From fb6ca63517a766601321040b682e71e4104703e3 Mon Sep 17 00:00:00 2001 From: neoexpert Date: Fri, 10 Jul 2020 09:20:45 +0200 Subject: [PATCH 1/6] port to maven --- src/api/java/org/jpsx/api/CPUControl.java | 60 - src/api/java/org/jpsx/api/CPUListener.java | 35 - .../api/InvalidConfigurationException.java | 29 - .../core/ContinueExecutionException.java | 39 - .../core/ImmediateBreakoutException.java | 4 - .../core/ReturnFromExceptionException.java | 27 - .../core/addressspace/AddressSpace.java | 145 - .../addressspace/AddressSpaceListener.java | 23 - .../addressspace/AddressSpaceRegistrar.java | 43 - .../core/addressspace/MemoryMapped.java | 30 - .../core/addressspace/Pollable.java | 23 - .../components/core/cpu/CPUInstruction.java | 137 - .../core/cpu/CPUInstructionDisassembler.java | 39 - .../core/cpu/CompilationContext.java | 123 - .../core/cpu/InstructionProvider.java | 23 - .../core/cpu/InstructionRegistrar.java | 29 - .../components/core/cpu/NativeCompiler.java | 124 - .../core/cpu/PollBlockListener.java | 40 - .../jpsx/api/components/core/cpu/R3000.java | 137 - .../org/jpsx/api/components/core/cpu/SCP.java | 55 - .../components/core/dma/DMAChannelOwner.java | 33 - .../components/core/dma/DMAController.java | 34 - .../components/core/irq/IRQController.java | 44 - .../api/components/core/irq/IRQOwner.java | 33 - .../api/components/core/scheduler/Quartz.java | 67 - .../core/scheduler/ScheduledAction.java | 33 - .../components/core/scheduler/Scheduler.java | 94 - .../components/hardware/cd/CDAudioSink.java | 42 - .../api/components/hardware/cd/CDDrive.java | 36 - .../api/components/hardware/cd/CDMedia.java | 43 - .../hardware/cd/MediaException.java | 29 - .../api/components/hardware/gpu/Display.java | 36 - .../hardware/gpu/DisplayManager.java | 97 - .../components/hardware/sio/SerialDevice.java | 29 - .../components/hardware/sio/SerialPort.java | 25 - .../java/org/jpsx/bootstrap/JPSXLauncher.java | 110 - .../org/jpsx/bootstrap/JPSXLauncher2.java | 126 - .../jpsx/bootstrap/JPSXMachineLifecycle.java | 29 - .../bootstrap/classloader/ClassGenerator.java | 29 - .../bootstrap/classloader/ClassModifier.java | 27 - .../classloader/JPSXClassLoader.java | 234 - .../configuration/ComponentDefinition.java | 44 - .../configuration/MachineDefinition.java | 66 - .../XMLMachineDefinitionParser.java | 213 - .../jpsx/bootstrap/connection/Connection.java | 105 - .../connection/MultipleConnection.java | 100 - .../connection/SimpleConnection.java | 93 - .../bootstrap/util/CollectionsFactory.java | 43 - .../components/hardware/gpu/LWJGLDisplay.java | 453 - .../org/jpsx/runtime/EmulationException.java | 29 - .../jpsx/runtime/FinalComponentSettings.java | 56 - .../runtime/FinalResolvedConnectionCache.java | 28 - .../java/org/jpsx/runtime/JPSXComponent.java | 79 - .../java/org/jpsx/runtime/JPSXMachine.java | 36 - .../org/jpsx/runtime/JPSXMachineImpl.java | 153 - .../org/jpsx/runtime/RuntimeConnections.java | 36 - .../jpsx/runtime/SingletonJPSXComponent.java | 45 - .../components/core/AddressSpaceImpl.java | 1786 ---- .../core/CoreComponentConnections.java | 53 - .../components/core/DMAChannelOwnerBase.java | 67 - .../components/core/DMAControllerImpl.java | 240 - .../components/core/DefaultQuartz.java | 73 - .../components/core/IRQControllerImpl.java | 144 - .../runtime/components/core/IRQOwnerBase.java | 61 - .../runtime/components/core/MTScheduler.java | 277 - .../runtime/components/core/R3000Impl.java | 1027 -- .../jpsx/runtime/components/core/SCPImpl.java | 449 - .../emulator/compiler/CodeUnit.java | 258 - .../compiler/CompilerClassLoader.java | 59 - .../emulator/compiler/Executable.java | 23 - .../emulator/compiler/FlowAnalyzer.java | 419 - .../emulator/compiler/MultiStageCompiler.java | 896 -- .../emulator/compiler/Stage1Generator.java | 1277 --- .../emulator/compiler/Stage2Generator.java | 1255 --- .../HardwareComponentConnections.java | 38 - .../components/hardware/bios/ImageBIOS.java | 82 - .../runtime/components/hardware/cd/CD.java | 1676 --- .../components/hardware/cd/XADecoder.java | 322 - .../hardware/counters/Counters.java | 362 - .../components/hardware/gpu/AWTDisplay.java | 339 - .../hardware/gpu/DefaultDisplayManager.java | 445 - .../runtime/components/hardware/gpu/GPU.java | 9260 ----------------- .../components/hardware/gpu/GPUGenerated.java | 5599 ---------- .../runtime/components/hardware/gte/GTE.java | 3585 ------- .../components/hardware/mdec/IDCT.java | 141 - .../components/hardware/mdec/MDEC.java | 459 - .../hardware/media/CueBinImageDrive.java | 259 - .../hardware/r3000/R3000InstructionSet.java | 2947 ------ .../hardware/sio/AWTKeyboardController.java | 105 - .../components/hardware/sio/BasicPad.java | 73 - .../runtime/components/hardware/sio/SIO0.java | 265 - .../hardware/sio/StandardController.java | 71 - .../components/hardware/spu/NullSPU.java | 289 - .../runtime/components/hardware/spu/SPU.java | 1287 --- .../core/DebugAddressSpaceImpl.java | 386 - .../emulator/console/Console.java | 419 - .../disassemblers/DisassemblerComponent.java | 55 - .../GTEInstructionDisassembler.java | 122 - .../R3000InstructionDisassembler.java | 289 - .../org/jpsx/runtime/util/ByteCodeUtil.java | 74 - .../java/org/jpsx/runtime/util/CDUtil.java | 78 - .../java/org/jpsx/runtime/util/ClassUtil.java | 30 - .../java/org/jpsx/runtime/util/MiscUtil.java | 64 - .../java/org/jpsx/runtime/util/Timing.java | 28 - 104 files changed, 41487 deletions(-) delete mode 100644 src/api/java/org/jpsx/api/CPUControl.java delete mode 100644 src/api/java/org/jpsx/api/CPUListener.java delete mode 100644 src/api/java/org/jpsx/api/InvalidConfigurationException.java delete mode 100644 src/api/java/org/jpsx/api/components/core/ContinueExecutionException.java delete mode 100644 src/api/java/org/jpsx/api/components/core/ImmediateBreakoutException.java delete mode 100644 src/api/java/org/jpsx/api/components/core/ReturnFromExceptionException.java delete mode 100644 src/api/java/org/jpsx/api/components/core/addressspace/AddressSpace.java delete mode 100644 src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java delete mode 100644 src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java delete mode 100644 src/api/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java delete mode 100644 src/api/java/org/jpsx/api/components/core/addressspace/Pollable.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/CPUInstruction.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/CompilationContext.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/InstructionProvider.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/NativeCompiler.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/PollBlockListener.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/R3000.java delete mode 100644 src/api/java/org/jpsx/api/components/core/cpu/SCP.java delete mode 100644 src/api/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java delete mode 100644 src/api/java/org/jpsx/api/components/core/dma/DMAController.java delete mode 100644 src/api/java/org/jpsx/api/components/core/irq/IRQController.java delete mode 100644 src/api/java/org/jpsx/api/components/core/irq/IRQOwner.java delete mode 100644 src/api/java/org/jpsx/api/components/core/scheduler/Quartz.java delete mode 100644 src/api/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java delete mode 100644 src/api/java/org/jpsx/api/components/core/scheduler/Scheduler.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/cd/CDDrive.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/cd/CDMedia.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/cd/MediaException.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/gpu/Display.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/sio/SerialDevice.java delete mode 100644 src/api/java/org/jpsx/api/components/hardware/sio/SerialPort.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher2.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassGenerator.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassModifier.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/configuration/MachineDefinition.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/connection/Connection.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/connection/MultipleConnection.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/connection/SimpleConnection.java delete mode 100644 src/bootstrap/java/org/jpsx/bootstrap/util/CollectionsFactory.java delete mode 100644 src/lwjgl/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java delete mode 100644 src/runtime/java/org/jpsx/runtime/EmulationException.java delete mode 100644 src/runtime/java/org/jpsx/runtime/FinalComponentSettings.java delete mode 100644 src/runtime/java/org/jpsx/runtime/FinalResolvedConnectionCache.java delete mode 100644 src/runtime/java/org/jpsx/runtime/JPSXComponent.java delete mode 100644 src/runtime/java/org/jpsx/runtime/JPSXMachine.java delete mode 100644 src/runtime/java/org/jpsx/runtime/JPSXMachineImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/RuntimeConnections.java delete mode 100644 src/runtime/java/org/jpsx/runtime/SingletonJPSXComponent.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/CoreComponentConnections.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/DMAControllerImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/DefaultQuartz.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/IRQControllerImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/IRQOwnerBase.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/MTScheduler.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/R3000Impl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/core/SCPImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Executable.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/cd/CD.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/counters/Counters.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPU.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/gte/GTE.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/sio/SIO0.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/sio/StandardController.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java delete mode 100644 src/runtime/java/org/jpsx/runtime/components/hardware/spu/SPU.java delete mode 100644 src/runtime/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java delete mode 100644 src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java delete mode 100644 src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java delete mode 100644 src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java delete mode 100644 src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java delete mode 100644 src/runtime/java/org/jpsx/runtime/util/ByteCodeUtil.java delete mode 100644 src/runtime/java/org/jpsx/runtime/util/CDUtil.java delete mode 100644 src/runtime/java/org/jpsx/runtime/util/ClassUtil.java delete mode 100644 src/runtime/java/org/jpsx/runtime/util/MiscUtil.java delete mode 100644 src/runtime/java/org/jpsx/runtime/util/Timing.java diff --git a/src/api/java/org/jpsx/api/CPUControl.java b/src/api/java/org/jpsx/api/CPUControl.java deleted file mode 100644 index 8a72745..0000000 --- a/src/api/java/org/jpsx/api/CPUControl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api; - -/** - * This interface is used to control (asynchronously) the thread which processes R3000 instructions - */ -public interface CPUControl { - /** - * Cause the CPU to run until a breakpoint is hit, or {@link #step()} or {@link #pause()} are called - */ - void go(); - - /** - * Execute one CPU instruction and then pause - */ - void step(); - - /** - * Stop executing CPU instructions, until {@link #go()} or {@link #step()} are called - */ - void pause(); - - /** - * Add a breakpoint at the specified address in the PSX address space - * - * @param address - */ - void addBreakpoint(int address); - - /** - * Remove a breakpoint at the specified address in the PSX address space - * - * @param address - */ - void removeBreakpoint(int address); - - /** - * Return all the currently defined breakpoint addresses - * - * @return - */ - int[] getBreakpoints(); -} diff --git a/src/api/java/org/jpsx/api/CPUListener.java b/src/api/java/org/jpsx/api/CPUListener.java deleted file mode 100644 index 388d9ce..0000000 --- a/src/api/java/org/jpsx/api/CPUListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api; - -/** - * Connection interface to be implemented by any component which cares when the CPU is paused or resumed in response - * to requests via the {@link CPUControl} interface. - */ -public interface CPUListener { - /** - * The CPU is starting to run again - */ - void cpuResumed(); - - /** - * The CPU has stopped running - */ - void cpuPaused(); -} diff --git a/src/api/java/org/jpsx/api/InvalidConfigurationException.java b/src/api/java/org/jpsx/api/InvalidConfigurationException.java deleted file mode 100644 index 33efc72..0000000 --- a/src/api/java/org/jpsx/api/InvalidConfigurationException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api; - -public class InvalidConfigurationException extends RuntimeException { - public InvalidConfigurationException(String message) { - super(message); - } - - public InvalidConfigurationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/api/java/org/jpsx/api/components/core/ContinueExecutionException.java b/src/api/java/org/jpsx/api/components/core/ContinueExecutionException.java deleted file mode 100644 index c944e7f..0000000 --- a/src/api/java/org/jpsx/api/components/core/ContinueExecutionException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core; - -public class ContinueExecutionException extends RuntimeException { - private boolean skipCurrentInstruction; - - // static members used since exception creation is costly, and we don't care about stack traces in this case - public static final ContinueExecutionException SKIP_CURRENT = new ContinueExecutionException(true); - public static final ContinueExecutionException DONT_SKIP_CURRENT = new ContinueExecutionException(false); - - public ContinueExecutionException() { - this(false); - } - - public ContinueExecutionException(boolean skipCurrentInstruction) { - this.skipCurrentInstruction = skipCurrentInstruction; - } - - public boolean skipCurrentInstruction() { - return skipCurrentInstruction; - } -} diff --git a/src/api/java/org/jpsx/api/components/core/ImmediateBreakoutException.java b/src/api/java/org/jpsx/api/components/core/ImmediateBreakoutException.java deleted file mode 100644 index a705aad..0000000 --- a/src/api/java/org/jpsx/api/components/core/ImmediateBreakoutException.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.jpsx.api.components.core; - -public class ImmediateBreakoutException extends RuntimeException { -} diff --git a/src/api/java/org/jpsx/api/components/core/ReturnFromExceptionException.java b/src/api/java/org/jpsx/api/components/core/ReturnFromExceptionException.java deleted file mode 100644 index 5a7ad5d..0000000 --- a/src/api/java/org/jpsx/api/components/core/ReturnFromExceptionException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core; - -public final class ReturnFromExceptionException extends RuntimeException { - // static singleton used since exception creation is costly, and we don't care about stack traces in this case - public static final ReturnFromExceptionException INSTANCE = new ReturnFromExceptionException(); - - private ReturnFromExceptionException() { - } -} diff --git a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpace.java b/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpace.java deleted file mode 100644 index 07970f7..0000000 --- a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpace.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.addressspace; - - -public interface AddressSpace { - // we use this when determining addresses as the offset from the prefix (top 16 bits)... - // this is because the 2M of ram should be repeated 4 times... since no other offsets are close to 2M big, this should be AOK - int OFFSET_MASK = 0x0f9fffff; - int RAM_AND = 0x5fffffff & OFFSET_MASK; // value to and main ram address with to make it map to array index*4 (or invalid) - - int SCRATCH_XOR = 0x1f800000; // value to xor scratch address with to make it map to array index*4 (or invalid) - int BIOS_XOR = 0xbfc00000; // value to xor bios address with to make it map to array index*4 (or invalid) - - int RAM_SIZE = 2 * 1024 * 1024; - - int SCRATCH_BASE = 0x1f800000; - int SCRATCH_SIZE = 0x1000; - int SCRATCH_END = SCRATCH_BASE + SCRATCH_SIZE; - - int PAR_BASE = 0x1f000000; - int PAR_SIZE = 0x10000; - int PAR_END = PAR_BASE + PAR_SIZE; - - int HW_BASE = 0x1f801000; - int HW_SIZE = 0x2000; - int HW_END = HW_BASE + HW_SIZE; - - int BIOS_BASE = 0xBFC00000; - int BIOS_SIZE = 0x80000; - int BIOS_END = BIOS_BASE + BIOS_SIZE; - - // Markers for the type of RAM access that an instruction at a particular addresses does - byte TAG_RAM = 0x01; - byte TAG_SCRATCH = 0x02; - byte TAG_HW = 0x04; - byte TAG_BIOS = 0x08; - byte TAG_PAR = 0x10; - byte TAG_POLL = 0x20; // polling detected at this address - byte TAG_RESERVED_FOR_COMPILER = 0x40; // our compiler happens to need a bit - byte TAG_RESERVED_FOR_COMPILER_2 = -0x80; // our compiler happens to need a bit - - public static class Util { - public static boolean isBIOS(int address) { - return address >= BIOS_BASE && address < BIOS_END; - } - } - - // read or write from RAM without any side effects (e.g. hardware IO) - int internalRead32(int address); - void internalWrite32(int address, int value); - - int read8(int address); - int read16(int address); - int read32(int address); - - void write8(int address, int value); - void write16(int address, int value); - void write32(int address, int value); - - /** - * Called by the SCP to enable/disable writing to RAM - * @param enable - */ - void enableMemoryWrite(boolean enable); - - byte getTag(int pc); - - void orTag(int pc, byte val); - - /** - * Return the array and index in a ResolveResult based on a given address - * @param address - * @param result the resolved address information or null if the address is not backed - */ - void resolve(int address, ResolveResult result); - - /** - * Return the array and index in a ResolveResult based on a given address, - * ensuring that both the address & address + size fall within the same memory - * region - * @param address base address - * @param size size in bytes - * @param write true if this is for write access, false for read - * @param result the resolved address information or null if the full address range is not backed - */ - void resolve(int address, int size, boolean write, ResolveResult result); - - /** - * todo we should allow the address space to return null here if it doesn't want to allow direct access - * @return the main RAM array to allow for direct access by other components - */ - int[] getMainRAM(); - - void tagAddressAccessWrite(int pc, int address); - - void tagAddressAccessRead8(int pc, int address); - - void tagAddressAccessRead16(int pc, int address); - - void tagAddressAccessRead32(int pc, int address); - - void tagClearPollCounters(); - - /** - * Private interface of static methods for use by compiler are on this class... this is not a full level - * abstraction, but makes it easier to replace the AddressSpaceImpl with a subclass - * - * This can return null if none is provided, though the MultiStageCompiler currently requires it - */ - public String getMainStaticInterfaceClassName(); - - - /** - * Private interface of static methods for use by compiler are on this class... this is not a full level - * abstraction, but makes it easier to replace the AddressSpaceImpl with a subclass - * - * This can return null if none is provided, though the MultiStageCompiler currently requires it - */ - public String getHardwareStaticInterfaceClassName(); - - static class ResolveResult { - public int address; // the original address - public int[] mem; - public int offset; - public int low2; - public byte tag; - } -} diff --git a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java b/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java deleted file mode 100644 index e7f946c..0000000 --- a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.addressspace; - -public interface AddressSpaceListener { - public void cacheCleared(); -} diff --git a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java b/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java deleted file mode 100644 index f6d19bb..0000000 --- a/src/api/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.addressspace; - -public interface AddressSpaceRegistrar { - void registerRead8Callback(int address, Class clazz, String methodName); - - void registerRead16Callback(int address, Class clazz, String methodName); - - void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead); - - void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead); - - void registerRead32Callback(int address, Class clazz, String methodName); - - void registerWrite8Callback(int address, Class clazz, String methodName); - - void registerWrite16Callback(int address, Class clazz, String methodName); - - void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite); - - void registerWrite32Callback(int address, Class clazz, String methodName); - - void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite); - - void registerPoll32Callback(int address, Pollable pollable); -} diff --git a/src/api/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java b/src/api/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java deleted file mode 100644 index d0542a3..0000000 --- a/src/api/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.addressspace; - -import org.jpsx.api.InvalidConfigurationException; - -public interface MemoryMapped { - /** - * Method invoked by the address space during initialization. - *

- * A memory mapped implementation should register its addresses with the address space at this time - */ - public void registerAddresses(AddressSpaceRegistrar registrar) throws InvalidConfigurationException; -} diff --git a/src/api/java/org/jpsx/api/components/core/addressspace/Pollable.java b/src/api/java/org/jpsx/api/components/core/addressspace/Pollable.java deleted file mode 100644 index 27b71df..0000000 --- a/src/api/java/org/jpsx/api/components/core/addressspace/Pollable.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.addressspace; - -public interface Pollable { - public void poll(int address, int size); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/CPUInstruction.java b/src/api/java/org/jpsx/api/components/core/cpu/CPUInstruction.java deleted file mode 100644 index 12c7cd3..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/CPUInstruction.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -import org.apache.bcel.generic.InstructionList; - -public class CPUInstruction { - /** - * any branch instruction - */ - public static final int FLAG_BRANCH = 0x00000001; - - /** - * for use if a branch is always taken - */ - public static final int FLAG_UNCONDITIONAL = 0x00000002; - /** - * for branch with an immediate relative offset - */ - public static final int FLAG_IMM_NEAR_TARGET = 0x00000004; - /** - * for branch with an immediate absolute offset - */ - public static final int FLAG_IMM_FAR_TARGET = 0x00000008; - /** - * for branch which links return address in R31 - */ - public static final int FLAG_LINK = 0x00000010; - - /** - * instruction is depdendent only on immediate value and input register values, - * and the only side effect (other than exception) is a register value change. - *

- * This is useful in compiler because if it can prove the input values are - * known at compile time, then it can invoke the {@link #simulate} method for the - * input to calculate the constant output. - */ - public static final int FLAG_SIMULATABLE = 0x00000020; - - /** - * what the instruction references - */ - public static final int FLAG_READS_RS = 0x00000100; - public static final int FLAG_READS_RT = 0x00000200; - public static final int FLAG_WRITES_RT = 0x00000400; - public static final int FLAG_WRITES_RD = 0x00000800; - - // all addresses are assumed to be of the form rs[offset] - public static final int FLAG_MEM8 = 0x00002000; - public static final int FLAG_MEM16 = 0x00004000; - public static final int FLAG_MEM32 = 0x00008000; - public static final int FLAG_MEM = (FLAG_MEM8 | FLAG_MEM16 | FLAG_MEM32); - - // the instruction may make use of reg_pc - public static final int FLAG_REFERENCES_PC = 0x00010000; - - // implicitly references pc - public static final int FLAG_MAY_RESTORE_INTERPRETER_STATE = 0x00020000; - public static final int FLAG_MAY_SIGNAL_EXCEPTION = FLAG_MAY_RESTORE_INTERPRETER_STATE; - - /** - * Applies only to the interpreted version of the function - */ - public static final int FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE = 0x00040000; - - public static final int FLAG_INVALID = 0x00080000; - - public static final int BRANCH_NEVER = 0; - public static final int BRANCH_SOMETIMES = 1; - public static final int BRANCH_ALWAYS = 2; - - private String name; - private Class interpreterClass; - private int flags; - - public CPUInstruction(String name, Class interpreterClass, int exceptions, int flags) { - this.interpreterClass = interpreterClass; - this.name = name; - this.flags = flags; - } - - public int getBranchType(int ci) { - if (0 != (flags & FLAG_BRANCH)) { - if (0 != (flags & FLAG_UNCONDITIONAL)) - return BRANCH_ALWAYS; - return BRANCH_SOMETIMES; - } - return BRANCH_NEVER; - } - - public String getName() { - return name; - } - - public Class getInterpreterClass() { - return interpreterClass; - } - - public CPUInstruction subDecode(int ci) { - return this; - } - - public final int getFlags() { - return flags; - } - - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - if (0 != (getFlags() & FLAG_BRANCH)) { - throw new IllegalStateException("default compiler may not be used for branch instructions: " + getName()); - } - context.emitInterpretedInstruction(il, ci, interpreterClass.getName(), getInterpretMethodName()); - } - - public boolean simulate(int ci, int[] regs) { - return false; - } - - public String getInterpretMethodName() { - return "interpret_" + getName(); - } -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java b/src/api/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java deleted file mode 100644 index 1ec55c1..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -/** - * A {@link CPUInstructionDisassembler} is capable of providing a string representation of an opcode - * for the purpose of disassembly. - *

- * Implementors of this interface are registered during registration via - * {@link InstructionRegistrar#setInstructionDisassembler(String,CPUInstructionDisassembler)} - */ -public interface CPUInstructionDisassembler { - /** - * Return a string representing the disassembly of the instruction - * - * @param inst the decoded instruction resulting from the opcode ci - * @param address the address of the instruction - * @param ci the 32 bit opcode itself - * @return The String representation of the opcode, which by convention has the instruction name padded with spaces to 8 characters - * followed by any instruction arguments - */ - public String disassemble(CPUInstruction inst, int address, int ci); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/CompilationContext.java b/src/api/java/org/jpsx/api/components/core/cpu/CompilationContext.java deleted file mode 100644 index cc91226..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/CompilationContext.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.InstructionHandle; -import org.apache.bcel.generic.InstructionList; - -public interface CompilationContext { - public int getRegValue(int reg); - - public int getConstantRegs(); - - public int getWritesReg(); - - public int getReadsReg(); - - public ConstantPoolGen getConstantPoolGen(); - - /** - * Call into the interpreted version of the instruction... the compiler - * is responsible for any marshalling of state on entry/exit - */ - public void emitInterpretedInstruction(InstructionList il, int ci, String clazz, String method); - - public void emitGetReg(InstructionList il, int reg); - - public void emitSetReg(InstructionList il, int reg); - - public void emitCall(InstructionList il, int address, int expectedReturnAddress); - - public void emitCall(InstructionList il, int expectedReturnAddress); - - public void emitJump(InstructionList il); - - public void emitJump(InstructionList il, int address); - - /** - * read from specified constant address - */ - public void emitReadMem8(InstructionList il, int address, boolean signed); - - /** - * read from base reg + offset - */ - public void emitReadMem8(InstructionList il, int reg, int offset); - - /** - * read from specified constant address - */ - public void emitReadMem16(InstructionList il, int address, boolean signed); - - /** - * read from base reg + offset - */ - public void emitReadMem16(InstructionList il, int reg, int offset); - - /** - * read from specified constant address - */ - public void emitReadMem32(InstructionList il, int address, boolean forceAlign); - - /** - * read from base reg + offset - */ - public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign); - - /** - * write value from stack(0) to specified address - */ - public void emitWriteMem8(InstructionList il, int address, InstructionList valueList); - - /** - * write value from stack(0) to base reg + offset - */ - public void emitWriteMem8(InstructionList il, int reg, int offset); - - /** - * write value from stack(0) to specified address - */ - public void emitWriteMem16(InstructionList il, int address, InstructionList valueList); - - /** - * write value from stack(0) to base reg + offset - */ - public void emitWriteMem16(InstructionList il, int reg, int offset); - - /** - * write value from stack(0) from address at stack(1) - */ - public void emitWriteMem32(InstructionList il, int address, InstructionList valueList, boolean forceAlign); - - /** - * write value from stack(0) to base reg + offset - */ - public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList valueList, boolean forceAlign); - - /** - * if this is a branch instruction then this would be the instructions - * for the delay slot - */ - public void emitDelaySlot(InstructionList il); - - public int getTempLocal(int index); - - public InstructionHandle getBranchTarget(int address); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/InstructionProvider.java b/src/api/java/org/jpsx/api/components/core/cpu/InstructionProvider.java deleted file mode 100644 index f410f5e..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/InstructionProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -public interface InstructionProvider { - public void addInstructions(InstructionRegistrar registrar); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java b/src/api/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java deleted file mode 100644 index 56ba2b9..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -public interface InstructionRegistrar { - void setInstruction(int index, CPUInstruction inst); - - void setSPECIALInstruction(int index, CPUInstruction inst); - - void setREGIMMInstruction(int index, CPUInstruction inst); - - void setInstructionDisassembler(String name, CPUInstructionDisassembler disassembler); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/NativeCompiler.java b/src/api/java/org/jpsx/api/components/core/cpu/NativeCompiler.java deleted file mode 100644 index e062ece..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/NativeCompiler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -/** - * Interface to be implemented by an instruction compiler. - *

- * The compiler's job is to provide faster execution of R3000 - * code than is possible by simple instruction by instruction - * interpretation. - */ -public interface NativeCompiler { - - /** - * Enter compiler. - *

- * This method is called by the interpreter for every interpreted JAL after - * the delay slot has been executed. i.e. address is the JAL target. - *

- * The compiler may continue execution from this point if it is able to, or - * may ask the interpreter to continue (e.g. if methods are only compiled - * after a certain number of invocations). - *

- * The compiler, if it decides to enter compiled code, should continue executing - * until the corresponding JR to the specified return address (i.e. return), or may throw a ContinueExecutionException - * if it needs to return execution flow to the interpreter for any other reason. - *

- * Note, that the compiler may be entered recursively; e.g. once for main - * execution flow, and then later for an interrupt. - * - * @return true - if the compiler execute code until the "return" - * false - if the compiler did not execute any code. - * @throws org.jpsx.api.components.core.ContinueExecutionException - * if the compiler wishes the interpeter to take over execution - */ - public boolean jumpAndLink(int address, int returnAddress); - - /** - * Method called whenever the R3000 instruction cache is flushed. - * The compiler should assume that any instructions in RAM may have been - * modified - */ - public void clearCache(); - - /** - * Determine if a thrown exception is OK; some compilers - * may allow some exceptions e.g. NullPointerException in the normal - * course of operation, and use them when they occur to update compiled - * code. - *

- * Note the compiler is responsible for restoring the interpreter state - * in either case. Note this method is also called for ReturnFromExceptionException - * and ContinueExecutionException to allow the compiler to know - * that it has been "thrown out of". - * - * @return true - * if the exception was handled by the compiler, and emulation should continue - * in the interpreter - */ - public boolean exceptionInCompiler(Throwable t); - - /** - * Called by the JPSX system if there is some interruption to execution - * flow that requires the compiler to return control temporarily. This - * includes, but is not limited to R3000 interrupts. - *

- * The compiler should call {@link R3000#compilerInterrupted} from the execution - * thread as soon as possible. - *

- * Note, this method is generally not called from the execution thread, though - * in some circumstances it could be. - *

- * On return from {@link R3000#compilerInterrupted}, the compiler should be - * aware that clearCache() or restoreInterpreterState() may - * have been called in the meanwhile. - */ - public void interrupt(); - - /** - * Adds a breakpoint at the specified address. - *

- * If the compiler is able to handle breakpoints it should make sure that the - * execution returns to the interpreter on or before this address - *

- * The simplest implementation of this function would be to perform no - * compiled execution while there are any breakpoints set. - * - * @return true - * if the compiler will be able to handle the breakpoint - */ - public boolean addBreakpoint(int address); - - /** - * Removes the breakpoint from the specified address - */ - public void removeBreakpoint(int address); - - /** - * If the compiler is keeping any local copies - * of registers etc., it should restore them - * in response to this call - */ - public void restoreInterpreterState(); - - public int getReg(int index); - - public void setReg(int index, int value ); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/PollBlockListener.java b/src/api/java/org/jpsx/api/components/core/cpu/PollBlockListener.java deleted file mode 100644 index 48aafbb..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/PollBlockListener.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -/** - * Connection interface to be implemented by components which care about poll-blocking - *

- * Much PSX code sits in busy-wait loops waiting for memory or memory mapped IO locations to change - * as a result of asynchronous (perhaps interrupt) events.

- *

- * The core implementation of the emulator detects these busy waits, and will block instead on a java - * monitor.

- *

- * This interface enables components to know when this is about to happen - */ -public interface PollBlockListener { - /** - * Called when CPU busy-wait has been detected, and the processing thread is about to block. - *

- * This is an indication that the CPU is effectively idle, and the component may choose - * to perform some idle processing. - */ - public void aboutToBlock(); -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/R3000.java b/src/api/java/org/jpsx/api/components/core/cpu/R3000.java deleted file mode 100644 index 001f0f4..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/R3000.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -// not thread safe - -public interface R3000 { - /** - * Stack pointer register constant - */ - public static final int R_SP = 29; - /** - * Return address register constant - */ - public static final int R_RETADDR = 31; - - // todo document what it means to read a compiler reg here - int getReg(int index); - - // todo document what it means to write a compiler register here - void setReg(int index, int value); - - int getPC(); - - int getLO(); - - int getHI(); - - void setPC(int pc); - - void setLO(int lo); - - void setHI(int hi); - - /** - * Decode the given opcode into an emulator instruction instance - * - * @param ci the 32 bit opcode - * @return the instruction specified by the opcode. If the op code is invalid, then this method returns an instruction representing - * and invalid instruction rather than null - */ - CPUInstruction decodeInstruction(int ci); - - String disassemble(int address, int ci); - - /** - * Determine if the current thread is the CPU execution thread - */ - boolean isExecutionThread(); - - /** - * Called from a non execution thread to request a controlled break out to the main interpreter/control loop as soon as possible. - * Currently used for R3000 interrupt handling and external pausing/stepping etc. of the CPU - */ - void requestBreakout(); - - /** - * Called from the execution thread to request an immediate return to the interpreter/control loop - this can be called mid - * instruction and may have undesirable side effects (i.e. half executed instruction) - */ - void immediateBreakout(); - - void restoreInterpreterState(); - - void interpreterBranch(int relativeToDelay); - - void interpreterJump(int relativeToDelay, int target); - - void interpreterJumpAndLink(int relativeToDelay, int target, int retAddr); - - // todo should this be elsewhere - void compilerInterrupted(); - - /** - * @return the array of registers used during intrepreted code execution; this value should be immutable - */ - int[] getInterpreterRegs(); - - CPUInstruction getInvalidInstruction(); - - void executeFromPC(); - - public static class Util { - - public static int bits_rs(final int ci) { - return (ci >> 21) & 0x1f; - } - - public static int bits_rt(final int ci) { - return (ci >> 16) & 0x1f; - } - - public static int bits_rd(final int ci) { - return (ci >> 11) & 0x1f; - } - - public static int bits_sa(final int ci) { - return (ci >> 6) & 0x1f; - } - - public static int bits25_6(int x) { - return (x >> 6) & 0xfffff; - } - - public static int sign_extend(int x) { - return ((x) << 16) >> 16; - } - - public static int signed_branch_delta(int x) { - return sign_extend(x) << 2; - } - - public static int lo(int x) { - return x & 0xffff; - } - - public static long longFromUnsigned(int x) { - return ((long) x) & 0xffffffffL; - } - } -} diff --git a/src/api/java/org/jpsx/api/components/core/cpu/SCP.java b/src/api/java/org/jpsx/api/components/core/cpu/SCP.java deleted file mode 100644 index ffdf553..0000000 --- a/src/api/java/org/jpsx/api/components/core/cpu/SCP.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.cpu; - -/** - * Interface used by the core implementation to represent actions against the System Control Processor - */ -public interface SCP { - // R3000 exception constants; very few are actually used currently - public static final int EXCEPT_INTERRUPT = 0; - public static final int EXCEPT_TLB_MOD = 1; - public static final int EXCEPT_TLB_REFILL_L = 2; - public static final int EXCEPT_TLB_REFILL_S = 3; - public static final int EXCEPT_ADDRESS_ERROR_L = 4; // load/fetch - public static final int EXCEPT_ADDRESS_ERROR_S = 5; // store - public static final int EXCEPT_BUS_ERROR_I = 6; - public static final int EXCEPT_BUS_ERROR_D = 7; - public static final int EXCEPT_SYSCALL = 8; - public static final int EXCEPT_BREAKPOINT = 9; - public static final int EXCEPT_RESERVED_INSTRUCTION = 10; - public static final int EXCEPT_COPROCESSOR_UNUSABLE = 11; - public static final int EXCEPT_OVERFLOW = 12; - - void setInterruptLine(int line, boolean raised); - - void signalReservedInstructionException(); - - void signalIntegerOverflowException(); - - void signalBreakException(); - - void signalSyscallException(); - - void signalInterruptException(); - - boolean shouldInterrupt(); - - int currentExceptionType(); -} diff --git a/src/api/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java b/src/api/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java deleted file mode 100644 index f54ca27..0000000 --- a/src/api/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.dma; - -public interface DMAChannelOwner { - void register(DMAController controller); - - String getName(); - - int getDMAChannel(); - - void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl); - - void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl); - - void cancelDMATransfer(int ctrl); -} diff --git a/src/api/java/org/jpsx/api/components/core/dma/DMAController.java b/src/api/java/org/jpsx/api/components/core/dma/DMAController.java deleted file mode 100644 index d8cd206..0000000 --- a/src/api/java/org/jpsx/api/components/core/dma/DMAController.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.dma; - -public interface DMAController { - public static final int DMA_MDEC_IN = 0; - public static final int DMA_MDEC_OUT = 1; - public static final int DMA_GPU = 2; - public static final int DMA_CD = 3; - public static final int DMA_SPU = 4; - public static final int DMA_GPU_OTC = 6; - - void registerDMAChannel(DMAChannelOwner owner); - - void dmaChannelTransferComplete(DMAChannelOwner owner); - - void dmaChannelTransferComplete(DMAChannelOwner owner, boolean interrupt); -} diff --git a/src/api/java/org/jpsx/api/components/core/irq/IRQController.java b/src/api/java/org/jpsx/api/components/core/irq/IRQController.java deleted file mode 100644 index c45f694..0000000 --- a/src/api/java/org/jpsx/api/components/core/irq/IRQController.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.irq; - -public interface IRQController { - public static final int IRQ_VSYNC = 0; - public static final int IRQ_GPU = 1; - public static final int IRQ_CD = 2; - public static final int IRQ_DMA = 3; - public static final int IRQ_COUNTER0 = 4; - public static final int IRQ_COUNTER1 = 5; - public static final int IRQ_COUNTER2 = 6; - public static final int IRQ_SIO0 = 7; - - void registerIRQOwner(IRQOwner owner); - - // todo allow queue (some sort of delivery guarantee) - /** - * Raise the given IRQ; this method may be called from any thread - * - * @param irq - */ - void raiseIRQ(int irq); - - int getIRQRequest(); - - int getIRQMask(); -} diff --git a/src/api/java/org/jpsx/api/components/core/irq/IRQOwner.java b/src/api/java/org/jpsx/api/components/core/irq/IRQOwner.java deleted file mode 100644 index 8622e8d..0000000 --- a/src/api/java/org/jpsx/api/components/core/irq/IRQOwner.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.irq; - -public interface IRQOwner { - void register(IRQController controller); - - int getIRQ(); - - String getName(); - - void raiseIRQ(); - - void irqSet(); - - void irqCleared(); -} diff --git a/src/api/java/org/jpsx/api/components/core/scheduler/Quartz.java b/src/api/java/org/jpsx/api/components/core/scheduler/Quartz.java deleted file mode 100644 index 88ecf1f..0000000 --- a/src/api/java/org/jpsx/api/components/core/scheduler/Quartz.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.scheduler; - -/** - * A Quartz implementation is the basic internal timer in the JPSX system. - *

- * Different implementations of {@link Quartz} may provide different granularities. Various - * components may require a certain level of granularity. - *

- * This interface contains the methods not only to determine the current time value, but for components - * to negociate granularity, or indeed fail if the {@link Quartz} implementation does not provide - * the required level of granularity - */ -public interface Quartz { - /** - * The number of nano-seconds in a second - */ - public static final long SEC = 1000000000L; - /** - * The number of nano-seconds in a millisecond - */ - public static final long MSEC = 1000000L; - - /** - * Return the current value a nano counter which counts up from 0 when the machine starts (but only while the machine is not paused) - *

- * The resolution of the nano time is undefined but should be accurate +/- the value from {@link #bestGranularity()} - */ - long nanoTime(); - - /** - * @return the estimated granularity of the time changes visible via {@link #nanoTime()} - */ - long bestGranularity(); - - /** - * Return the current value an arbitrary nano counter which counts up from 0 when the machine starts (but only while the machine is not paused) - *

- * The resolution of the nano time should be accurate +/- the specified granularity value. - *

- * The passed granularity should be greater than the value returned from {@link #bestGranularity()} - *

- * This method is provided for use by callers who don't need insane accuracy in the hope that the implementation - * may be able to perform a less costly time calculation - * - * @param granularity the requested granularity - * @throw IllegalArgumentException if the granularity is more fine than that returned by {@link #bestGranularity} - */ - long nanoTime(long granularity); -} diff --git a/src/api/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java b/src/api/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java deleted file mode 100644 index 206c8af..0000000 --- a/src/api/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.scheduler; - -/** - * A scheduled action is registered with the {@link Scheduler} to be called back at a certain time. - *

- * All implementors must be thread-safe since they may be called from any thread, and potentially simultaneously - * if the action is registered multiple times. - */ -public interface ScheduledAction { - /** - * @param currentTime - * @return the next time the action should be scheduled or 0 for no automatic re-scheduling - */ - long run(long currentTime); -} diff --git a/src/api/java/org/jpsx/api/components/core/scheduler/Scheduler.java b/src/api/java/org/jpsx/api/components/core/scheduler/Scheduler.java deleted file mode 100644 index 9cf59ab..0000000 --- a/src/api/java/org/jpsx/api/components/core/scheduler/Scheduler.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.core.scheduler; - -/** - * The scheduler is responsible for all real-time activity within the emulator. - *

- * The actual implementation is also largely responsible for the threading mechanism used. - */ -public interface Scheduler { - /** - * Schedule an action to happen as soon as possible after the given time. For this method the definition of - * "as soon as possible" is left to the scheduler, but in general most implementations will probably not try - * to schedule with greater than 1ms accuracy.

- *

- * No actual guarantees are made about how soon the action will be called, so periodic actions that would - * usually re-schedule themselves every X nanoseconds, may want to take corrective action if they detect - * that they have been called back mutch later than expected.

- *

- * Actions scheduled in this manner should be as concise as possible, as all actions may be performed on - * one thread, and indeed that thread may be (but won't necessarily be) the R3000 cpu thread.

- *

- * If an action has long lasting work that it needs to do, it should delegate it to other worker threads - * - * @param time the time in nanoseconds since the start of the machine - * @param action the action to perform - */ - void schedule(long time, ScheduledAction action); - - /** - * Schedule an action to happen as soon as possible after the given time. For this method the definition of - * "as soon as possible" is specified to mean try your very best to get to schedule the action to happen between time - * and time+jitter. This method is useful if you really require very high frequency callbacks.

- *

- * No actual guarantees are made about how soon the action will be called, so periodic actions that would - * usually re-schedule themselves every X nanoseconds, may want to take corrective action if they detect - * that they have been called back mutch later than expected.

- *

- * Actions scheduled in this manner should be as concise as possible, as all actions may be performed on - * one thread, and indeed that thread may be (but won't necessarily be) the R3000 cpu thread.

- *

- * If an action has long lasting work that it needs to do, it should delegate it to other worker threads - * - * @param time the time in nanoseconds since the start of the machine - * @param action the action to perform - */ - void schedule(long time, long jitter, ScheduledAction action); - - /** - * Checks whether the action is currently scheduled. - *

- * In this case scheduled means is either scheduled one or more times in the future, or is currently being called - * back. This latter behavior is useful if you have a repeating action which is only used some of the time. - * External (to the action) code can safely use this method to determine whether it should schedule the action itself - * - * @param action - * @return - */ - boolean isScheduled(ScheduledAction action); - - /** - * This method may be called by the cpu thread to indicate that it is in a busy-wait loop, and has no further useful - * work to do in the absence of some external force. - *

- * This method will not return until {@link #cpuThreadNotify} is called. - *

- * Note this is not necessarily implemented via Java monitors since the particular scheduler may be single-threaded - */ - void cpuThreadWait(); - - /** - * This method is generally called by {@link ScheduledAction scheduled actions} to indicate that they have performed - * some work which may potentially un-block the R3000 cpu thread. - *

- * Note this is not necessarily implemented via Java monitors since the particular scheduler may be single-threaded - */ - void cpuThreadNotify(); -} diff --git a/src/api/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java b/src/api/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java deleted file mode 100644 index 067f8a5..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.cd; - -public interface CDAudioSink { - - public int getCDAudioLatency(); - - public void setCDAudioRate(int hz); - - public void newCDAudio(); - - /** - * Handle CD Audio data in 2 channel 16 bit sigend little endian format - * - * @param data - * @return true if the audio is now playing - */ - public boolean cdAudioData(byte[] data, int offset, int length); - - public void setExternalCDAudioVolumeLeft(int vol); - - public void setExternalCDAudioVolumeRight(int vol); - - public boolean isCDAudible(); -} diff --git a/src/api/java/org/jpsx/api/components/hardware/cd/CDDrive.java b/src/api/java/org/jpsx/api/components/hardware/cd/CDDrive.java deleted file mode 100644 index 3bd60ce..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/cd/CDDrive.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.cd; - -/** - * TODO FIX THIS UP - also, read game title etc. media changed etc... - * support "changing" media - */ -public interface CDDrive { - - /** - * @return the current CDMedia or null if there is none present - */ - public CDMedia getCurrentMedia(); - - public void refreshMedia(); - - public boolean isDriveOpen(); -} - diff --git a/src/api/java/org/jpsx/api/components/hardware/cd/CDMedia.java b/src/api/java/org/jpsx/api/components/hardware/cd/CDMedia.java deleted file mode 100644 index 4550b22..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/cd/CDMedia.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.cd; - -public interface CDMedia { - public enum TrackType { - UNKNOWN, MODE2_2352, AUDIO - } - - int getFirstTrack(); - - int getLastTrack(); - - int getTrackMSF(int track); - - TrackType getTrackType(int track); - - void readSector(int sectorNumber, byte[] buffer) throws MediaException; - - /** - * @param num - * @param buffer - * @throws MediaException - * @deprecated just for use of old cd stuff - */ - void readSector(int num, int[] buffer) throws MediaException; -} diff --git a/src/api/java/org/jpsx/api/components/hardware/cd/MediaException.java b/src/api/java/org/jpsx/api/components/hardware/cd/MediaException.java deleted file mode 100644 index b305c9a..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/cd/MediaException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.cd; - -public class MediaException extends Exception { - public MediaException(String message) { - super(message); - } - - public MediaException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/api/java/org/jpsx/api/components/hardware/gpu/Display.java b/src/api/java/org/jpsx/api/components/hardware/gpu/Display.java deleted file mode 100644 index 293d69e..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/gpu/Display.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.gpu; - -public interface Display { - /** - * initialize the display - */ - public void initDisplay(); - - // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU); - public int[] acquireDisplayBuffer(); - - public void releaseDisplayBuffer(); - - public void refresh(); -} - - - diff --git a/src/api/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java b/src/api/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java deleted file mode 100644 index 415b5a1..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.gpu; - -public interface DisplayManager { - boolean getInterlaceField(); - - boolean getNTSC(); - - boolean getInterlaced(); - - boolean getDoubleY(); - - boolean getRGB24(); - - boolean getBlanked(); - - int getDefaultPixelWidth(); - - int getDefaultPixelHeight(); - - int getPixelWidth(); - - int getPixelHeight(); - - int getXOrigin(); - - int getYOrigin(); - - int getLeftMarginPixels(); - - int getRightMarginPixels(); - - int getTopMarginPixels(); - - int getBottomMarginPixels(); - - void preAsync(); - - // called if a vsync has passed to make sure display is updated if necessary - // (e.g. drawing to display)... usually this does nothing, because setOrigin - // updates display if necessary - void vsync(); - - void setOrigin(int x, int y); - - void toggleInterlaceField();// mark a display area as changed... if it intersects the next - - // display region, then we will get an update at the next vsync, or - // display origin change - void dirtyRectangle(int x, int y, int w, int h); - - void setPixelDivider(int divider); - - void setNTSC(boolean NTSC); - - void setInterlaced(boolean interlaced); - - void setDoubleY(boolean doubleY); - - void setRGB24(boolean rgb24); - - void setBlanked(boolean blanked); - - void setHorizontalTiming(int hStart, int hEnd); - - void setVerticalTiming(int vStart, int vEnd); - - int getDefaultTimingWidth(); - - int getDefaultTimingHeight(); - - int getLeftMargin(); - - int getRightMargin(); - - int getTopMargin(); - - int getBottomMargin(); - -} diff --git a/src/api/java/org/jpsx/api/components/hardware/sio/SerialDevice.java b/src/api/java/org/jpsx/api/components/hardware/sio/SerialDevice.java deleted file mode 100644 index 6bbf590..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/sio/SerialDevice.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.sio; - -public interface SerialDevice { - public void prepareForTransfer(); - - public void send(int data); - - public int receive(); - - public String getDescription(); -} diff --git a/src/api/java/org/jpsx/api/components/hardware/sio/SerialPort.java b/src/api/java/org/jpsx/api/components/hardware/sio/SerialPort.java deleted file mode 100644 index ade6403..0000000 --- a/src/api/java/org/jpsx/api/components/hardware/sio/SerialPort.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.api.components.hardware.sio; - -public interface SerialPort { - public void connect(SerialDevice device); - - public void disconnect(); -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher.java b/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher.java deleted file mode 100644 index c48d789..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ - -package org.jpsx.bootstrap; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.classloader.JPSXClassLoader; -import org.jpsx.bootstrap.configuration.MachineDefinition; -import org.jpsx.bootstrap.configuration.XMLMachineDefinitionParser; -import org.w3c.dom.Element; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.File; -import java.io.IOException; -import java.util.Properties; -import java.awt.*; - -/** - * Bootstrap for JPSX - simply runs JPSXSystem in the {@link JPSXClassLoader} - */ -public class JPSXLauncher { - private static final Logger log = Logger.getLogger("Bootstrap"); - - public static void main(String args[]) { - // fix for Mac OSX which requires that we load AWT in the main classloader - new Frame(); - - Properties vars = new Properties(); - String configFile = "jpsx.xml"; - String machineId = "default"; - String log4jFile = "log4j.properties"; - - for (int i = 0; i < args.length; i++) { - if (args[i].equals("-config")) { - if (i == args.length - 1) { - usage(); - return; - } - configFile = args[++i]; - } else if (args[i].equals("-log")) { - if (i == args.length - 1) { - usage(); - return; - } - log4jFile = args[++i]; - } else if (args[i].indexOf("=") > 0) { - int split = args[i].indexOf("="); - vars.put(args[i].substring(0, split), args[i].substring(split + 1)); - } else if (args[i].equals("-?")) { - usage(); - return; - } else { - machineId = args[i]; - } - } - - // init log4j - PropertyConfigurator.configure(log4jFile); - - log.info("configFile=" + configFile + " machineId=" + machineId); - Element config; - try { - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - config = builder.parse(new File(configFile)).getDocumentElement(); - } catch (IOException e) { - log.error("Cannot open/read '" + configFile + "'", e); - return; - } catch (Exception e) { - log.error("Cannot parse '" + configFile + "'", e); - return; - } - - try { - MachineDefinition machineDefinition = new XMLMachineDefinitionParser().parse(config, machineId, vars); - JPSXMachineLifecycle machine = JPSXClassLoader.newMachine(JPSXLauncher.class.getClassLoader(), machineDefinition); - machine.start(); - } catch (InvalidConfigurationException e) { - log.error("Invalid Configuration", e); - } catch (Throwable t) { - log.error("Unexpected error", t); - } - } - - private static void usage() { - System.err.println("Usage: JPSXLauncher (-log ) (-config ) () (var=value)*\n" + - " The default log4j properties file is 'log4j.properties'\n" + - " The default xmlfile is 'jpsx.xml'\n" + - " The default machineId is 'default'"); - } -} - diff --git a/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher2.java b/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher2.java deleted file mode 100644 index 086ccc2..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/JPSXLauncher2.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.classloader.JPSXClassLoader; -import org.jpsx.bootstrap.configuration.MachineDefinition; -import org.jpsx.bootstrap.configuration.XMLMachineDefinitionParser; -import org.w3c.dom.Element; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.File; -import java.io.IOException; -import java.util.Properties; -import java.awt.*; - -/** - * Bootstrap for JPSX - simply runs JPSXSystem in the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} - * - * THIS IS JUST A TEST CLASS THAT RUNS 3 GAMES IN THE SAME VM ON MY MACHINE!!! - */ -public class JPSXLauncher2 { - private static final Logger log = Logger.getLogger("Bootstrap"); - - private static final String JPSX_MACHINE_CLASS = "org.jpsx.runtime.JPSXMachineImpl"; - - public static void main(String args[]) { - // fix for Mac OSX which requires that we load AWT in the main classloader - new Frame(); - - final Properties vars = new Properties(); - String configFile = "jpsx.xml"; - String machineId = "default"; - String log4jFile = "log4j.properties"; - - for (int i = 0; i < args.length; i++) { - if (args[i].equals("-config")) { - if (i == args.length - 1) { - usage(); - return; - } - configFile = args[++i]; - } else if (args[i].equals("-log")) { - if (i == args.length - 1) { - usage(); - return; - } - log4jFile = args[++i]; - } else if (args[i].indexOf("=") > 0) { - int split = args[i].indexOf("="); - vars.put(args[i].substring(0, split), args[i].substring(split + 1)); - } else if (args[i].equals("-?")) { - usage(); - return; - } else { - machineId = args[i]; - } - } - - // init log4j - PropertyConfigurator.configure(log4jFile); - - new Thread(new Runnable() { - public void run() { - runMachine("jpsx.xml", "abe", new Properties(vars)); - } - }).start(); - new Thread(new Runnable() { - public void run() { - runMachine("jpsx.xml", "bandicoot", new Properties(vars)); - } - }).start(); - runMachine(configFile, machineId, vars); - } - - private static void runMachine(String configFile, String machineId, Properties vars) { - log.info("configFile=" + configFile + " machineId=" + machineId); - Element config; - try { - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - config = builder.parse(new File(configFile)).getDocumentElement(); - } catch (IOException e) { - log.error("Cannot open/read '" + configFile + "'", e); - return; - } catch (Exception e) { - log.error("Cannot parse '" + configFile + "'", e); - return; - } - - try { - MachineDefinition machineDefinition = new XMLMachineDefinitionParser().parse(config, machineId, vars); - JPSXMachineLifecycle machine = JPSXClassLoader.newMachine(JPSXLauncher2.class.getClassLoader(), machineDefinition); - machine.start(); - } catch (InvalidConfigurationException e) { - log.error("Invalid Configuration", e); - } catch (Throwable t) { - log.error("Unexpected error", t); - } - } - - private static void usage() { - System.err.println("Usage: JPSXLauncher (-log ) (-config ) () (var=value)*\n" + - " The default log4j properties file is 'log4j.properties'\n" + - " The default xmlfile is 'jpsx.xml'\n" + - " The default machineId is 'default'"); - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java b/src/bootstrap/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java deleted file mode 100644 index 0f6965f..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap; - -import org.jpsx.bootstrap.configuration.MachineDefinition; - -public interface JPSXMachineLifecycle { - void initialize(MachineDefinition definition); - - void start(); - - void close(); -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassGenerator.java b/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassGenerator.java deleted file mode 100644 index f562850..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassGenerator.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.classloader; - -import org.apache.bcel.generic.ClassGen; - -public interface ClassGenerator { - /** - * @param classname the full classname of the class being loaded - * @return the generated version of the class - */ - public ClassGen generateClass(String classname ); -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassModifier.java b/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassModifier.java deleted file mode 100644 index f30094d..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/classloader/ClassModifier.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.classloader; - -import org.apache.bcel.generic.ClassGen; - -public interface ClassModifier { - /** - */ - public ClassGen modifyClass(String classname, ClassGen original); -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java b/src/bootstrap/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java deleted file mode 100644 index 3443b47..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.classloader; - -import org.apache.bcel.classfile.ClassParser; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.InstructionList; -import org.apache.bcel.generic.MethodGen; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.JPSXMachineLifecycle; -import org.jpsx.bootstrap.configuration.MachineDefinition; -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -// todo wildcard rather than prefix for modifiers/generators -// todo class modifiers - -/** - * JPSX ClassLoader. - *

- * This classloader relies on its parent classloader - * for getting RAW .class data, but it does not - * necessarily follow the Java 2 delegation model. - *

- * All JPSX classes should be loaded by this classloader - * instead, since they mey reference other classes which - * need to be modified before they are defined. - *

- * Therefore this class recognizes certain package - * prefixes as JPSX classes - */ - -// todo multiple modifiers? - -public class JPSXClassLoader extends ClassLoader { - public static final boolean dumpClasses = false; - private static final String JPSX_MACHINE_CLASS = "org.jpsx.runtime.JPSXMachineImpl"; - - private static int BUFFER_SIZE = 8192; - - private final List generatorClassnamePrefixes = CollectionsFactory.newArrayList(); - private final List generators = CollectionsFactory.newArrayList(); - private final List modifierClassnamePrefixes = CollectionsFactory.newArrayList(); - private final List modifiers = CollectionsFactory.newArrayList(); - private final Set jpsxClassnamePrefixes = CollectionsFactory.newHashSet(); - - private JPSXClassLoader(ClassLoader parent, MachineDefinition machineDefinition) { - super(parent); - jpsxClassnamePrefixes.add("org.jpsx.runtime"); - jpsxClassnamePrefixes.addAll(machineDefinition.getClassNamePrefixes()); - } - - public static JPSXMachineLifecycle newMachine(ClassLoader parent, MachineDefinition machineDefinition) throws InvalidConfigurationException { - // each machine needs to have its own classloader instance - JPSXClassLoader loader = new JPSXClassLoader(parent, machineDefinition); - try { - Class clazz = Class.forName(JPSX_MACHINE_CLASS, true, loader); - JPSXMachineLifecycle rc = (JPSXMachineLifecycle) clazz.newInstance(); - rc.initialize(machineDefinition); - return rc; - } catch (Exception e) { - throw new InvalidConfigurationException("Failed to create machine instance", e); - } - } - - private int prefixIndex(Collection prefixes, String name) { - int i = 0; - for (String prefix : prefixes) { - if (name.startsWith(prefix)) { - return i; - } - i++; - } - return -1; - } - - public static void registerClassGenerator(String classnamePrefix, ClassGenerator generator) { - JPSXClassLoader instance = getLoaderInstance(generator); - instance.generatorClassnamePrefixes.add(classnamePrefix); - instance.generators.add(generator); - } - - public static void registerClassModifier(String classnamePrefix, ClassModifier modifier) { - JPSXClassLoader instance = getLoaderInstance(modifier); - instance.modifierClassnamePrefixes.add(classnamePrefix); - instance.modifiers.add(modifier); - } - - private static JPSXClassLoader getLoaderInstance(Object obj) { - ClassLoader loader = obj.getClass().getClassLoader(); - assert (loader != null && (loader instanceof JPSXClassLoader)) : obj + " was not loaded by JPSXClassLoader"; - return (JPSXClassLoader) loader; - } - - /** - * Utility method to define a class from a stream of bytes - * - * @param stream the stream containing the binary class data - * @param classname the class name for the class - */ - private Class getClassFromStream(InputStream stream, String classname) - throws IOException { - // read the stream into a byte array - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[BUFFER_SIZE]; - - int bytesRead; - while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) { - baos.write(buffer, 0, bytesRead); - } - - byte[] classData = baos.toByteArray(); - - // and define the class using our protection domain - return defineClass(classname, classData, 0, classData.length, null); - } - - /** - * Override of the standard loadClass method to allow for class duplication. - *

- * If we determine that we should duplicate the class then we do so, otherwise - * we invoke the superclasses' method which follows the standard Java 2 delegation - * model - */ - public synchronized Class loadClass(final String name, boolean resolve) throws ClassNotFoundException { - // make sure we haven't defined it already - Class c = findLoadedClass(name); - if (c == null) { - //System.out.println( "load class "+name); - if (-1 != prefixIndex(jpsxClassnamePrefixes, name)) { - c = makeClass(name); - } else { - return super.loadClass(name, resolve); - } - } - if (resolve) { - resolveClass(c); - } - return c; - } - - private Class makeClass(final String name) throws ClassNotFoundException { - ClassGen cgen = null; - - int genIndex = prefixIndex(generatorClassnamePrefixes, name); - int modIndex = prefixIndex(modifierClassnamePrefixes, name); - - if (genIndex != -1) { - //System.out.println("generating class "+name); - cgen = generators.get(genIndex).generateClass(name); - } else { - // make the ClassGen from the raw data from our parent loader - final URL url = getResource(getClassFilename(name)); - if (url != null) { - try { - InputStream stream = url.openStream(); - if (modIndex == -1) { - //System.out.println("copying parent class "+name); - return getClassFromStream(stream, name); - } else { - cgen = new ClassGen((new ClassParser(stream, getClassFilename(name))).parse()); - } - } catch (IOException e) { - // will cause a class not found exception later - } - } - } - if (cgen != null && modIndex != -1) { - //System.out.println("modifying class "+name); - // modify the class if needed - cgen = modifiers.get(modIndex).modifyClass(name, cgen); - } - - if (cgen == null) { - throw new ClassNotFoundException(name); - } - - JavaClass jclass = cgen.getJavaClass(); - - if (dumpClasses) { - try { - jclass.dump("modified_" + name + ".class"); - } catch (IOException e) { - } - } - - byte[] classData = jclass.getBytes(); - return defineClass(name, classData, 0, classData.length, null); - } - - public static MethodGen emptyMethod(ClassGen cgen, Method m) { - MethodGen mg = new MethodGen(m, cgen.getClassName(), cgen.getConstantPool()); - return new MethodGen(mg.getAccessFlags(), - mg.getReturnType(), - mg.getArgumentTypes(), - mg.getArgumentNames(), - mg.getName(), - mg.getClassName(), - new InstructionList(), - mg.getConstantPool()); - } - - /** - * Utility method to convert class name to filename - */ - public static String getClassFilename(String classname) { - return classname.replace('.', '/') + ".class"; - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java b/src/bootstrap/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java deleted file mode 100644 index 03f0caf..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.configuration; - -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.util.Map; - -public class ComponentDefinition { - private final String className; - private final Map properties = CollectionsFactory.newHashMap(); - - public ComponentDefinition(String className) { - this.className = className; - } - - public void setProperty(String property, String value) { - properties.put(property, value); - } - - public String getClassName() { - return className; - } - - public Map getProperties() { - return properties; - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/configuration/MachineDefinition.java b/src/bootstrap/java/org/jpsx/bootstrap/configuration/MachineDefinition.java deleted file mode 100644 index 52b8683..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/configuration/MachineDefinition.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.configuration; - -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.util.Collections; -import java.util.List; - -/** - * A machine definition is just the in memory representation of the ordered - * list of component that make up the machine. - * - * Each component is described by a {@link ComponentDefinition}

- * - * An instance of this class is the raw input used by the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} to construct a new machine, - * however instances of this class may be built from another source (e.g. {@link XMLMachineDefinitionParser})

- * - * In addition to defining the components, the machine definition also includes the class name prefixes that the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} - * should consider to be part of machine runtime. All runtime classes should be loaded by the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} instead of the - * usual class loader, such that code modification/generation and multiple machine instances work correctly. - */ -public class MachineDefinition { - private final List components = CollectionsFactory.newArrayList(); - private final List classNamePrefixes = CollectionsFactory.newArrayList(); - - public void addComponent(ComponentDefinition definition) { - components.add(definition); - } - - public void removeComponent(ComponentDefinition definition) { - components.remove(definition); - } - - public List getComponents() { - return Collections.unmodifiableList(components); - } - - /** - * Add a class prefix to the list of prefixes of classes which are part of the machine runtime - * @param classPrefix A string which is compared with fully qualified classname, so "com.fo" would be a prefix match "com.foo.Foo" - */ - public void addClassPrefix(String classPrefix) { - classNamePrefixes.add(classPrefix); - } - - public List getClassNamePrefixes() { - return Collections.unmodifiableList(classNamePrefixes); - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java b/src/bootstrap/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java deleted file mode 100644 index 1271d63..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.configuration; - -import org.apache.log4j.Logger; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; -import java.util.Map; -import java.util.Properties; - -public class XMLMachineDefinitionParser { - public static final String CATEGORY = "XML-Config"; - private static Logger log = Logger.getLogger(CATEGORY); - - public static final String ROOT_ELEMENT = "jpsx"; - public static final String MACHINE_ELEMENT = "machine"; - public static final String MACHINE_ID_ATTRIBUTE = "id"; - public static final String COMPONENT_ELEMENT = "component"; - public static final String COMPONENT_ID_ATTRIBUTE = "id"; - public static final String COMPONENT_CLASS_NAME_ATTRIBUTE = "classname"; - public static final String COMPONENT_SET_ELEMENT = "components"; - public static final String COMPONENT_SET_ID_ATTRIBUTE = "id"; - public static final String INCLUDE_ELEMENT = "include"; - public static final String INCLUDE_REF_ID_ATTRIBUTE = "refid"; - public static final String VAR_ELEMENT = "var"; - public static final String VAR_NAME_ATTRIBUTE = "name"; - public static final String VAR_VALUE_ATTRIBUTE = "value"; - public static final String PROPERTY_ELEMENT = "property"; - public static final String PROPERTY_NAME_ATTRIBUTE = "name"; - public static final String PROPERTY_VALUE_ATTRIBUTE = "value"; - - private Properties vars; - /** - * Map from id to component for those components which have ids. - */ - private Map componentsById; - private XPath xPath = XPathFactory.newInstance().newXPath(); - private Element rootElement; - - public MachineDefinition parse(Element element, String machineId, Properties vars) throws InvalidConfigurationException { - MachineDefinition rc = new MachineDefinition(); - - componentsById = CollectionsFactory.newHashMap(); - rootElement = getUniqueElement(element, "/" + ROOT_ELEMENT, "root element"); - this.vars = vars; - - Element machineElement = getUniqueElement(rootElement, MACHINE_ELEMENT + "[@" + MACHINE_ID_ATTRIBUTE + "='" + machineId + "']", "machine with id " + machineId); - parseComponents(rc, machineElement); - return rc; - } - - private void parseComponents(MachineDefinition machine, Element containerElement) { - NodeList nodes = containerElement.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - if (node instanceof Element) { - Element element = (Element) nodes.item(i); - if (element.getTagName().equals(COMPONENT_ELEMENT)) { - parseComponentElement(machine, element); - } else if (element.getTagName().equals(INCLUDE_ELEMENT)) { - String id = element.getAttribute(INCLUDE_REF_ID_ATTRIBUTE); - id = resolveVariables(id); - Element refElement = getUniqueElement( - rootElement, - COMPONENT_ELEMENT + "[@" + COMPONENT_ID_ATTRIBUTE + "='" + id + "']|" + COMPONENT_SET_ELEMENT + "[@" + COMPONENT_SET_ID_ATTRIBUTE + "='" + id + "']", - "referenced component/nodes with id " + id); - if (refElement.getTagName().equals(COMPONENT_ELEMENT)) { - parseComponentElement(machine, refElement); - } else { - parseComponents(machine, refElement); - } - } else if (element.getTagName().equals(VAR_ELEMENT)) { - String name = element.getAttribute(VAR_NAME_ATTRIBUTE); - String value = element.getAttribute(VAR_VALUE_ATTRIBUTE); - if (!name.equals("")) { - value = resolveVariables(value); - if (value.equals("")) vars.remove(name); - else vars.setProperty(name, value); - } - } else { - throw new InvalidConfigurationException("Unexpected element " + element.getTagName()); - } - } - } - } - - private void parseComponentElement(MachineDefinition machine, Element componentElement) { - String id = componentElement.hasAttribute(COMPONENT_ID_ATTRIBUTE) ? componentElement.getAttribute(COMPONENT_ID_ATTRIBUTE) : null; - String className = componentElement.getAttribute(COMPONENT_CLASS_NAME_ATTRIBUTE); - - if (className.equals("")) { - throw new InvalidConfigurationException("Machine has component (id=" + id + ") with no className"); - } - - ComponentDefinition component = addComponent(machine, id, componentElement.getAttribute(COMPONENT_CLASS_NAME_ATTRIBUTE)); - parseConfiguration(component, componentElement); - } - - /** - * Handle xml configuration for this component; note this should not have actual - * side effects other than recording the information. This method is called before init - *

- * This implementation looks for <property name="" value=""/> elements and adds - * them to the properties collection. - *

- * Subclasses may override this method to parse other configuration data - * - * @param element - */ - private void parseConfiguration(ComponentDefinition component, Element element) { - NodeList nodes = element.getElementsByTagName(PROPERTY_ELEMENT); - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - if (node instanceof Element) { - Element prop = (Element) node; - if (prop.hasAttribute(PROPERTY_NAME_ATTRIBUTE) && prop.hasAttribute(PROPERTY_VALUE_ATTRIBUTE)) { - String value = prop.getAttribute(PROPERTY_VALUE_ATTRIBUTE); - value = resolveVariables(value); - if (!value.equals("")) { - component.setProperty(prop.getAttribute(PROPERTY_NAME_ATTRIBUTE), value); - } - } - } - } - } - - private Element getUniqueElement(Element context, String path, String description) { - NodeList nodes; - try { - nodes = (NodeList) xPath.evaluate(path, context, XPathConstants.NODESET); - } catch (XPathExpressionException e) { - throw new InvalidConfigurationException("XPath Error", e); - } - if (nodes == null || nodes.getLength() == 0) { - throw new InvalidConfigurationException("Can't find: " + description); - } - if (nodes.getLength() > 1) { - log.warn("More than one node found for search: " + description); - } - Node node = nodes.item(0); - if (node instanceof Element) { - return (Element) node; - } - throw new InvalidConfigurationException("Match for '" + description + "' was not an element"); - } - - /** - * Substitutes any variables for ${varname} - * - * @param value - * @return the value with substitutions - */ - public String resolveVariables(String value) { - StringBuffer rc = new StringBuffer(); - int index = 0; - while (true) { - int start = value.indexOf("${", index); - if (start == -1) break; - int end = value.indexOf("}"); - if (end == -1) break; - rc.append(value.substring(index, start)); - String varName = value.substring(start + 2, end); - String varValue = getVariable(varName); - if (varValue != null) { - rc.append(varValue); - } - index = end + 1; - } - rc.append(value.substring(index)); - return rc.toString(); - } - - public String getVariable(String name) { - return vars.getProperty(name); - } - - public ComponentDefinition addComponent(MachineDefinition machine, String id, String className) { - ComponentDefinition component = new ComponentDefinition(className); - if (id != null) { - ComponentDefinition oldComponent = componentsById.get(id); - if (oldComponent != null) { - machine.removeComponent(oldComponent); - } - componentsById.put(id, component); - } - machine.addComponent(component); - return component; - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/connection/Connection.java b/src/bootstrap/java/org/jpsx/bootstrap/connection/Connection.java deleted file mode 100644 index 141ffec..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/connection/Connection.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ - -package org.jpsx.bootstrap.connection; - -import java.util.Set; - -/** - * A {@link Connection} object provides a lazily bound connection to one or more implementors - * of a particular interface.

- *

- * The client need not know who is on the other end of the connection; indeed the various sub-classes - * of this class, provide the targets with a way to register themselves with a particular connection instance.

- *

- * The client can connect to the target(s) by calling {@link #resolve()} which returns an implementor of the parametric type which - * connects to the targets. Note this method will throw an exception if there is no target.

- *

- * The connection also has an open flag, which indicates whether the connection is open. It should not be - * possible to use the the connection (via the implementation returned by {@link #resolve()}) when the connection is closed;

- *

- * The typical usage pattern is to place an instance of a connection in a class shareable by two otherwise unrelated classes, - * and one class can become the target of the connection and the other the client without them knowing anything else about eachother. - * - * @see SimpleConnection - * @see MultipleConnection - */ -public abstract class Connection { - /** - * Flags for the base connection or any well known subclasses - */ - enum Flags { - InitiallyClosed - } - - /** - * Name of the connection - */ - private final String name; - - /** - * the callbable interface implemented by the return value from {@link #resolve()} - */ - private final Class ifc; - - /** - * true if the connection accepts calls - */ - private boolean open; - - // the dispatcher object should cease to work if the connection is closed - // this is useful for connections which should only work at certain phases. - - protected Connection(String name, Class ifc, Set flags) { - if (!ifc.isInterface()) throw new IllegalArgumentException("ifc must be an interface"); - this.name = name; - this.ifc = ifc; - if (!flags.contains(Flags.InitiallyClosed)) { - open = true; - } - } - - public String getName() { - return name; - } - - public final Class getInterface() { - return ifc; - } - - public final boolean isOpen() { - return open; - } - - public void open() { - assert !this.open; - this.open = true; - } - - // todo flag for only open once - public void close() { - assert open; - open = false; - } - - /** - * Return an implementation which acts as the conduit between caller and callees - */ - public abstract I resolve(); -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/connection/MultipleConnection.java b/src/bootstrap/java/org/jpsx/bootstrap/connection/MultipleConnection.java deleted file mode 100644 index 3fd313d..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/connection/MultipleConnection.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.connection; - -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.EnumSet; -import java.util.List; - -/** - * A {@link MultipleConnection} represent a connection to zero or more instances of a particular interface. - *

- * The typical usage pattern might be for a set of listeners:
- *

- * The listeners register themselves with the connection, and the client calls {@link #resolve} on the connection - * to get an implementation of the interface which takes care of looping over all the instances and calling each - * registered listener.

- *

- * This saves the listeners from needing to know about the caller, and the caller having to keep track of lists of listeners - */ -public class MultipleConnection extends Connection { - private final List targets = CollectionsFactory.newArrayList(); - private I dispatcher; - - public MultipleConnection(String name, Class ifc, EnumSet flags) { - super(name, ifc, flags); - } - - public void add(I target) { - assert target != null; - // todo remove this restriction, allowing for rewrite of dispatcher - assert dispatcher == null : "targets may not be added to connection after first dispatch"; - targets.add(target); - } - - public void remove(I target) { - // todo remove this restriction, allowing for rewrite of dispatcher - assert dispatcher == null : "targets may not be removed from connection after first dispatch"; - targets.remove(target); - } - - @Override - public I resolve() { - if (dispatcher == null) { - if (targets.size() == 1) { - dispatcher = targets.iterator().next(); - } else { - // todo optimize this if compiled by factorying a better class than the reflection proxy - dispatcher = getInterface().cast(Proxy.newProxyInstance(getInterface().getClassLoader(), new Class[]{getInterface()}, new Invoker())); - } - } - return dispatcher; - } - - protected class Invoker implements InvocationHandler { - protected Invoker() { - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - assert isOpen() : "Connection " + getName() + " used when not open"; - Object rc = null; - for (I target : targets) { - try { - rc = method.invoke(target, args); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - return rc; - } - } - - public static MultipleConnection create(String name, Class clazz) { - return new MultipleConnection(name, clazz, EnumSet.noneOf(Flags.class)); - } - - public static MultipleConnection create(String name, Class clazz, EnumSet flags) { - return new MultipleConnection(name, clazz, flags); - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/connection/SimpleConnection.java b/src/bootstrap/java/org/jpsx/bootstrap/connection/SimpleConnection.java deleted file mode 100644 index bb2ca62..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/connection/SimpleConnection.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.connection; - -import org.jpsx.api.InvalidConfigurationException; - -import java.util.EnumSet; - -/** - * A {@link SimpleConnection} represents a connection to a single implementation object. - *

- * This type of connection is useful when you want to be able to connect to a single implementor - * of an interface for some specific purpose but do not want to be involved with the details of - * how that implementor is constructed.

- *

- * The target of the connection calls {@link #set} to initialize itself as the target.

- *

- * The client of the connection calls {@link #resolve} as usual, or {@link #peek} if it wants null returned - * if there is no implementor. - */ -public class SimpleConnection extends Connection { - private I target; - - public SimpleConnection(String name, Class ifc, EnumSet flags) { - super(name, ifc, flags); - } - - public void set(I target) { - if (target == null) - throw new IllegalStateException("Target for simple connection '" + getName() + "' may only be set once"); - this.target = target; - } - - /** - * @return the target of the connection - * @throws org.jpsx.api.InvalidConfigurationException - * if there is no target - */ - @Override - public I resolve() { - if (target == null) - throw new InvalidConfigurationException("No target for simple connection '" + getName() + "'"); - // todo we need a wrapper which respects open/closed - return target; - } - - /** - * @return the target of the connection or null if there is one - */ - public I peek() { - return target; - } - - /** - * Factory method to create a simple connection to an implementor of a given interface - * - * @param name - * @param clazz - * @return - */ - public static SimpleConnection create(String name, Class clazz) { - return new SimpleConnection(name, clazz, EnumSet.noneOf(Flags.class)); - } - - /** - * Factory method to create a simple connection to an implementor of a given interface, specifying - * specifc flags for the connection - * - * @param name - * @param clazz - * @param flags - * @return - */ - public static SimpleConnection create(String name, Class clazz, EnumSet flags) { - return new SimpleConnection(name, clazz, flags); - } -} diff --git a/src/bootstrap/java/org/jpsx/bootstrap/util/CollectionsFactory.java b/src/bootstrap/java/org/jpsx/bootstrap/util/CollectionsFactory.java deleted file mode 100644 index 483be61..0000000 --- a/src/bootstrap/java/org/jpsx/bootstrap/util/CollectionsFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.bootstrap.util; - -import java.util.*; - -public class CollectionsFactory { - public static Set newHashSet() { - return new HashSet(); - } - - public static Map newHashMap() { - return new HashMap(); - } - - public static Map newTreeMap() { - return new TreeMap(); - } - - public static Map newTreeMap(Comparator c) { - return new TreeMap(c); - } - - public static List newArrayList() { - return new ArrayList(); - } -} diff --git a/src/lwjgl/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java b/src/lwjgl/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java deleted file mode 100644 index 34ede3e..0000000 --- a/src/lwjgl/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.gpu; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.hardware.gpu.Display; -import org.jpsx.api.components.hardware.gpu.DisplayManager; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.util.Timing; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.lwjgl.opengl.AWTGLCanvas; -import org.lwjgl.opengl.PixelFormat; -import org.lwjgl.opengl.GL11; -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL12.*; -import org.lwjgl.LWJGLException; - -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.image.*; -import java.nio.IntBuffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public class LWJGLDisplay extends JPSXComponent implements Display, KeyListener { - private static final Logger log = Logger.getLogger("Display"); - - public static final String LOCATION_X_PROPERTY = "x"; - public static final String LOCATION_Y_PROPERTY = "y"; - - private Frame frame; - - // todo see if this is slower - we can fix GPU instead! - private static final int SOURCE_FORMAT = GL_BGRA; - /** - * Used to transfer pixel data to open GL texture - */ - private ByteBuffer transferBuffer; - /** - * Used to copy int[] pixel data into the transfer buffer - */ - private IntBuffer transferBufferIntView; - - private boolean blanked = true; - - private int[] ram; // video RAM - private DisplayManager displayManager; - - /** - * protected data - */ - private int sourceWidth, sourceHeight; // the size of the source to be stretched to be displayed - - private boolean showBlitTime; - private boolean antiAlias; - - private boolean displayVRAM; - - private boolean funkyfudge; - - private int MAX_X = 960; - private int MAX_Y = 512; - - private final int xres[] = new int[]{320, 640, 800, 960, 1024, 1280}; - private final int yres[] = new int[]{256, 512, 600, 768, 768, 1024}; - - private static final int BLIT_TIME_COUNT = 100; - private long blitTimeTotal; - private int blitTimeCount; - private long refreshTimeTotal; - private int refreshTimeCount; -// private boolean noStretch; - private int textureHandle; - - private AWTGLCanvas canvas; - int resindex = 1; - - - public LWJGLDisplay() { - super("JPSX LWJGL AWT Display"); - } - - @Override - public void init() { - super.init(); - HardwareComponentConnections.DISPLAY.set(this); - RuntimeConnections.KEY_LISTENERS.add(this); - transferBuffer = ByteBuffer.allocateDirect(4*1024*512+1); // todo check + 1, we may need to be one off for BGRA, but we should - // just force the GPU to render in the correct format - // don't want any conversions going on - transferBuffer.order(ByteOrder.nativeOrder()); - transferBufferIntView = transferBuffer.asIntBuffer(); - - showBlitTime = Boolean.valueOf(getProperty("showBlitTime","true")); - antiAlias = Boolean.valueOf(getProperty("antiAlias","true")); -// noStretch = Boolean.valueOf(getProperty("noStretch","false")); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - displayManager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); - } - - public static IntBuffer allocInts(int howmany) { - return ByteBuffer.allocateDirect(howmany * 4).order(ByteOrder.nativeOrder()).asIntBuffer(); - } - - public void initDisplay() { - - // todo, make a new initialization state for this - frame = new Frame("JPSX"); - - try { - canvas = new AWTGLCanvas(new PixelFormat()) { - protected void initGL() { - IntBuffer textureHandleB = allocInts(1); - GL11.glGenTextures(textureHandleB); - textureHandle = textureHandleB.get(0); - // 'select' the new texture by it's handle - GL11.glDisable(GL_LIGHTING); - GL11.glDisable(GL_DEPTH_TEST); - GL11.glEnable(GL_TEXTURE_2D); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureHandle); - // set texture parameters - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, antiAlias?GL11.GL_LINEAR:GL11.GL_NEAREST); //GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); //GL11.GL_NEAREST); - - // Create the texture from pixels - GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 1024, 512, 0, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); - } - - protected void paintGL() { - stretchBlit(); - try { - swapBuffers(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - }; - - frame.setLayout(new LayoutManager() { - public void addLayoutComponent(String name, Component comp) { - } - - public void removeLayoutComponent(Component comp) { - } - - public Dimension preferredLayoutSize(Container parent) { - Insets insets = parent.getInsets(); - Dimension dim = getContentSize(); - dim.width += insets.left + insets.right; - dim.height += insets.top + insets.bottom; - return dim; - } - - public Dimension minimumLayoutSize(Container parent) { - return preferredLayoutSize(parent); - } - - public void layoutContainer(Container parent) { - Dimension dim = getContentSize(); - Insets insets = parent.getInsets(); - for(Component component : parent.getComponents()) { - component.setBounds(insets.left, insets.top, dim.width, dim.height); - } - } - }); - frame.add(canvas); - canvas.repaint(); - } catch (LWJGLException e) { - throw new InvalidConfigurationException("Failed to initialize lwjgl", e); - } -// DirectColorModel model = new DirectColorModel( 24, 0x0000ff, 0x00ff00, 0xff0000); - DirectColorModel model = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); - WritableRaster raster = model.createCompatibleWritableRaster(1024, 513); - DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); - ram = db.getData(); - int w = getIntProperty(LOCATION_X_PROPERTY, -1); - int h = getIntProperty(LOCATION_Y_PROPERTY, -1); - if (w != -1 && h != -1) frame.setLocation(w, h); - frame.setResizable(false); - frame.show(); - sizeframe(); - canvas.addKeyListener(RuntimeConnections.KEY_LISTENERS.resolve()); - frame.addWindowListener(new Closer()); - frame.addComponentListener(new ComponentAdapter() { - public void componentResized(ComponentEvent e) { - frame.doLayout(); - } - }); - } - - protected void sizeframe() { - if (displayVRAM) - frame.setSize(new Dimension(1024 + frame.getInsets().left + frame.getInsets().right, 512 + frame.getInsets().top + frame.getInsets().bottom)); - else - frame.setSize(new Dimension(xres[resindex] + frame.getInsets().left + frame.getInsets().right, yres[resindex] + frame.getInsets().top + frame.getInsets().bottom)); - } - - // todo cache these - protected Dimension getContentSize() { - if (displayVRAM) - return new Dimension(1024, 512); - else - return new Dimension(xres[resindex], yres[resindex]); - } - - protected void switchsize() { - resindex++; - if (resindex == xres.length) resindex = 0; - sizeframe(); - } - - // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU). - public int[] acquireDisplayBuffer() { - return ram; - } - - public void releaseDisplayBuffer() { - } - - /** - * needs to protect drawing state - */ - private Object stateLock = new Object(); - - protected void stretchBlit() { - int l = frame.getInsets().left; - int t = frame.getInsets().top; - long timeBasis = 0; - if (showBlitTime) { - timeBasis = Timing.nanos(); - } - // todo don't recreate - Dimension dim = getContentSize(); - GL11.glViewport(0,0,dim.width, dim.height); - GL11.glMatrixMode(GL_PROJECTION); - GL11.glLoadIdentity(); - GL11.glOrtho(0,dim.width,0,dim.height,-1,1); - GL11.glMatrixMode(GL_MODELVIEW); - GL11.glLoadIdentity(); - // todo sync on that too - if (displayVRAM) { - synchronized (stateLock) { - GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 1024, 512, 0, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); - } - GL11.glBegin(GL_QUADS); - GL11.glTexCoord2f(0f,1f); - GL11.glVertex2f(0f,0f); - GL11.glTexCoord2f(1f,1f); - GL11.glVertex2f(1024f,0f); - GL11.glTexCoord2f(1f,0f); - GL11.glVertex2f(1024f,512f); - GL11.glTexCoord2f(0f,0f); - GL11.glVertex2f(0f,512f); - GL11.glEnd(); - } else { - if (blanked) { - GL11.glClear(GL_COLOR_BUFFER_BIT); - } else { - float tw, th; - synchronized (stateLock) { - GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, sourceWidth, sourceHeight, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); - // todo coords are wrong because of blanking - refactor along with other stuff - tw = sourceWidth/1024f; - th = sourceHeight/512f; - } - GL11.glBegin(GL_QUADS); - GL11.glTexCoord2f(0f,0f); - GL11.glVertex2f(0f,0f); - GL11.glTexCoord2f(tw,0f); - GL11.glVertex2f(dim.width,0f); - GL11.glTexCoord2f(tw,th); - GL11.glVertex2f(dim.width,dim.height); - GL11.glTexCoord2f(0f,th); - GL11.glVertex2f(0f,dim.height); - GL11.glEnd(); -// g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], -// 0, 0, sourceWidth, sourceHeight, null); - - } -// if (volatileImage != null && !volatileImage.contentsLost()) { -// if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); -// if (noStretch) { -// g.drawImage(volatileImage, l, t, l + sourceWidth, t + sourceHeight, -// 0, 0, sourceWidth, sourceHeight, null); -// } else { -// g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], -// 0, 0, sourceWidth, sourceHeight, null); -// } -// } - } - if (showBlitTime) { - blitTimeTotal += Timing.nanos()-timeBasis; - if (BLIT_TIME_COUNT == ++blitTimeCount) { - String refreshString = ""; - if (refreshTimeCount!=0) { - refreshString = " refresh="+((refreshTimeTotal/(refreshTimeCount*100000))/10.0)+"ms"; - refreshTimeTotal = refreshTimeCount = 0; - } - double blitTimeMSRounded = (blitTimeTotal/(BLIT_TIME_COUNT*100000))/10.0; - frame.setTitle("JPSX lwjgl - " + ((blitTimeMSRounded >= 1) ? "!SLOW! blit=" : "blit=") + blitTimeMSRounded + "ms" + refreshString); - blitTimeCount = 0; - blitTimeTotal = 0; - } - } - } - - // todo fix sync - public void refresh() { - boolean rgb24 = displayManager.getRGB24(); - if (funkyfudge) { - GPU.setVRAMFormat(!rgb24); - funkyfudge = false; - } - GPU.setVRAMFormat(rgb24); - // for now we use default display size - long timeBasis = 0; - if (showBlitTime) { - timeBasis = Timing.nanos(); - } - synchronized (stateLock) { - if (displayManager.getBlanked()) { - blanked = true; - } else { - blanked = false; - if (displayVRAM) { - // copy all of vram - transferBufferIntView.clear(); - transferBufferIntView.put(ram, 0, 1024*512); - transferBufferIntView.flip(); - } else { - sourceWidth = displayManager.getDefaultPixelWidth(); - if (rgb24) sourceWidth = (sourceWidth * 3) / 2; - sourceHeight = displayManager.getDefaultPixelHeight(); - int marginLeft = displayManager.getLeftMarginPixels(); - if (rgb24) marginLeft = (marginLeft * 3) / 2; - int marginTop = displayManager.getTopMarginPixels(); - int pixelWidth = displayManager.getPixelWidth(); - if (rgb24) pixelWidth = (pixelWidth * 3) / 2; - int pixelHeight = displayManager.getPixelHeight(); - int marginRight = sourceWidth - pixelWidth - marginLeft; - int marginBottom = sourceHeight - pixelHeight - marginTop; - if (pixelWidth > 0 && pixelHeight > 0) { - transferBufferIntView.clear(); - // from left-right and bottom to top, we copy the pixels into our transfer buffer - int offset = displayManager.getXOrigin() + (displayManager.getYOrigin() + pixelHeight - 1) * 1024; - for(int i=0; i 0) { -// // fill left -// g2.fillRect(0, 0, marginLeft, sourceHeight); -// } -// if (marginRight > 0) { -// // fill left -// g2.fillRect(sourceWidth - marginRight, 0, marginRight, sourceHeight); -// } -// if (marginTop > 0) { -// // fill top -// g2.fillRect(0, 0, sourceWidth, marginTop); -// } -// if (marginBottom > 0) { -// // fill top -// g2.fillRect(0, sourceHeight - marginBottom, sourceWidth, marginBottom); -// } - } - } - } - if (showBlitTime) { - refreshTimeTotal += Timing.nanos()-timeBasis; - refreshTimeCount++; - } - canvas.repaint(); - //stretchBlit(graphics); - } - - public void keyTyped(KeyEvent e) { - } - - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_F12) { - switchsize(); - } - if (e.getKeyCode() == KeyEvent.VK_F11) { - refresh(); - } - if (e.getKeyCode() == KeyEvent.VK_F10) { - funkyfudge = true; - } - if (e.getKeyCode() == KeyEvent.VK_F9) { - displayVRAM = !displayVRAM; - sizeframe(); - refresh(); - } - if (e.getKeyCode() == KeyEvent.VK_F8) { - for (int i = 0; i < 1024 * 512; i++) { - ram[i] = ram[i] & 0x01ffffff; - } - } - if (e.getKeyCode() == KeyEvent.VK_F7) { - for (int i = 0; i < 1024 * 512; i++) { - ram[i] = ram[i] | 0xfe000000; - } - } - } - - public void keyReleased(KeyEvent e) { - } - - private static class Closer extends WindowAdapter { - public void windowClosing(WindowEvent e) { - RuntimeConnections.MACHINE.resolve().close(); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/EmulationException.java b/src/runtime/java/org/jpsx/runtime/EmulationException.java deleted file mode 100644 index 52c8ef7..0000000 --- a/src/runtime/java/org/jpsx/runtime/EmulationException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -public class EmulationException extends RuntimeException { - public EmulationException(String message) { - super(message); - } - - public EmulationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/FinalComponentSettings.java b/src/runtime/java/org/jpsx/runtime/FinalComponentSettings.java deleted file mode 100644 index f05e7c4..0000000 --- a/src/runtime/java/org/jpsx/runtime/FinalComponentSettings.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import org.jpsx.api.InvalidConfigurationException; - -/** - * Components which wish to cache static final variables based on component settings - * should place those settings inside another (presumably inner class) such that - * they can easily check that the inner class is not referenced in the wrong order - *

- * A sample usage is shown below - *

- * public class Foo extends JPSXComponent {
- *    @Override void init() {
- *       MySettings.setComponent(this);
- *    }
- * 

- * private static class Settings extends FinalComponentSettings { - * public static final boolean someFlag = getComponent().getBooleanProperty("someFlag",true) - * } - * } - *

- */ -public class FinalComponentSettings { - private static JPSXComponent component; - - public static JPSXComponent getComponent() { - if (component == null) { - throw new InvalidConfigurationException("Attempted to access cached component settings before component initialization"); - } - return component; - } - - public static void setComponent(JPSXComponent component) { - if (FinalComponentSettings.component != null) - throw new InvalidConfigurationException("Attempted to set component more than once"); - FinalComponentSettings.component = component; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/FinalResolvedConnectionCache.java b/src/runtime/java/org/jpsx/runtime/FinalResolvedConnectionCache.java deleted file mode 100644 index 1e45b33..0000000 --- a/src/runtime/java/org/jpsx/runtime/FinalResolvedConnectionCache.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import org.jpsx.bootstrap.connection.Connection; - -public class FinalResolvedConnectionCache { - public static I resolve(Connection connection) { - // todo throw an exception if it is too early in the cycle - return connection.resolve(); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/JPSXComponent.java b/src/runtime/java/org/jpsx/runtime/JPSXComponent.java deleted file mode 100644 index 976da54..0000000 --- a/src/runtime/java/org/jpsx/runtime/JPSXComponent.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import java.util.Properties; - -public abstract class JPSXComponent { - private Properties properties = new Properties(); - private String description; - - protected JPSXComponent(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } - - public void init() { - } - - /** - * Called during machine initialization to connect the components together - *

- * Subclasses should override this to - */ - public void resolveConnections() { - } - - public void begin() { - } - - public void setProperty(String name, String value) { - properties.put(name, value); - } - - public String getProperty(String name, String defaultValue) { - return properties.getProperty(name, defaultValue); - } - - public boolean getBooleanProperty(String name, boolean defaultValue) { - String val = properties.getProperty(name, String.valueOf(defaultValue)); - return Boolean.valueOf(val); - } - - public int getIntProperty(String name, int defaultValue) { - int rc = defaultValue; - String val = properties.getProperty(name); - if (val != null) { - try { - rc = Integer.parseInt(val); - } catch (NumberFormatException e) { - - } - } - return rc; - } - - protected Properties getProperties() { - return properties; - } -} - diff --git a/src/runtime/java/org/jpsx/runtime/JPSXMachine.java b/src/runtime/java/org/jpsx/runtime/JPSXMachine.java deleted file mode 100644 index 249e5db..0000000 --- a/src/runtime/java/org/jpsx/runtime/JPSXMachine.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -public interface JPSXMachine { - - // initializer priorities; higher happens earliest - - int PRIORITY_RESOLVE_CONNECTIONS = 90000; - int PRIORITY_ADD_INSTRUCTIONS = 50000; - int PRIORITY_DMA_CONTROLLER = 40000; - int PRIORITY_IRQ_CONTROLLER = 35000; - int PRIORITY_REGISTER_ADDRESSES = 30000; - int PRIORITY_POPULATE_MEMORY = 10000; - int PRIORITY_FREEZE_SETTINGS = 5000; - - void addInitializer(int priority, Runnable initializer); - - void close(); -} diff --git a/src/runtime/java/org/jpsx/runtime/JPSXMachineImpl.java b/src/runtime/java/org/jpsx/runtime/JPSXMachineImpl.java deleted file mode 100644 index fb14103..0000000 --- a/src/runtime/java/org/jpsx/runtime/JPSXMachineImpl.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import org.apache.log4j.Logger; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.JPSXMachineLifecycle; -import org.jpsx.bootstrap.configuration.ComponentDefinition; -import org.jpsx.bootstrap.configuration.MachineDefinition; -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * This class is responsible for creating the components and initializing them - */ -public class JPSXMachineImpl implements JPSXMachine, JPSXMachineLifecycle { - public static final String CATEGORY = "Machine"; - private static Logger log = Logger.getLogger(CATEGORY); - - /** - * List of all components - */ - private List components = CollectionsFactory.newArrayList(); - - /** - * Ordered set of initializers to be run before execution begins - */ - private Map> initializers = CollectionsFactory.newTreeMap(Collections.reverseOrder()); - - private boolean settingsFrozen; - - public void initialize(MachineDefinition machine) { - RuntimeConnections.MACHINE.set(this); - addMachineElements(machine); - - // add our initializers - addInitializer(PRIORITY_RESOLVE_CONNECTIONS, new Runnable() { - public void run() { - log.info("Resolving connections..."); - for (JPSXComponent component : components) { - component.resolveConnections(); - } - } - }); - - addInitializer(PRIORITY_FREEZE_SETTINGS, new Runnable() { - public void run() { - settingsFrozen = false; - } - }); - - log.info("Pre-initializing components..."); - for (JPSXComponent component : components) { - component.init(); - } - - // perform ordered initialization - runInitializers(); - } - - public void start() { - for (JPSXComponent component : components) { - component.begin(); - } - - Runnable entryPoint = RuntimeConnections.MAIN.peek(); - if (entryPoint != null) { - entryPoint.run(); - } else { - // default implementation is just to run cpu - RuntimeConnections.CPU_CONTROL.resolve().go(); - - while (true) { - try { - Thread.sleep(Integer.MAX_VALUE); - } catch (InterruptedException e) { - break; - } - } - } - - close(); - } - - public void addInitializer(int priority, Runnable initializer) { - List list = initializers.get(priority); - if (list == null) { - list = CollectionsFactory.newArrayList(); - initializers.put(priority, list); - } - list.add(initializer); - } - - protected void addMachineElements(MachineDefinition machineDef) { - for (ComponentDefinition componentDef : machineDef.getComponents()) { - JPSXComponent component = createComponent(componentDef.getClassName()); - for (Map.Entry entry : componentDef.getProperties().entrySet()) { - component.setProperty(entry.getKey(), entry.getValue()); - } - log.info("Adding component " + component.getDescription()); - components.add(component); - } - } - - public JPSXComponent createComponent(String className) { - - try { - Class clazz = Class.forName(className); - return (JPSXComponent) clazz.newInstance(); - } catch (ClassCastException e) { - throw new InvalidConfigurationException("Class " + className + " does not extend JPSXComponent"); - } catch (Throwable e) { - throw new InvalidConfigurationException("Can't create instance of class " + className, e); - } - } - - private void runInitializers() { - for (List list : initializers.values()) { - for (Runnable initializer : list) { - initializer.run(); - } - } - } - - public void close() { - log.info("Closing...\n"); - // todo something other than this! - System.exit(0); - } - - public boolean settingsFrozen() { - return settingsFrozen; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/RuntimeConnections.java b/src/runtime/java/org/jpsx/runtime/RuntimeConnections.java deleted file mode 100644 index f7f3b6f..0000000 --- a/src/runtime/java/org/jpsx/runtime/RuntimeConnections.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import org.jpsx.api.CPUControl; -import org.jpsx.bootstrap.connection.MultipleConnection; -import org.jpsx.bootstrap.connection.SimpleConnection; - -import java.awt.event.KeyListener; - -public class RuntimeConnections { - /** - * This connections is always available - */ - public static final SimpleConnection MACHINE = SimpleConnection.create("JPSX Machine", JPSXMachine.class); - - public static final SimpleConnection CPU_CONTROL = SimpleConnection.create("CPU Control", CPUControl.class); - public static final MultipleConnection KEY_LISTENERS = MultipleConnection.create("Key Listeners", KeyListener.class); - public static final SimpleConnection MAIN = SimpleConnection.create("JPSX Main", Runnable.class); -} diff --git a/src/runtime/java/org/jpsx/runtime/SingletonJPSXComponent.java b/src/runtime/java/org/jpsx/runtime/SingletonJPSXComponent.java deleted file mode 100644 index 4534ccd..0000000 --- a/src/runtime/java/org/jpsx/runtime/SingletonJPSXComponent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime; - -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.bootstrap.util.CollectionsFactory; - -import java.util.Set; - -/** - * Only one instance of a specific subclass may be created; this - * does not stop you from creating two different classes which represent - * the same piece of hardware - */ -public abstract class SingletonJPSXComponent extends JPSXComponent { - private static final Set usedClasses = CollectionsFactory.newHashSet(); - - protected SingletonJPSXComponent(String description) { - super(description); - } - - @Override - public void init() { - super.init(); - if (!usedClasses.add(getClass().getName())) { - throw new InvalidConfigurationException("Attempted to create multiple instances of " + getClass().getName()); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java b/src/runtime/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java deleted file mode 100644 index 18a755e..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java +++ /dev/null @@ -1,1786 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.bcel.generic.*; -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceListener; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.Pollable; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.bootstrap.classloader.ClassModifier; -import org.jpsx.bootstrap.classloader.JPSXClassLoader; -import org.jpsx.bootstrap.connection.SimpleConnection; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.JPSXMachine; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.util.ByteCodeUtil; -import org.jpsx.runtime.util.ClassUtil; -import org.jpsx.runtime.util.MiscUtil; - -import java.lang.reflect.Method; -import java.util.Iterator; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -// todo disallow multiple reg at the same address -public final class AddressSpaceImpl extends SingletonJPSXComponent implements ClassModifier, AddressSpace, AddressSpaceRegistrar { - private static final Logger log = Logger.getLogger("AddressSpace"); - private static final Logger logPoll = Logger.getLogger("AddressSpace.poll"); - private static final Logger logUnknown = Logger.getLogger("AddressSpace.unknown"); - - private static final String HARDWARE_CLASS = ClassUtil.innerClassName(AddressSpaceImpl.class, "Hardware"); - - private static final boolean logUnknownDebug = logUnknown.isDebugEnabled(); - private static final boolean logPollDebug = logPoll.isDebugEnabled(); - private static final boolean logPollTrace = logPoll.isTraceEnabled(); - - public static class Settings { - public static final boolean tagAddressAccess = true; - public static final boolean checkAlignment = false; - public static final boolean debugPoll = false; - public static final boolean assertOnUnknownAddress = true; - public static final boolean checkHWOverlap = false; - } - - public static final int[] ram; - public static int[] ramD; - public static final int[] scratch; - public static final int[] bios; - public static final int[] hw; - public static final int[] par; - - private static int[] ramDummy; - private static byte[] ramTags; - private static byte[] biosTags; - private static int lastPoll32Address = 0; - private static int lastPoll32Count = 0; - private static boolean writeEnabled = true; - - private static final int SCRATCH_MASK = SCRATCH_SIZE - 1; - private static final int PAR_MASK = PAR_SIZE - 1; - private static final int BIOS_MASK = BIOS_SIZE - 1; - private static final int HW_MASK = HW_SIZE - 1; - - private static int readPC0; - private static int readPC1; - private static int readPC2; - private static int readPCHW; // PC of last hw read - private static int readAddress0; - private static int readAddress1; - private static int readAddress2; - private static int readAddressHW; - private static int readsSinceHW; // count of reads since last hw read - private static final int MAX_READS_SINCE_HW = 16; - - private static AddressSpaceListener addressSpaceListeners; - private static Scheduler scheduler; - - static { - ram = new int[RAM_SIZE >> 2]; - // not much writing usually done when ram writing disabled - ramDummy = new int[0x1000 >> 2]; - ramD = ram; - ramTags = new byte[RAM_SIZE >> 2]; - biosTags = new byte[BIOS_SIZE >> 2]; - scratch = new int[SCRATCH_SIZE >> 2]; - bios = new int[BIOS_SIZE >> 2]; - hw = new int[HW_SIZE >> 2]; - par = new int[PAR_SIZE >> 2]; - } - - public AddressSpaceImpl() { - super("JPSX Address Space"); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpaceListeners = CoreComponentConnections.ADDRESS_SPACE_LISTENERS.resolve(); -// r3000 = CoreComponentConnections.R3000.resolve(); - scheduler = CoreComponentConnections.SCHEDULER.resolve(); - } - - public void init() { - super.init(); - JPSXClassLoader.registerClassModifier(HARDWARE_CLASS, this); - JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); - CoreComponentConnections.ADDRESS_SPACE.set(this); - machine.addInitializer(JPSXMachine.PRIORITY_REGISTER_ADDRESSES, new Runnable() { - public void run() { - log.info("Registering memory mapped addresses..."); - - // make a connection wrapper around the registrar, so that we can close it afterwards - SimpleConnection connection = SimpleConnection.create("AddressSpaceRegistrar", AddressSpaceRegistrar.class); - connection.set(AddressSpaceImpl.this); - CoreComponentConnections.ALL_MEMORY_MAPPED.resolve().registerAddresses(connection.resolve()); - CoreComponentConnections.ALL_MEMORY_MAPPED.close(); - connection.close(); - } - }); - machine.addInitializer(JPSXMachine.PRIORITY_POPULATE_MEMORY, new Runnable() { - public void run() { - log.info("Populating memory..."); - CoreComponentConnections.ALL_POPULATORS.resolve().run(); - CoreComponentConnections.ALL_POPULATORS.close(); - } - }); - } - - private void rewriteHWMethod(ClassGen cgen, String name, String signature, SortedMap cases, InstructionList suffix, int resolution) { - ConstantPoolGen cp = cgen.getConstantPool(); - org.apache.bcel.classfile.Method m = cgen.containsMethod(name, signature); - MethodGen mg = JPSXClassLoader.emptyMethod(cgen, m); - InstructionList il = mg.getInstructionList(); - - ByteCodeUtil.emitSwitch(cp, il, 0, cases, resolution, HW_BASE, HW_END - resolution); - il.append(suffix); - - mg.setMaxLocals(); - mg.setMaxStack(); - cgen.replaceMethod(m, mg.getMethod()); - il.dispose(); - } - - public ClassGen modifyClass(String classname, ClassGen cgen) { - ConstantPoolGen cp = cgen.getConstantPool(); - InstructionList suffix = new InstructionList(); - InstructionList il = new InstructionList(); - TreeMap cases; - Iterator addresses; - Integer address; - Method m; - - // read 32 - cases = new TreeMap(); - for (addresses = read32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) read32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new IRETURN()); - cases.put(address, il); - } - for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subRead32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new IRETURN()); - cases.put(address, il); - } - suffix.append(new ILOAD(0)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead32", "(I)I"))); - suffix.append(new IRETURN()); - rewriteHWMethod(cgen, "read32", "(I)I", cases, suffix, 4); - - // write 32 - cases.clear(); - for (addresses = write32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) write32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); - il.append(new RETURN()); - cases.put(address, il); - } - for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, -1)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(address, il); - } - suffix.append(new ILOAD(0)); - suffix.append(new ILOAD(1)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite32", "(II)V"))); - suffix.append(new RETURN()); - rewriteHWMethod(cgen, "write32", "(II)V", cases, suffix, 4); - - // read 16 - cases.clear(); - for (addresses = read16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) read16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - } - for (addresses = subRead16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subRead16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - } - for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~3; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subRead32Callbacks.get(address); - - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new IRETURN()); - cases.put(iAddress + 2, il); - } - - suffix.append(new ILOAD(0)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead16", "(I)I"))); - suffix.append(new IRETURN()); - rewriteHWMethod(cgen, "read16", "(I)I", cases, suffix, 2); - - // write 16 - cases.clear(); - for (addresses = write16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) write16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); - il.append(new RETURN()); - cases.put(address, il); - } - for (addresses = subWrite16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subWrite16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xffff)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(address, il); - } - for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~3; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUSH(cp, 0xffff)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(address, il); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 0xffff0000)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(iAddress + 2, il); - } - suffix.append(new ILOAD(0)); - suffix.append(new ILOAD(1)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite16", "(II)V"))); - suffix.append(new RETURN()); - rewriteHWMethod(cgen, "write16", "(II)V", cases, suffix, 2); - - // read 8 - cases.clear(); - for (addresses = read8Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) read8Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - } - for (addresses = subRead16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~1; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subRead16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 8)); - il.append(new ISHR()); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(iAddress + 1, il); - } - for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~3; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subRead32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(address, il); - - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 8)); - il.append(new ISHR()); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(iAddress + 1, il); - - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new IRETURN()); - cases.put(iAddress + 2, il); - - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); - il.append(new PUSH(cp, 24)); - il.append(new ISHR()); - il.append(new IRETURN()); - cases.put(iAddress + 3, il); - } - - suffix.append(new ILOAD(0)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead8", "(I)I"))); - suffix.append(new IRETURN()); - rewriteHWMethod(cgen, "read8", "(I)I", cases, suffix, 1); - - // write 8 - cases.clear(); - for (addresses = write8Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - m = (Method) write8Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); - il.append(new RETURN()); - cases.put(address, il); - } - for (addresses = subWrite16Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~1; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subWrite16Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new PUSH(cp, 0xff)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(address, il); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 8)); - il.append(new ISHL()); - il.append(new PUSH(cp, 0xff00)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(iAddress + 1, il); - } - for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { - address = (Integer) addresses.next(); - int iAddress = address.intValue() & ~3; - assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new PUSH(cp, 0xff)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(address, il); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new PUSH(cp, 8)); - il.append(new ISHL()); - il.append(new PUSH(cp, 0x0000ff00)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(iAddress + 1, il); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 0xff)); - il.append(new IAND()); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 0x00ff0000)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(iAddress + 2, il); - - m = (Method) subWrite32Callbacks.get(address); - il = new InstructionList(); - il.append(new PUSH(cp, iAddress)); - il.append(new ILOAD(1)); - il.append(new PUSH(cp, 24)); - il.append(new ISHL()); - il.append(new PUSH(cp, 0xff000000)); - il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); - il.append(new RETURN()); - cases.put(iAddress + 3, il); - } - - suffix.append(new ILOAD(0)); - suffix.append(new ILOAD(1)); - suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite8", "(II)V"))); - suffix.append(new RETURN()); - rewriteHWMethod(cgen, "write8", "(II)V", cases, suffix, 1); - - return cgen; - } - - - public void tagClearPollCounters() { - _tagClearPollCounters(); - } - - public static void _tagClearPollCounters() { - readPC0 = readPC1 = readPC2 = -1; - } - - - public void tagAddressAccessRead8(int pc, int address) { - _tagAddressAccessRead8(pc, address); - } - - /** - * Note this method requires that pc falls either in RAM or - * BIOS - */ - public static void _tagAddressAccessRead8(final int pc, final int address) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - - int value; - byte tag = 0;//TAG_INVALID; ?? todo why was this here - if (Settings.tagAddressAccess) { - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - tag = TAG_SCRATCH; - } else if (prefix == 0 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (prefix == -6 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < HW_END && address >= HW_BASE) { - tag = TAG_HW; - } else if (address < PAR_END && address >= PAR_BASE) { - tag = TAG_PAR; - } else if (address >= BIOS_BASE && address < BIOS_END) { - tag = TAG_BIOS; - } - } - - int index = (pc & 0x1fffff) >> 2; - int oldTag = tags[index]; - if (0 != (oldTag & TAG_POLL)) { - _checkPoll8(address); - } else { - if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible poll at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible HW specific poll8 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } - } - readPC0 = readPC1; - readPC1 = readPC2; - readPC2 = pc; - readAddress0 = readAddress1; - readAddress1 = readAddress2; - readAddress2 = address; - if (address < HW_END && address >= HW_BASE) { - readAddressHW = address; - readPCHW = pc; - readsSinceHW = 0; - } else { - readsSinceHW++; - } - - tags[index] |= tag; - } - - public void tagAddressAccessRead16(final int pc, final int address) { - _tagAddressAccessRead16(pc, address); - } - - /** - * Note this method requires that pc falls either in RAM or - * BIOS - */ - public static void _tagAddressAccessRead16(final int pc, final int address) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - - byte tag = 0;//TAG_INVALID; ?? todo why was this here - if (Settings.tagAddressAccess) { - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - tag = TAG_SCRATCH; - } else if (prefix == 0 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (prefix == -6 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < HW_END && address >= HW_BASE) { - tag = TAG_HW; - } else if (address < PAR_END && address >= PAR_BASE) { - tag = TAG_PAR; - } else if (address >= BIOS_BASE && address < BIOS_END) { - tag = TAG_BIOS; - } - } - - int index = (pc & 0x1fffff) >> 2; - int oldTag = tags[index]; - if (0 != (oldTag & TAG_POLL)) { - _checkPoll16(address); - } else { - if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible poll at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible HW specific poll16 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } - } - readPC0 = readPC1; - readPC1 = readPC2; - readPC2 = pc; - readAddress0 = readAddress1; - readAddress1 = readAddress2; - readAddress2 = address; - if (address < HW_END && address >= HW_BASE) { - readAddressHW = address; - readPCHW = pc; - readsSinceHW = 0; - } else { - readsSinceHW++; - } - tags[index] |= tag; - } - - public void tagAddressAccessRead32(int pc, int address) { - _tagAddressAccessRead32(pc, address); - } - - /** - * Note this method requires that pc falls either in RAM or - * BIOS - */ - public static void _tagAddressAccessRead32(final int pc, final int address) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - - byte tag = 0;//TAG_INVALID; ?? todo why was this here - - if (Settings.tagAddressAccess) { - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - tag = TAG_SCRATCH; - } else if (prefix == 0 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (prefix == -6 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < HW_END && address >= HW_BASE) { - tag = TAG_HW; - } else if (address < PAR_END && address >= PAR_BASE) { - tag = TAG_PAR; - } else if (address >= BIOS_BASE && address < BIOS_END) { - tag = TAG_BIOS; - } - } - - int index = (pc & 0x1fffff) >> 2; - int oldTag = tags[index]; - if (0 != (oldTag & TAG_POLL)) { - _checkPoll32(address); - } else { - // Simple check of last 3 reads - if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible poll32 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { - // Tony Hawk fails to catch poll of 0x1f801814 for vsync in interlaced mode, because the polling is spread - // across several functions... in this hardware read case, lets look back a little further - tag |= TAG_POLL; - if (logPollDebug) { - logPoll.debug("possible HW specific poll32 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); - } - } - } - readPC0 = readPC1; - readPC1 = readPC2; - readPC2 = pc; - readAddress0 = readAddress1; - readAddress1 = readAddress2; - readAddress2 = address; - if (address < HW_END && address >= HW_BASE) { - readAddressHW = address; - readPCHW = pc; - readsSinceHW = 0; - } else { - readsSinceHW++; - } - tags[index] |= tag; - } - - public void tagAddressAccessWrite(final int pc, final int address) { - _tagAddressAccessWrite(pc, address); - } - - /** - * Note this method requires that pc falls either in RAM or - * BIOS - */ - public static void _tagAddressAccessWrite(final int pc, final int address) { - if (Settings.tagAddressAccess) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - byte tag = 0; // why is this there? TAG_INVALID; - if (prefix == -8 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - tag = TAG_SCRATCH; - } else if (prefix == 0 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (prefix == -6 && offset < RAM_SIZE) { - tag = TAG_RAM; - } else if (address < HW_END && address >= HW_BASE) { - tag = TAG_HW; - } else if (address < PAR_END && address >= PAR_BASE) { - tag = TAG_PAR; - } else if (address >= BIOS_BASE && address < BIOS_END) { -// System.out.println("------------ "+MiscUtil.toHex( pc, 8)+" : "+MiscUtil.toHex( address, 8)); - tag = TAG_BIOS; - } - - tags[(pc & 0x1fffff) >> 2] |= tag; - } - } - - public byte getTag(int pc) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - int index = (pc & 0x1fffff) >> 2; - return tags[index]; - } - - public void orTag(final int pc, byte val) { - byte[] tags; - if (pc < BIOS_BASE || pc >= BIOS_END) { - tags = ramTags; - } else { - tags = biosTags; - } - int index = (pc & 0x1fffff) >> 2; - tags[index] |= val; - } - - public int read8(int address) { - return _read8(address); - } - - public static int _read8(final int address) { - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - int value; - if (prefix == -8 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - value = scratch[(offset & SCRATCH_MASK) >> 2]; - } else if (prefix == 0 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (prefix == -6 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (address < HW_END && address >= HW_BASE) { - return Hardware.read8(address); - } else if (address < PAR_END && address >= PAR_BASE) { - return _parRead8(address); - } else if (address >= BIOS_BASE && address < BIOS_END) { - value = bios[(offset & BIOS_MASK) >> 2]; - } else { - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - value = 0; - } - switch (address & 3) { - case 3: - return (value >> 24) & 0xff; - case 2: - return (value >> 16) & 0xff; - case 1: - return (value >> 8) & 0xff; - default: - return value & 0xff; - } - } - - public static int _read8Ram(final int address) { - int value = ramD[(address & RAM_AND) >> 2]; - - switch (address & 3) { - case 3: - return (value >> 24) & 0xff; - case 2: - return (value >> 16) & 0xff; - case 1: - return (value >> 8) & 0xff; - default: - return value & 0xff; - } - } - - public static int _read8Scratch(final int address) { - int value = scratch[(address ^ SCRATCH_XOR) >> 2]; - - switch (address & 3) { - case 3: - return (value >> 24) & 0xff; - case 2: - return (value >> 16) & 0xff; - case 1: - return (value >> 8) & 0xff; - default: - return value & 0xff; - } - } - - public static int _read8Bios(final int address) { - int value = bios[(address ^ BIOS_XOR) >> 2]; - - switch (address & 3) { - case 3: - return (value >> 24) & 0xff; - case 2: - return (value >> 16) & 0xff; - case 1: - return (value >> 8) & 0xff; - default: - return value & 0xff; - } - } - - public static void _write8Bios(final int address, int value) { - int dummy = bios[(address ^ BIOS_XOR) >> 2]; - } - - public static void _write16Bios(final int address, int value) { - int dummy = bios[(address ^ BIOS_XOR) >> 2]; - } - - public static void _write32Bios(final int address, int value) { - int dummy = bios[(address ^ BIOS_XOR) >> 2]; - } - - public int read16(int address) { - return _read16(address); - } - - public static int _read16(final int address) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - int value; - if (prefix == -8 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - value = scratch[(offset & SCRATCH_MASK) >> 2]; - } else if (prefix == 0 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (prefix == -6 && offset < RAM_SIZE) { - value = ramD[offset >> 2]; - } else if (address < HW_END && address >= HW_BASE) { - return Hardware.read16(address); - } else if (address < PAR_END && address >= PAR_BASE) { - return _parRead16(address); - } else if (address >= BIOS_BASE && address < BIOS_END) { - value = bios[(offset & BIOS_MASK) >> 2]; - } else { - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - value = 0; - } - switch (address & 2) { - case 2: - return (value >> 16) & 0xffff; - default: - return value & 0xffff; - } - } - - public static int _read16Ram(final int address) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int value = ramD[(address & RAM_AND) >> 2]; - switch (address & 2) { - case 2: - return (value >> 16) & 0xffff; - default: - return value & 0xffff; - } - } - - public static int _read16Scratch(final int address) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int value = scratch[(address ^ SCRATCH_XOR) >> 2]; - switch (address & 2) { - case 2: - return (value >> 16) & 0xffff; - default: - return value & 0xffff; - } - } - - public static int _read16Bios(final int address) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int value = bios[(address ^ BIOS_XOR) >> 2]; - switch (address & 2) { - case 2: - return (value >> 16) & 0xffff; - default: - return value & 0xffff; - } - } - - public int read32(int address) { - return _read32(address); - } - - public static int _read32(final int address) { - if (Settings.checkAlignment) { - if ((address & 3) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - return ramD[offset >> 2]; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - return scratch[(offset & SCRATCH_MASK) >> 2]; - } else if (prefix == -6 && offset < RAM_SIZE) { - return ramD[offset >> 2]; - } else if (prefix == 0 && offset < RAM_SIZE) { - return ramD[offset >> 2]; - } else if (address < HW_END && address >= HW_BASE) { - return Hardware.read32(address); - } else if (address < PAR_END && address >= PAR_BASE) { - return _parRead32(address); - } else if (address >= BIOS_BASE && address < BIOS_END) { - return bios[(offset & BIOS_MASK) >> 2]; - } - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - return 0; - } - - - public void write8(int address, int value) { - _write8(address, value); - } - - public static void _write8(final int address, final int value) { - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffffff00; - nvalue = (value & 0xff); - break; - case 1: - mask = 0xffff00ff; - nvalue = (value & 0xff) << 8; - break; - case 2: - mask = 0xff00ffff; - nvalue = (value & 0xff) << 16; - break; - default: - mask = 0x00ffffff; - nvalue = value << 24; - break; - } - if (prefix == -8 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - scratch[(offset & SCRATCH_MASK) >> 2] = (scratch[(offset & SCRATCH_MASK) >> 2] & mask) | nvalue; - } else if (prefix == 0 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (prefix == -6 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (address < HW_END && address >= HW_BASE) { - Hardware.write8(address, value); - } else if (address < PAR_END && address >= PAR_BASE) { - if (!_parWrite8(address, value)) { - //System.out.println("write8 HW "+MiscUtil.toHex( address, 8)); - par[(offset & PAR_MASK) >> 2] = (par[(offset & PAR_MASK) >> 2] & mask) | nvalue; - } - } else if (address >= BIOS_BASE && address < BIOS_END) { - } else { - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - } - return; - } - - public static void _write8Ram(int address, final int value) { - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffffff00; - nvalue = (value & 0xff); - break; - case 1: - mask = 0xffff00ff; - nvalue = (value & 0xff) << 8; - break; - case 2: - mask = 0xff00ffff; - nvalue = (value & 0xff) << 16; - break; - default: - mask = 0x00ffffff; - nvalue = value << 24; - break; - } - address = (address & RAM_AND) >> 2; - ramD[address] = (ramD[address] & mask) | nvalue; - return; - } - - public static void _write8Scratch(int address, final int value) { - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffffff00; - nvalue = (value & 0xff); - break; - case 1: - mask = 0xffff00ff; - nvalue = (value & 0xff) << 8; - break; - case 2: - mask = 0xff00ffff; - nvalue = (value & 0xff) << 16; - break; - default: - mask = 0x00ffffff; - nvalue = value << 24; - break; - } - address = (address ^ SCRATCH_XOR) >> 2; - scratch[address] = (scratch[address] & mask) | nvalue; - return; - } - - public void write16(int address, int value) { - _write16(address, value); - } - - public static void _write16(final int address, final int value) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - - // todo reverse sense of mask - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffff0000; - nvalue = (value & 0xffff); - break; - default: - mask = 0x0000ffff; - nvalue = value << 16; - } - if (prefix == -8 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - scratch[(offset & SCRATCH_MASK) >> 2] = (scratch[(offset & SCRATCH_MASK) >> 2] & mask) | nvalue; - } else if (prefix == 0 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (prefix == -6 && offset < RAM_SIZE) { - ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; - } else if (address < HW_END && address >= HW_BASE) { - Hardware.write16(address, value); - } else if (address < PAR_END && address >= PAR_BASE) { - if (!_parWrite16(address, value)) { - par[(offset & PAR_MASK) >> 2] = (par[(offset & PAR_MASK) >> 2] & mask) | nvalue; - } - } else if (address >= BIOS_BASE && address < BIOS_END) { - } else { - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - } - return; - } - - public static void _write16Ram(int address, final int value) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffff0000; - nvalue = (value & 0xffff); - break; - default: - mask = 0x0000ffff; - nvalue = value << 16; - } - address = (address & RAM_AND) >> 2; - ramD[address] = (ramD[address] & mask) | nvalue; - return; - } - - public static void _write16Scratch(int address, final int value) { - if (Settings.checkAlignment) { - if ((address & 1) != 0) { - throw new IllegalStateException("misaligned"); - } - } - - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffff0000; - nvalue = (value & 0xffff); - break; - default: - mask = 0x0000ffff; - nvalue = value << 16; - } - address = (address ^ SCRATCH_XOR) >> 2; - scratch[address] = (scratch[address] & mask) | nvalue; - return; - } - - public void write32(int address, int value) { - _write32(address, value); - } - - public static void _write32(final int address, final int value) { - if (Settings.checkAlignment) { - if ((address & 3) != 0) { - throw new IllegalStateException("misaligned"); - } - } - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - ramD[offset >> 2] = value; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - scratch[(offset & SCRATCH_MASK) >> 2] = value; - } else if (prefix == 0 && offset < RAM_SIZE) { - ramD[offset >> 2] = value; - } else if (prefix == -6 && offset < RAM_SIZE) { - ramD[offset >> 2] = value; - } else if (address < HW_END && address >= HW_BASE) { - Hardware.write32(address, value); - } else if (address < PAR_END && address >= PAR_BASE) { - if (!_parWrite32(address, value)) { - par[(offset & PAR_MASK) >> 2] = value; - } - } else if (address >= BIOS_BASE && address < BIOS_END) { - } else if (address == 0xfffe0130) { - // System.out.println( "write 0xfffe0130 "+MiscUtil.toHex( value, 8)); - } else { - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - } - } - - public int internalRead32(final int address) { - return _internalRead32(address); - } - - public static int _internalRead32(final int address) { - // todo check misaligned address? - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - return ram[offset >> 2]; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - return scratch[(offset & SCRATCH_MASK) >> 2]; - } else if (address >= BIOS_BASE && address < BIOS_END) { - return bios[(offset & BIOS_MASK) >> 2]; - } else if (address < HW_END && address >= HW_BASE) { - return hw[(offset & HW_MASK) >> 2]; - } else if (address < PAR_END && address >= PAR_BASE) { - return par[(offset & PAR_MASK) >> 2]; - } else if (prefix == 0 && offset < RAM_SIZE) { - return ram[offset >> 2]; - } else if (prefix == -6 && offset < RAM_SIZE) { - return ram[offset >> 2]; - } - - if (Settings.assertOnUnknownAddress) - throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); - return 0; - } - - public void internalWrite32(int address, int value) { - _internalWrite32(address, value); - } - - public static void _internalWrite32(final int address, final int value) { - // todo check misaligned address? - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if (prefix == -8 && offset < RAM_SIZE) { - ram[offset >> 2] = value; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - scratch[(offset & SCRATCH_MASK) >> 2] = value; - } else if (address < HW_END && address >= HW_BASE) { - hw[(offset & HW_MASK) >> 2] = value; - } else if (address < PAR_END && address >= PAR_BASE) { - par[(offset & PAR_MASK) >> 2] = value; - } else if (address >= BIOS_BASE && address < BIOS_END) { - bios[(offset & BIOS_MASK) >> 2] = value; - } else if (prefix == 0 && offset < RAM_SIZE) { - ram[offset >> 2] = value; - } else if (prefix == -6 && offset < RAM_SIZE) { - ram[offset >> 2] = value; - } - } - - private static Map read8Callbacks = CollectionsFactory.newHashMap(); - private static Map read16Callbacks = CollectionsFactory.newHashMap(); - private static Map subRead16Callbacks = CollectionsFactory.newHashMap(); - private static Map read32Callbacks = CollectionsFactory.newHashMap(); - private static Map subRead32Callbacks = CollectionsFactory.newHashMap(); - private static Map write8Callbacks = CollectionsFactory.newHashMap(); - private static Map write16Callbacks = CollectionsFactory.newHashMap(); - private static Map subWrite16Callbacks = CollectionsFactory.newHashMap(); - private static Map write32Callbacks = CollectionsFactory.newHashMap(); - private static Map subWrite32Callbacks = CollectionsFactory.newHashMap(); - - private static Map poll8Callbacks = CollectionsFactory.newHashMap(); - private static Map poll16Callbacks = CollectionsFactory.newHashMap(); - private static Map poll32Callbacks = CollectionsFactory.newHashMap(); - - private static final Class[] READ_CALLBACK_PARAMS = new Class[]{int.class}; - private static final Class[] WRITE_CALLBACK_PARAMS = new Class[]{int.class, int.class}; - private static final Class[] SUBWRITE_CALLBACK_PARAMS = new Class[]{int.class, int.class, int.class}; - - private void registerCallback(Map map, int address, Class clazz, String methodName, Class[] params) { - //System.out.println(" register address "+MiscUtil.toHex( address, 8)); - try { - Method m = clazz.getMethod(methodName, params); - map.put(address, m); - } catch (Throwable t) { - StringBuilder desc = new StringBuilder(); - desc.append("Cannot find method "); - desc.append(clazz.getName()); - desc.append("."); - desc.append(methodName); - desc.append("("); - for (int i = 0; i < params.length; i++) { - if (i != 0) desc.append(","); - desc.append(params[i].getName()); - } - desc.append(")"); - throw new IllegalStateException(desc.toString()); - } - } - - public void registerRead8Callback(int address, Class clazz, String methodName) { - registerCallback(read8Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); - } - - public void registerRead16Callback(int address, Class clazz, String methodName) { - registerRead16Callback(address, clazz, methodName, false); - } - - public void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead) { - assert 0 == (address & 1); - if (allowSubRead) { - registerCallback(subRead16Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); - } else { - registerCallback(read16Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); - } - } - - public void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead) { - assert 0 == (address & 3); - if (allowSubRead) { - registerCallback(subRead32Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); - } else { - registerCallback(read32Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); - } - } - - public void registerPoll32Callback(int address, Pollable pollable) { - poll32Callbacks.put(address, pollable); - } - - public void registerRead32Callback(int address, Class clazz, String methodName) { - registerRead32Callback(address, clazz, methodName, false); - } - - public void registerWrite8Callback(int address, Class clazz, String methodName) { - registerCallback(write8Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); - } - - public void registerWrite16Callback(int address, Class clazz, String methodName) { - registerWrite16Callback(address, clazz, methodName, false); - } - - public void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { - assert 0 == (address & 1); - if (allowSubWrite) { - registerCallback(subWrite16Callbacks, address, clazz, methodName, SUBWRITE_CALLBACK_PARAMS); - } else { - registerCallback(write16Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); - } - } - - public void registerWrite32Callback(int address, Class clazz, String methodName) { - registerWrite32Callback(address, clazz, methodName, false); - } - - public void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { - assert 0 == (address & 3); - if (allowSubWrite) { - registerCallback(subWrite32Callbacks, address, clazz, methodName, SUBWRITE_CALLBACK_PARAMS); - } else { - registerCallback(write32Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); - } - } - - public void resolve(int address, ResolveResult result) { - result.address = address; - result.low2 = address & 3; - - int prefix = address >> 28; - int offset = address & OFFSET_MASK; - if ((prefix == 0 || prefix == -8 || prefix == -6) && offset < RAM_SIZE) { - result.mem = ram; - result.offset = offset >> 2; - result.tag = TAG_RAM; - return; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { - result.mem = scratch; - result.offset = (offset & SCRATCH_MASK) >> 2; - result.tag = TAG_SCRATCH; - return; - } else if (address < HW_END && address >= HW_BASE) { - result.mem = hw; - result.offset = (offset & HW_MASK) >> 2; - result.tag = TAG_HW; - return; - } else if (address >= BIOS_BASE && address < BIOS_END) { - result.mem = bios; - result.offset = (offset & BIOS_MASK) >> 2; - result.tag = TAG_BIOS; - return; - } - result.mem = null; - //result.tag = TAG_INVALID; - return; - } - - public void resolve(int address, int size, boolean write, ResolveResult result) { - result.address = address; - result.low2 = address & 3; - - // assert end>=address - - int end = size == 0 ? address : (address + size - 1); - int prefix = address >> 28; - int prefix2 = end >> 28; - if (prefix == prefix2) { - int offset = address & OFFSET_MASK; - int offset2 = end & OFFSET_MASK; - if ((prefix == 0 || prefix == -8 || prefix == -6) && offset < RAM_SIZE && offset2 < RAM_SIZE) { - result.mem = ram; - result.offset = offset >> 2; - result.tag = TAG_RAM; - return; - } else if (address < SCRATCH_END && address >= SCRATCH_BASE && end < SCRATCH_END) { - result.mem = scratch; - result.offset = (offset & SCRATCH_MASK) >> 2; - result.tag = TAG_SCRATCH; - return; - } else if (address < HW_END && address >= HW_BASE && end < HW_END) { - result.mem = hw; - result.offset = (offset & HW_MASK) >> 2; - result.tag = TAG_HW; - return; - } else if (address >= BIOS_BASE && address < BIOS_END && end < BIOS_END) { - result.mem = bios; - result.offset = (offset & BIOS_MASK) >> 2; - result.tag = TAG_BIOS; - return; - } - } - result.mem = null; - //result.tag = TAG_INVALID; - } - - public static int _parRead8(final int address) { - //System.out.println( "PAR READ 8: " + MiscUtil.toHex( address, 8 ) ); - return 0; - } - - public static int _parRead16(final int address) { - //System.out.println( "PAR READ 16: " + MiscUtil.toHex( address, 8 ) ); - return 0; - } - - public static int _parRead32(final int address) { - //System.out.println( "PAR READ 32: " + MiscUtil.toHex( address, 8 ) ); - return 0; - } - - public static boolean _parWrite8(final int address, int value) { - //System.out.println( "PAR WRITE 8: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 2 ) ); - return false; - } - - public static boolean _parWrite16(final int address, int value) { - //System.out.println( "PAR WRITE 16: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 4 ) ); - return false; - } - - public static boolean _parWrite32(final int address, int value) { - //System.out.println( "PAR WRITE 32: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 8 ) ); - return false; - } - - public void enableMemoryWrite(boolean enableWrite) { - ramD = enableWrite ? ram : ramDummy; - if (!enableWrite && writeEnabled) { - // clear all the tags - for (int i = 0; i < RAM_SIZE / 4; i++) { - ramTags[i] = 0; - } - addressSpaceListeners.cacheCleared(); - } - writeEnabled = enableWrite; - } - - public static void _checkPoll8(int address) { - if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) - System.out.println("Checking poll8: " + MiscUtil.toHex(address, 8)); - //+" "+MiscUtil.toHex( AddressSpaceImpl.read8( address), 2)); - } - - public static void _checkPoll16(int address) { - // todo check this! - if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) - System.out.println("Checking poll16: " + MiscUtil.toHex(address, 8)); - //+" "+MiscUtil.toHex( AddressSpaceImpl.read16( address), 4)); - } - - // todo make this an N-stack - public static void _checkPoll32(int address) { - if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) - System.out.println("Checking poll32: " + MiscUtil.toHex(address, 8)); - if (address == lastPoll32Address) { - lastPoll32Count++; - if (lastPoll32Count == 256) { - if (logPollTrace) { - logPoll.trace("Poll of " + MiscUtil.toHex(address, 8)); - } - - if ((address & 0x50000000) == 0x00000000) { - // we assume that poll of RAM is broken out of by interrupt - scheduler.cpuThreadWait(); - } else { - Pollable p = poll32Callbacks.get(address); - if (p != null) - p.poll(address, 4); - } - lastPoll32Count = 0; - } - } else { - lastPoll32Address = address; - lastPoll32Count = 0; - } - } - - public static class Hardware { - public static void write8(int address, int value) { - // should be rewritten; - assert false; - } - - public static void write16(int address, int value) { - // should be rewritten; - assert false; - } - - public static void write32(int address, int value) { - // should be rewritten; - assert false; - } - - public static int read8(int address) { - // should be rewritten; - assert false; - return 0; - } - - public static int read16(int address) { - // should be rewritten; - assert false; - return 0; - } - - public static int read32(int address) { - // should be rewritten; - assert false; - return 0; - } - - public static int defaultRead32(int address) { - if (Settings.checkHWOverlap) { - if (null != read8Callbacks.get(address)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (null != read8Callbacks.get(address + 1)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (null != read8Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (null != read8Callbacks.get(address + 3)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (null != read16Callbacks.get(address)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (null != subRead16Callbacks.get(address)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (null != read16Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (null != subRead16Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - } - int rc = hw[(address & HW_MASK) >> 2]; - if (logUnknownDebug) { - logUnknown.debug("unknown hwRead32 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 8)); - } - return rc; - } - - public static void defaultWrite32(int address, int value) { - if (Settings.checkHWOverlap && null != write8Callbacks.get(address)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 1)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 3)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != write16Callbacks.get(address)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (Settings.checkHWOverlap && null != subWrite16Callbacks.get(address)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (Settings.checkHWOverlap && null != write16Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (Settings.checkHWOverlap && null != subWrite16Callbacks.get(address + 2)) { - throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (logUnknownDebug) { - logUnknown.debug("unknown hwWrite32 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 8)); - } - hw[(address & HW_MASK) >> 2] = value; - } - - public static int defaultRead16(int address) { - if (Settings.checkHWOverlap && null != read32Callbacks.get(address & ~3)) { - throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); - } - if (Settings.checkHWOverlap && null != read8Callbacks.get(address)) { - throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != read8Callbacks.get(address + 1)) { - throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - int rc = hw[(address & HW_MASK) >> 2]; - if (logUnknownDebug) { - logUnknown.debug("unknown hwRead16 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 4)); - } - if (0 != (address & 2)) { - rc >>= 16; - } - return rc & 0xffff; - } - - public static void defaultWrite16(final int address, int value) { - if (Settings.checkHWOverlap && null != write32Callbacks.get(address & ~3)) { - throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); - } - if (Settings.checkHWOverlap && null != write8Callbacks.get(address)) { - throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 1)) { - throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); - } - int mask; - int nvalue; - switch (address & 2) { - case 0: - mask = 0xffff0000; - nvalue = (value & 0xffff); - break; - default: - mask = 0x0000ffff; - nvalue = value << 16; - } - if (logUnknownDebug) { - logUnknown.debug("unknown hwWrite16 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 4)); - } - hw[(address & HW_MASK) >> 2] = (hw[(address & HW_MASK) >> 2] & mask) | nvalue; - } - - public static int defaultRead8(int address) { - if (Settings.checkHWOverlap && null != read16Callbacks.get(address & ~1)) { - throw new AssertionError("8 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (Settings.checkHWOverlap && null != read32Callbacks.get(address & ~3)) { - throw new AssertionError("8 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); - } - int rc = hw[(address & HW_MASK) >> 2]; - if (logUnknownDebug) { - logUnknown.debug("unknown hwRead8 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 2)); - } - rc >>= ((address & 3) << 3); - return rc & 0xff; - } - - public static void defaultWrite8(final int address, int value) { - if (Settings.checkHWOverlap && null != write16Callbacks.get(address & ~1)) { - throw new AssertionError("8 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); - } - if (Settings.checkHWOverlap && null != write32Callbacks.get(address & ~3)) { - throw new AssertionError("8 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); - } - int mask; - int nvalue; - switch (address & 3) { - case 0: - mask = 0xffffff00; - nvalue = (value & 0xff); - break; - case 1: - mask = 0xffff00ff; - nvalue = (value & 0xff) << 8; - break; - case 2: - mask = 0xff00ffff; - nvalue = (value & 0xff) << 16; - break; - default: - mask = 0x00ffffff; - nvalue = value << 24; - break; - } - if (logUnknownDebug) { - logUnknown.debug("unknown hwWrite8 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 8)); - } - hw[(address & HW_MASK) >> 2] = (hw[(address & HW_MASK) >> 2] & mask) | nvalue; - } - } - - public int[] getMainRAM() { - return ram; - } - - @Override - public String getMainStaticInterfaceClassName() { - // Defaults to name of us, so override to push static methods to subclass - return AddressSpaceImpl.class.getName(); - } - - @Override - public String getHardwareStaticInterfaceClassName() { - // Defaults to name of us, so override to push static methods to subclass - // Note we don't dereference the class since it is generated (potentially later) - return HARDWARE_CLASS; - } -} \ No newline at end of file diff --git a/src/runtime/java/org/jpsx/runtime/components/core/CoreComponentConnections.java b/src/runtime/java/org/jpsx/runtime/components/core/CoreComponentConnections.java deleted file mode 100644 index c9b13cc..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/CoreComponentConnections.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.jpsx.api.CPUListener; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceListener; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.cpu.*; -import org.jpsx.api.components.core.dma.DMAChannelOwner; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.irq.IRQOwner; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.bootstrap.connection.MultipleConnection; -import org.jpsx.bootstrap.connection.SimpleConnection; - -public class CoreComponentConnections { - public static final SimpleConnection R3000 = SimpleConnection.create("R3000", R3000.class); - public static final SimpleConnection SCP = SimpleConnection.create("SCP", SCP.class); - public static final SimpleConnection QUARTZ = SimpleConnection.create("QUARTZ", Quartz.class); - public static final SimpleConnection SCHEDULER = SimpleConnection.create("Scheduler", Scheduler.class); - public static final SimpleConnection ADDRESS_SPACE = SimpleConnection.create("Address Space", AddressSpace.class); - public static final SimpleConnection IRQ_CONTROLLER = SimpleConnection.create("IRQ Controller", IRQController.class); - public static final SimpleConnection DMA_CONTROLLER = SimpleConnection.create("DMA Controller", DMAController.class); - public static final SimpleConnection NATIVE_COMPILER = SimpleConnection.create("Native Compiler", NativeCompiler.class); - - public static final MultipleConnection CPU_LISTENERS = MultipleConnection.create("CPU Listeners", CPUListener.class); - public static final MultipleConnection INSTRUCTION_PROVIDERS = MultipleConnection.create("Instruction Providers", InstructionProvider.class); - public static final MultipleConnection ADDRESS_SPACE_LISTENERS = MultipleConnection.create("Address Space Listeners", AddressSpaceListener.class); - public static final MultipleConnection IRQ_OWNERS = MultipleConnection.create("IRQ Owners", IRQOwner.class); - public static final MultipleConnection DMA_CHANNEL_OWNERS = MultipleConnection.create("DMA Channel Owners", DMAChannelOwner.class); - public static final MultipleConnection ALL_MEMORY_MAPPED = MultipleConnection.create("Memory Mapped", MemoryMapped.class); - public static final MultipleConnection ALL_POPULATORS = MultipleConnection.create("Memory Populators", Runnable.class); - public static final MultipleConnection POLL_BLOCK_LISTENERS = MultipleConnection.create("Poll Block Listeners", PollBlockListener.class); -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java b/src/runtime/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java deleted file mode 100644 index c480dd9..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.dma.DMAChannelOwner; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.runtime.util.MiscUtil; - -public abstract class DMAChannelOwnerBase implements DMAChannelOwner { - public static final Logger log = Logger.getLogger(DMAControllerImpl.CATEGORY); - private DMAController dmaController; - - public abstract int getDMAChannel(); - - - public void register(DMAController controller) { - log.info("Registering channel " + getName()); - dmaController = controller; - controller.registerDMAChannel(this); - } - - public String getName() { - return "DMA device " + getDMAChannel(); - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - if (DMAControllerImpl.debugDMA) - System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - signalTransferComplete(); - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if (DMAControllerImpl.debugDMA) - System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - signalTransferComplete(); - } - - public void cancelDMATransfer(int ctrl) { - if (DMAControllerImpl.debugDMA) System.out.println("cancel " + getName() + " DMA transfer"); - } - - public final void signalTransferComplete() { - dmaController.dmaChannelTransferComplete(this); - } - - public final void signalTransferComplete(boolean interrupt) { - dmaController.dmaChannelTransferComplete(this, interrupt); -// Console.println( getName()+" transfer complete"); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/DMAControllerImpl.java b/src/runtime/java/org/jpsx/runtime/components/core/DMAControllerImpl.java deleted file mode 100644 index dbdede0..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/DMAControllerImpl.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.dma.DMAChannelOwner; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.runtime.JPSXMachine; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.util.MiscUtil; - -// todo synch of DMA address control -// - -// TODO check DMA_ICR - what is bit 23? - what are low bits? - -public class DMAControllerImpl extends SingletonJPSXComponent implements DMAController, MemoryMapped { - protected static final String CATEGORY = "DMA"; - private static final Logger log = Logger.getLogger(CATEGORY); -//$1f801080 DMA channel 0 MDECin -//$1f801090 DMA channel 1 MDECout -//$1f8010a0 DMA channel 2 GPU (lists + image data) -//$1f8010b0 DMA channel 3 CDrom -//$1f8010c0 DMA channel 4 SPU -//$1f8010d0 DMA channel 5 PIO -//$1f8010e0 DMA channel 6 OTC (reverse clear OT) - - protected static final String CLASS = DMAControllerImpl.class.getName(); - - // todo settings - public static final boolean debugDMA = false; - private static AddressSpace addressSpace; - - private static final int ADDR_DMA_PCR = 0x1f8010f0; - private static final int ADDR_DMA_ICR = 0x1f8010f4; - private static final int CHANNEL_COUNT = 7; - private static final int DMA_CTRL_TO_DEVICE = 0x00000001; - private static final int DMA_CTRL_BUSY = 0x01000000; - - private static final int ADDR_DMA0_ADDR = 0x1f801080; - private static final int ADDR_DMA0_SIZE = 0x1f801084; - private static final int ADDR_DMA0_CTRL = 0x1f801088; - - private static final DMAChannelOwner[] dmaChannelOwners = new DMAChannelOwner[CHANNEL_COUNT]; - - private static int pcr; - private static int icr; - - private static IRQ irq; - - - public DMAControllerImpl() { - super("JPSX DMA Controller"); - } - - private static class IRQ extends IRQOwnerBase { - public IRQ() { - super(IRQController.IRQ_DMA, "DMA"); - } - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.DMA_CONTROLLER.set(this); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); - machine.addInitializer(JPSXMachine.PRIORITY_DMA_CONTROLLER, new Runnable() { - public void run() { - log.info("Initializing DMA channels..."); - // get all DMAChannels to register - CoreComponentConnections.DMA_CHANNEL_OWNERS.resolve().register(DMAControllerImpl.this); - } - }); - irq = new IRQ(); - CoreComponentConnections.IRQ_OWNERS.add(irq); - } - - public void registerAddresses(AddressSpaceRegistrar registrar) { - registrar.registerWrite32Callback(ADDR_DMA_ICR, DMAControllerImpl.class, "dmaICRWrite32", true); - registrar.registerWrite32Callback(ADDR_DMA_PCR, DMAControllerImpl.class, "dmaPCRWrite32"); - registrar.registerRead32Callback(ADDR_DMA_ICR, DMAControllerImpl.class, "dmaICRRead32", true); - registrar.registerRead32Callback(ADDR_DMA_PCR, DMAControllerImpl.class, "dmaPCRRead32", true); - for (int i = 0; i < CHANNEL_COUNT; i++) { - if (dmaChannelOwners[i] != null) { - registrar.registerWrite32Callback(ADDR_DMA0_CTRL + i * 0x10, DMAControllerImpl.class, "dmaChannelCtrlWrite32"); - } - } - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - } - - public void registerDMAChannel(DMAChannelOwner owner) { - int channel = owner.getDMAChannel(); - dmaChannelOwners[channel] = owner; - } - - public static void dmaICRWrite32(int address, int value, int mask) { - assert address == ADDR_DMA_ICR; - - int oldICR = icr; - // mask off dma channels' interrupt pending bits - int newICR = ((icr & ~value) & 0xff000000) | (value & 0xffffff); - // only affect the bits which were actually written by the cpu - newICR = (oldICR & ~mask) | (newICR & mask); - - // todo what does bit 31 mean - i've seen *value = (*value & 0x00ffffff)|0x88000000; - if (debugDMA) { - if ((oldICR & 0xffff) != (newICR & 0xffff)) { - log.warn("??? DMA ICR: low bits changed from " + MiscUtil.toHex(oldICR & 0xffff, 4) + " to " + MiscUtil.toHex(newICR & 0xffff, 4)); - } - int changed = newICR ^ oldICR; - for (int i = 0; i < 8; i++) { - if (0 != (changed & (1 << (16 + i)))) { - if (0 != (newICR & (1 << (16 + i)))) { - System.out.println("DMA ICR: Enabling DMA IRQ for channel " + i); - } else { - System.out.println("DMA ICR: Disabling DMA IRQ for channel " + i); - } - } - } - } - icr = newICR; - } - - public static int dmaICRRead32(int address) { - return icr; - } - - public static int dmaPCRRead32(int address) { - return pcr; - } - - public static void dmaPCRWrite32(int address, int value) { - // todo is this true, perhaps bit3 per channel - // is whether to have any effect on that channel - if (debugDMA) { - int changed = pcr ^ value; - System.out.println("DMA PCR " + MiscUtil.toHex(value, 8)); - for (int i = 0; i < 8; i++) { - if (0 != (changed & (1 << (3 + i * 4)))) { - if (0 != (value & (1 << (3 + i * 4)))) { - System.out.println("DMA PCR: Enabling DMA channel " + i); - } else { - System.out.println("DMA PCR: Disabling DMA channel " + i); - } - } - } - } - pcr = value; - } - - public static void dmaChannelCtrlWrite32(int address, int ctrl) { - int channel = (address - ADDR_DMA0_CTRL) / 0x10; - //ASSERT( INVALID_PARAMETER, channel>=0, ""); - //ASSERT( INVALID_PARAMETER, channel> 16) & 0xffff; - ; - if ((ctrl & DMA_CTRL_TO_DEVICE) != 0) { - dmaChannelOwners[channel].beginDMATransferToDevice(base, blocks, blockSize, ctrl); - } else { - dmaChannelOwners[channel].beginDMATransferFromDevice(base, blocks, blockSize, ctrl); - } - } else { - dmaChannelOwners[channel].cancelDMATransfer(ctrl); - } - } else { - if ((ctrl & DMA_CTRL_BUSY) != 0) { - if ((ctrl & DMA_CTRL_TO_DEVICE) != 0) { - System.out.println("DMA to Unknown channel " + channel); - } else { - System.out.println("DMA from Unknown channel " + channel); - } - } else { - System.out.println("DMA cancel Unknown channel " + channel); - } - } - } - - public void dmaChannelTransferComplete(DMAChannelOwner owner) { - dmaChannelTransferComplete(owner, true); - } - - public void dmaChannelTransferComplete(DMAChannelOwner owner, boolean interrupt) { - int channel = owner.getDMAChannel(); - //ASSERT( INVALID_PARAMETER, channel>=0, ""); - //ASSERT( INVALID_PARAMETER, channel. - */ -package org.jpsx.runtime.components.core; - -import org.jpsx.api.CPUListener; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.runtime.JPSXComponent; - -/** - * Simple JDK5 nanotime quartz - */ -public class DefaultQuartz extends JPSXComponent implements Quartz, CPUListener { - private long base; - private long stoppedAt; - - public void init() { - super.init(); - base = System.nanoTime(); - cpuPaused(); - CoreComponentConnections.QUARTZ.set(this); - CoreComponentConnections.CPU_LISTENERS.add(this); - } - - public DefaultQuartz() { - super("JPSX System.nanoTime() Quartz"); - } - - public synchronized long nanoTime() { - if (stoppedAt != 0L) return stoppedAt - base; - return System.nanoTime() - base; - } - - public long bestGranularity() { - // todo we need to verify this on different platforms - return 1L; - } - - public long nanoTime(long granularity) { - // for now - return nanoTime(); - } - - public synchronized void cpuResumed() { - if (stoppedAt != 0L) { - base += System.nanoTime() - stoppedAt; - stoppedAt = 0L; - } - } - - public synchronized void cpuPaused() { - if (stoppedAt == 0L) { - stoppedAt = System.nanoTime(); - // would be VERY unlucky! - if (stoppedAt == 0L) stoppedAt = 1L; - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/IRQControllerImpl.java b/src/runtime/java/org/jpsx/runtime/components/core/IRQControllerImpl.java deleted file mode 100644 index 67d290f..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/IRQControllerImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.cpu.SCP; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.irq.IRQOwner; -import org.jpsx.runtime.JPSXMachine; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.SingletonJPSXComponent; - -// todo threading -public class IRQControllerImpl extends SingletonJPSXComponent implements MemoryMapped, IRQController { - static final String CATEGORY = "IRQ"; - private static final Logger log = Logger.getLogger(CATEGORY); - - private static int IRQ_COUNT = 8; - private static IRQOwner[] owners = new IRQOwner[IRQ_COUNT]; - - private static final int ALL_INTERRUPTS = 0xff; - - private static final int ADDR_IRQ_REQUEST = 0x1f801070; - private static final int ADDR_IRQ_MASK = 0x1f801074; - - private static int irqRequest; - private static int irqMask; - private static SCP scp; - - public IRQControllerImpl() { - super("JPSX IRQ Controller"); - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.IRQ_CONTROLLER.set(this); - JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); - machine.addInitializer(JPSXMachine.PRIORITY_IRQ_CONTROLLER, new Runnable() { - public void run() { - log.info("Initializing IRQ owners..."); - // get all IRQOwners to register - CoreComponentConnections.IRQ_OWNERS.resolve().register(IRQControllerImpl.this); - } - }); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - scp = CoreComponentConnections.SCP.resolve(); - } - - public void registerAddresses(AddressSpaceRegistrar registrar) { - registrar.registerWrite32Callback(ADDR_IRQ_REQUEST, IRQControllerImpl.class, "irqRequestWrite32", true); - registrar.registerRead32Callback(ADDR_IRQ_REQUEST, IRQControllerImpl.class, "irqRequestRead32", true); - - registrar.registerWrite32Callback(ADDR_IRQ_MASK, IRQControllerImpl.class, "irqMaskWrite32", true); - registrar.registerRead32Callback(ADDR_IRQ_MASK, IRQControllerImpl.class, "irqMaskRead32", true); - } - - public void registerIRQOwner(IRQOwner owner) { - int irq = owner.getIRQ(); - owners[irq] = owner; - } - - public static synchronized void irqRequestWrite32(int addr, int value, int mask) { - irqRequest &= (~mask) | (value & mask); - updateInterruptLine(); - } - - public static int irqRequestRead32(int addr) { - return irqRequest; - } - - public static void irqMaskWrite32(int addr, int value, int mask) { - irqMask = (irqMask & ~mask) | (value & mask); - } - - public static int irqMaskRead32(int addr) { - return irqMask; - } - - @Override - public void raiseIRQ(int irq) { - _raiseIRQ(irq); - } - - public static synchronized void _raiseIRQ(int irq) { - irqRequest |= (1 << irq); - updateInterruptLine(); - } - - private static int oldRequest; - - private static void updateInterruptLine() { - assert Thread.holdsLock(IRQControllerImpl.class); - int changes = oldRequest ^ irqRequest; - oldRequest = irqRequest; - int irq = 0; - while (irq < IRQ_COUNT && changes != 0) { - if (0 != (changes & 1)) { - IRQOwner owner = owners[irq]; - if (owner != null) { - if (0 != (irqRequest & (1 << irq))) { - owner.irqSet(); - } else { - owner.irqCleared(); - } - } - } - changes >>= 1; - irq++; - } - scp.setInterruptLine(2, 0 != ((irqMask & irqRequest) & ALL_INTERRUPTS)); - } - - public int getIRQRequest() { - return irqRequest; - } - - public int getIRQMask() { - return irqMask; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/IRQOwnerBase.java b/src/runtime/java/org/jpsx/runtime/components/core/IRQOwnerBase.java deleted file mode 100644 index a2fc69f..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/IRQOwnerBase.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.irq.IRQOwner; - -public abstract class IRQOwnerBase implements IRQOwner { - public static final Logger log = Logger.getLogger(IRQControllerImpl.CATEGORY); - protected int irq; - protected String name; - private IRQController controller; - - public IRQOwnerBase(int irq, String name) { - this.irq = irq; - this.name = name; - } - - public void register(IRQController controller) { - this.controller = controller; - log.info("registering IRQ " + getName()); - controller.registerIRQOwner(this); - } - - public final int getIRQ() { - return irq; - } - - public final String getName() { - return name; - } - - public void raiseIRQ() { - controller.raiseIRQ(getIRQ()); - } - - // in case the device needs to know - public void irqSet() { - } - - // in case the device needs to know - public void irqCleared() { - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/MTScheduler.java b/src/runtime/java/org/jpsx/runtime/components/core/MTScheduler.java deleted file mode 100644 index 59cac1e..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/MTScheduler.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.cpu.PollBlockListener; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.ScheduledAction; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.runtime.SingletonJPSXComponent; - -public class MTScheduler extends SingletonJPSXComponent implements Scheduler { - private static final Logger log = Logger.getLogger("Scheduler"); - private static final boolean logTraceEnabled = log.isTraceEnabled(); - - public MTScheduler() { - super("JPSX Multi-threaded Scheduler"); - } - - private Quartz quartz; - private R3000 r3000; - private PollBlockListener pollBlockListeners; - - private static TickGeneratorThread tickThread; - private static ActionThread actionThread; - - private static final Object cpuControlMonitor = new Object(); - private static volatile int cpuResumeCount; - - public void init() { - super.init(); - tickThread = new TickGeneratorThread(); - actionThread = new ActionThread(); - CoreComponentConnections.SCHEDULER.set(this); - } - - public void resolveConnections() { - super.resolveConnections(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - r3000 = CoreComponentConnections.R3000.resolve(); - pollBlockListeners = CoreComponentConnections.POLL_BLOCK_LISTENERS.resolve(); - } - - public void begin() { - tickThread.start(); - actionThread.start(); - } - - public void schedule(long time, ScheduledAction action) { - schedule(time, Quartz.MSEC, action); - } - - public void schedule(long time, long jitter, ScheduledAction action) { - if (jitter < Quartz.MSEC) { - // todo fix this via CPU - throw new IllegalStateException("jitter <1 msec not yet supported"); - } - actionThread.schedule(time, action); - } - - public boolean isScheduled(ScheduledAction action) { - // todo cope with non-action thread actions when we have them - return actionThread.isScheduled(action); - } - - public void cpuThreadWait() { - assert r3000.isExecutionThread(); - pollBlockListeners.aboutToBlock(); - int count = cpuResumeCount; - synchronized (cpuControlMonitor) { - // if we've had an interruption in the meanwhile, then we don't bother to wait - if (count == cpuResumeCount) { - try { - cpuControlMonitor.wait(); - } catch (InterruptedException e) { - } - } - } - } - - public void cpuThreadNotify() { - synchronized (cpuControlMonitor) { - cpuResumeCount++; - cpuControlMonitor.notify(); - } - } - - - /** - * high priority thread which does tight sleep(1) loop. On Win32 this keeps - * pretty good time - */ - private static class TickGeneratorThread extends Thread { - private TickGeneratorThread() { - super("JPSX Scheduler tick generator thread"); - setPriority(MAX_PRIORITY); - setDaemon(true); - } - - public void run() { - log.info("Tick generator thread starts"); - try { - for (; ;) { - actionThread.tick(); - try { - sleep(1); - } catch (InterruptedException e) { - } - } - } finally { - log.info("Tick generator thread ends"); - } - } - } - - private class ActionThread extends Thread { - private static final int MAX_ACTIONS = 64; - /** - * List of actions, not kept sorted since it is generally small; indeed we limit the size - * the list does not auto-compact instead null entries are left in the middle - */ - private ScheduledAction[] actions = new ScheduledAction[MAX_ACTIONS]; - /** - * List of scheduled times, not kept sorted since it is generally small; indeed we limit the size - * the list does not auto-compact instead null entries are left in the middle marked by 0L time. - */ - private long[] times = new long[MAX_ACTIONS]; - private int length = 0; // length of above arrays - - private volatile long wakeupTime = Long.MAX_VALUE; - - public ActionThread() { - super("JPSX Scheduler action thread"); - setPriority(NORM_PRIORITY + 2); - setDaemon(true); - } - - public void tick() { - // called by the tick generator thread, should do any signalling and return ASAP - long time = quartz.nanoTime(); - if (time < wakeupTime) return; - synchronized (this) { - // wake our potentially blocked thread up - notify(); - } - } - - public void run() { - log.info("ScheduledAction thread starts"); - for (; ;) { - long now = sleepUntilWakeupTime(); - if (logTraceEnabled) { - log.trace("Wakeup " + traceTime(now)); - } - // make one pass over the array, providing synchronized access to our data structures - // but not holding a lock during a callback - int i = 0; - for (; ;) { - ScheduledAction toRun = null; - synchronized (this) { - if (i >= length) break; - long t = times[i]; - if (t != 0L && t <= now) { - toRun = actions[i]; - assert toRun != null; - } - } - if (toRun != null) { - if (logTraceEnabled) { - log.trace("Run " + toRun); - } - long rescheduleTime = toRun.run(now); - if (logTraceEnabled) { - log.trace("Reschedule = " + traceTime(rescheduleTime)); - } - synchronized (this) { - times[i] = rescheduleTime; - if (rescheduleTime == 0L) { - actions[i] = null; - if (i == length) length--; - } - } - } - i++; - } - updateWakeupTime(); - } - } - - private synchronized void updateWakeupTime() { - long next = Long.MAX_VALUE; - if (logTraceEnabled) { - log.trace("New actions: "); - for (int i = 0; i < length; i++) { - long t = times[i]; - if (t != 0L) { - log.trace(traceTime(t) + " " + actions[i]); - } - } - } - for (int i = 0; i < length; i++) { - long t = times[i]; - if (t != 0L && t < next) next = t; - } - wakeupTime = next; - } - - private long sleepUntilWakeupTime() { - for (; ;) { - long t = quartz.nanoTime(); - if (t >= wakeupTime) return t; - synchronized (this) { - try { - wait(); - } catch (InterruptedException e) { - // we interrupt ourselves in {@link #schedule} if an action - // is inserted before the current wakeup time. - } - } - } - } - - public synchronized void schedule(long time, ScheduledAction action) { - if (logTraceEnabled) { - log.trace("Adding " + traceTime(time) + " " + action); - } - boolean added = false; - for (int i = 0; i < length; i++) { - if (actions[i] == null) { - actions[i] = action; - times[i] = time; - added = true; - } - } - if (!added) { - if (length == MAX_ACTIONS) throw new IllegalStateException("too many actions"); - actions[length] = action; - times[length++] = time; - } - if (time < wakeupTime) { - wakeupTime = time; - // interrupt the action thread, unless we are the action thread! - if (Thread.currentThread() != this) { - actionThread.interrupt(); - } - } - } - - public synchronized boolean isScheduled(ScheduledAction action) { - for (int i = 0; i < length; i++) { - if (actions[i] == action) return true; - } - return false; - } - } - - private static String traceTime(long time) { - return String.valueOf(time / Quartz.MSEC); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/R3000Impl.java b/src/runtime/java/org/jpsx/runtime/components/core/R3000Impl.java deleted file mode 100644 index 8dde2f2..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/R3000Impl.java +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.*; -import org.apache.log4j.Logger; -import org.jpsx.api.CPUControl; -import org.jpsx.api.CPUListener; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.api.components.core.ContinueExecutionException; -import org.jpsx.api.components.core.ImmediateBreakoutException; -import org.jpsx.api.components.core.ReturnFromExceptionException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceListener; -import org.jpsx.api.components.core.cpu.*; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.bootstrap.classloader.ClassModifier; -import org.jpsx.bootstrap.classloader.JPSXClassLoader; -import org.jpsx.bootstrap.connection.SimpleConnection; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.*; -import org.jpsx.runtime.util.ClassUtil; -import org.jpsx.runtime.util.MiscUtil; - -import java.lang.reflect.Modifier; -import java.util.List; -import java.util.Map; - -public final class R3000Impl extends SingletonJPSXComponent implements ClassModifier, R3000, CPUControl, InstructionRegistrar { - private static final Logger logPrintf = Logger.getLogger("PRINTF"); - private static final Logger logCache = Logger.getLogger("Cache"); - private static final Logger log = Logger.getLogger("R3000"); - - private static final String CLASS = R3000Impl.class.getName(); - private static final String UTIL_CLASS = R3000.Util.class.getName(); - private static final String DECODER_CLASS = ClassUtil.innerClassName(R3000Impl.class, "Decoder"); - - private static final String INTERPRET_SIGNATURE = "(I)V"; - private static final Class[] INTERPRET_ARGS = {int.class}; - - public static class Settings extends FinalComponentSettings { - public static final boolean debugBIOS = false; - public static final boolean traceExecutionFlow = false; - public static final boolean skipShell = false; // todo move this elsewhere - public static final boolean dumpRegsOnCall = false; - } - - private static class Refs extends FinalResolvedConnectionCache { - public static final AddressSpace addressSpace = resolve(CoreComponentConnections.ADDRESS_SPACE); - public static final SCP scp = resolve(CoreComponentConnections.SCP); - public static final Scheduler scheduler = resolve(CoreComponentConnections.SCHEDULER); - } - - // todo figure out how to do this generically - public static boolean shellHit; - - private static final int MAX_EXECUTION_DEPTH = 4; - private static final boolean[] inCompiler = new boolean[MAX_EXECUTION_DEPTH]; - private static int executionDepth = -1; - private static Map instructionDisassemblers = CollectionsFactory.newHashMap(); - - public static final int[] regs = new int[32]; - public static int reg_lo; - public static int reg_hi; - public static int reg_pc; // this is the PC if in BIOS etc, or the low 28 bits if in 0/8/A RAM. - //public static int reg_pc_upper; // value to OR with reg_pc to get true PC value.. this changes when jumping between ram banks). - - private static int delayedPCDelta = 4; - private static int interpretedJumpAndLinkTarget = -1; - private static int interpretedJumpAndLinkRetAddr = -1; - - private static int interpretedJumpTarget = -1; - private static int currentPCDelta; - - // todo revisit this; execution control interface - private static final Object cpuControlSemaphore = new Object(); - private static volatile boolean cpuCmdPending; // cpu should pause and wait for command - private static boolean cpuReadyForCommand; - private static int cpuCmd; - private static final int CMD_NOP = 0; - private static final int CMD_STEP = 1; - private static final int CMD_RUN = 2; - private static final int CMD_UPDATE_BREAKPOINTS = 3; - - private static CPUInstruction[] decoding; - private static CPUInstruction[] decodingSPECIAL; - private static CPUInstruction[] decodingREGIMM; - - private static List breakpoints = CollectionsFactory.newArrayList(); - - private static NativeCompiler compiler; - private static CPUListener executionListeners; - - private static int breakpointAdd; - private static int breakpointRemove; - - public R3000Impl() { - super("JPSX Main Processor"); - } - - @Override - public void init() { - super.init(); - RuntimeConnections.CPU_CONTROL.set(this); - CoreComponentConnections.R3000.set(this); - JPSXClassLoader.registerClassModifier(DECODER_CLASS, this); - JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); - machine.addInitializer(JPSXMachine.PRIORITY_ADD_INSTRUCTIONS, new Runnable() { - public void run() { - addInstructions(); - } - }); - CoreComponentConnections.ADDRESS_SPACE_LISTENERS.add(new AddressSpaceListener() { - public void cacheCleared() { - R3000Impl.cacheCleared(); - } - }); - } - - protected void addInstructions() { - i_invalid = new CPUInstruction("invalid", R3000Impl.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION | CPUInstruction.FLAG_INVALID); - decoding = new CPUInstruction[64]; - for (int i = 0; i < 64; i++) { - decoding[i] = i_invalid; - } - decodingSPECIAL = new CPUInstruction[64]; - for (int i = 0; i < 64; i++) { - decodingSPECIAL[i] = i_invalid; - } - decodingREGIMM = new CPUInstruction[32]; - for (int i = 0; i < 32; i++) { - decodingREGIMM[i] = i_invalid; - } - // create connection wrapper so we can close it - SimpleConnection connection = SimpleConnection.create("InstructionRegistrar", InstructionRegistrar.class); - connection.set(this); - CoreComponentConnections.INSTRUCTION_PROVIDERS.resolve().addInstructions(connection.resolve()); - CoreComponentConnections.INSTRUCTION_PROVIDERS.close(); - connection.close(); - } - -// public void registerAddresses() -// { -// // todo move this somewhere else -// AddressSpaceImpl.registerWrite8Callback( 0x1f802041, CLASS, "bootStatus"); - // } - - private static CPUInstruction i_invalid; - - public CPUInstruction getInvalidInstruction() { - return i_invalid; - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - compiler = CoreComponentConnections.NATIVE_COMPILER.peek(); - } - - public static void bootStatus(int address, int value) { - //System.out.println( "BIOS: BOOT STATUS " + value ); - } - - public CPUInstruction decodeInstruction(int ci) { - int index = ci >> 26; - CPUInstruction rc; - switch (index) { - case 0: - rc = decodingSPECIAL[ci & 0x3f]; - break; - case 1: - rc = decodingREGIMM[Util.bits_rt(ci)]; - break; - default: - rc = decoding[index & 0x3f]; - break; - } - return rc.subDecode(ci); - } - - public void setInstructionDisassembler(String name, CPUInstructionDisassembler disassembler) { - instructionDisassemblers.put(name, disassembler); - } - - public void setInstruction(int index, CPUInstruction inst) { - decoding[index] = inst; - } - - public void setSPECIALInstruction(int index, CPUInstruction inst) { - decodingSPECIAL[index] = inst; - } - - public void setREGIMMInstruction(int index, CPUInstruction inst) { - decodingREGIMM[index] = inst; - } - - private static void checkInstruction(CPUInstruction inst) { - // todo decide whether to put this back; needs a flag for those instructions with subdecode - try { - java.lang.reflect.Method method = inst.getInterpreterClass().getDeclaredMethod(inst.getInterpretMethodName(), INTERPRET_ARGS); - if (!Modifier.isStatic(method.getModifiers())) { - throw new InvalidConfigurationException("Interpreter method " + inst.getInterpretMethodName() + " on class " + inst.getInterpreterClass().getName() + " is not static"); - } - } catch (Exception e) { - throw new InvalidConfigurationException("Missing correct interpreter method " + inst.getInterpretMethodName() + " on class " + inst.getInterpreterClass().getName(), e); - } - } - - /** - * The methods in this class are replaced by the morph method - * above at runtime - */ - private static class Decoder { - public static void invokeSpecial(final int ci) { - // this method is runtime generated - throw new EmulationException("should have been generated"); - } - - public static void invokeRegImm(final int ci) { - // this method is runtime generated - throw new EmulationException("should have been generated"); - } - - public static void invoke(final int ci) { - // this method is runtime generated - throw new EmulationException("should have been generated"); - } - } - - private static Thread executionThread; - - public boolean isExecutionThread() { - return Thread.currentThread() == executionThread; - } - - public void begin() { - executionListeners = CoreComponentConnections.CPU_LISTENERS.resolve(); - executionThread = new R3000Thread(); - cpuCmdPending = true; // thread should configure and wait for a cmd - executionThread.start(); - } - - public static void shutdown() { - //pause(); - //m_cpuLaunch = false; - //synchronized (m_cpuControlSemaphore) { - // m_cpuControlSemaphore.notify(); - //} - } - - /** - * If not called from the execution thread, then this blocks until the execution is paused; - * otherwise it - */ - public void pause() { - sendCmd(CMD_NOP); - } - - /** - * Sends a command to the execution thread. Generally this is synchronous, and waits for the command to be acknowledged; - * however if called from the execution thread itself, then this method will throw an exception to return to safely - * return control to the command handling code. PC will be at the currently executing instruction, but side effects - * may already have happened. - * - * @param cmd - */ - private static void sendCmd(int cmd) { - //System.out.println("main: sendCmd "+cmd); - synchronized (cpuControlSemaphore) { - cpuCmdPending = true; - if (Thread.currentThread() != executionThread) { - // normally fine just to have the execution thread make itself ready for a command as soon as possible - CoreComponentConnections.R3000.resolve().requestBreakout(); - if (!cpuReadyForCommand) { - //System.out.println("main: waiting for cpu to be ready"); - try { - cpuControlSemaphore.wait(); - } catch (InterruptedException e) { - } - } - cpuCmd = cmd; - //System.out.println("main: informing cpu of cmd"); - cpuControlSemaphore.notify(); - //System.out.println("main: waiting for cpu to acknowledge cmd"); - try { - cpuControlSemaphore.wait(); - } catch (InterruptedException e) { - } - } else { - // by definition the execution thread is not ready for a command - assert !cpuReadyForCommand; - cpuCmd = cmd; - // This won't return, as we are the execution thread, and this must throw - // an exception to achieve its goals - CoreComponentConnections.R3000.resolve().immediateBreakout(); - } - } - } - - public void step() { - sendCmd(CMD_STEP); - // wait for step to complete by sending another cmd - sendCmd(CMD_NOP); - } - - public void go() { - sendCmd(CMD_RUN); - } - - private static void cpuWaitForCmd() { - executionListeners.cpuPaused(); - synchronized (cpuControlSemaphore) { - boolean done = false; - while (!done) { - //System.out.println("cpu: signalling read for cmd"); - // notify that we're ready for a command - cpuReadyForCommand = true; - cpuControlSemaphore.notify(); - - //System.out.println("cpu: waiting for cmd"); - try { - cpuControlSemaphore.wait(); - } catch (InterruptedException e) { - } - switch (cpuCmd) { - case CMD_NOP: - cpuCmdPending = false; - break; - case CMD_RUN: - done = true; - cpuCmdPending = false; - executionListeners.cpuResumed(); - break; - case CMD_STEP: - done = true; - cpuCmdPending = true; - break; - case CMD_UPDATE_BREAKPOINTS: - updateBreakpoints(); - cpuCmdPending = false; - break; - } - cpuReadyForCommand = false; - cpuControlSemaphore.notify(); - //System.out.println("cpu: acknowledging cmd"); - } - } - } - - // todo revisit this - private class R3000Thread extends Thread { - public R3000Thread() { - super("Execution thread"); - synchronized (cpuControlSemaphore) { - cpuReadyForCommand = false; - } - } - - public void run() { - log.info("Processor thread starts"); - executeFromPC(); - log.info("Processor thread ends"); - } - } - - public final void executeFromPC() { - executionDepth++; - assert executionDepth < MAX_EXECUTION_DEPTH; - - delayedPCDelta = currentPCDelta = 4; - - while (true) { - try { - interpreterLoop(); - } catch (ContinueExecutionException e) { - if (inCompiler[executionDepth]) { - compiler.exceptionInCompiler(e); - inCompiler[executionDepth] = false; - } - if (e.skipCurrentInstruction()) { - reg_pc += 4; - } - // System.out.println("... broke out to execute loop"); - // continue from where we were! - delayedPCDelta = currentPCDelta = 4; - } catch (ReturnFromExceptionException rfe) { - if (inCompiler[executionDepth]) { - compiler.exceptionInCompiler(rfe); - inCompiler[executionDepth] = false; - } - //System.out.println("... returned from exception"); - assert delayedPCDelta == 4 : "rfe delayedPCDelta should be 4"; - currentPCDelta = 4; - // on return from exception we exit loop - break; - } catch (Throwable t) { - boolean ok = false; - if (inCompiler[executionDepth]) { - ok = compiler.exceptionInCompiler(t); - inCompiler[executionDepth] = false; - } - if (!ok) { - t.printStackTrace(); - System.out.println("Execution paused due to Java exception!"); - cpuWaitForCmd(); - } - } - } - executionDepth--; - } - - // should ready this only - public static boolean breakout; - - public void requestBreakout() { - breakout = true; - if (compiler != null) { - compiler.interrupt(); - } - } - - private void handleInterpreterBreakout() { - assert isExecutionThread(); - // all breakouts should cause another breakout if they wish to have another one - breakout = false; - if (Refs.scp.shouldInterrupt()) { - restoreInterpreterState(); - Refs.scp.signalInterruptException(); - } - } - - public final void compilerInterrupted() { - handleInterpreterBreakout(); - if (cpuCmdPending) { - // need to return to CPU loop - immediateBreakout(); - } - } - - @Override - public final void immediateBreakout() { - assert isExecutionThread(); - restoreInterpreterState(); - throw new ImmediateBreakoutException(); - } - - public final void interpreterLoop() { - if (Settings.traceExecutionFlow) { - log.trace("Enter interpreter loop at " + MiscUtil.toHex(reg_pc, 8)); - } - do { - boolean checkBreakout = (currentPCDelta != 4) && (delayedPCDelta == 4); // only check interrupt on non linear flow - - currentPCDelta = delayedPCDelta; - delayedPCDelta = 4; - - boolean shouldWait = cpuCmdPending; - - // not using for each since we want to avoid iterator allocation - for (int i = 0; i < breakpoints.size(); i++) { - if (reg_pc == breakpoints.get(i)) { - shouldWait = true; - break; - } - } - - if (shouldWait) { - cpuWaitForCmd(); - } - - - if (checkBreakout && breakout) { - // not sure if this is the right place for this check; basically we don't want to take interrupts while - // we're stepping - if (!cpuCmdPending) { - handleInterpreterBreakout(); - } - } - - if (reg_pc == interpretedJumpAndLinkTarget) { - if (Settings.skipShell) { - if (!shellHit && reg_pc == 0x80030000) { - shellHit = true; - reg_pc = regs[31]; - } - } - if (Settings.dumpRegsOnCall && shouldDumpRegs(reg_pc)) { - dumpRegs(); - } - // interpreted jalr/jal got us to this PC - if (false && 0 != Refs.scp.currentExceptionType()) { - log.trace("Call " + MiscUtil.toHex(reg_pc, 8) + " from " + MiscUtil.toHex(regs[31] - 8, 8)); - } - - interpretedJumpAndLinkTarget = -1; - - if (!shouldWait && compiler != null) { - - if (Settings.traceExecutionFlow) { - log.trace("calling compiler for " + MiscUtil.toHex(reg_pc, 8)); - } - - inCompiler[executionDepth] = true; - if (compiler.jumpAndLink(reg_pc, interpretedJumpAndLinkRetAddr)) { - // we expect the registers are already restored - inCompiler[executionDepth] = false; - - if (Settings.traceExecutionFlow) { - log.trace("returning from level0 unit"); - } - - // on returning from a call, it must have been a JR, so we can't be in a delay slot - delayedPCDelta = 4; - continue; - } - } - if (Settings.traceExecutionFlow) { - System.out.println("staying in interpreter for " + MiscUtil.toHex(reg_pc, 8)); - } - // todo move this - if (Settings.debugBIOS) { - // todo, register functions s.t. the compiler can insert these also! - if (reg_pc == 0x00001b44) { - debugDeliverEvent(); - } - - if (reg_pc == 0xa0) { - debugA0(); - } - - if (reg_pc == 0xb0) { - debugB0(); - } - - if (reg_pc == 0xc0) { - debugC0(); - } - - } - - // todo move this - if (reg_pc == 0xbfc018e0) { - debugPrintf(); - } - } - - if (reg_pc == interpretedJumpTarget && reg_pc == regs[31]) { - if (false && 0 != Refs.scp.currentExceptionType()) { - System.out.println("return to " + MiscUtil.toHex(regs[31], 8)); - } - if (Settings.traceExecutionFlow) { - System.out.println("r31 return to " + MiscUtil.toHex(reg_pc, 8)); - } - } - - // the virtual invokation here isn't much of a problem compared to the speed of the interpreter - int ci = Refs.addressSpace.internalRead32(reg_pc); - - Decoder.invoke(ci); - - assert regs[0] == 0 : "instruction changed r0"; - - reg_pc += currentPCDelta; - } while (true); - } - - public static boolean shouldDumpRegs(int addr) { - if (Settings.dumpRegsOnCall) { - //return addr==0x80072c1c || addr==0x800729ac || addr==0x8001a504 || addr==0x80019988 || addr==0x800198d8 || addr==0x8003c05c || addr==0x8003a62c; - } - return false; - } - - public static void tempHackForException() { - currentPCDelta = 0; - delayedPCDelta = 4; - } - - public void addBreakpoint(int address) { - // todo fix this shit - breakpointAdd = address; - breakpointRemove = -1; - sendCmd(CMD_UPDATE_BREAKPOINTS); - } - - - public void removeBreakpoint(int address) { - // todo fix this shit - breakpointAdd = -1; - breakpointRemove = address; - sendCmd(CMD_UPDATE_BREAKPOINTS); - } - - private static void updateBreakpoints() { - if (breakpointAdd != -1) { - if (!breakpoints.contains(breakpointAdd)) { - breakpoints.add(0, breakpointAdd); - if (compiler != null) { - compiler.addBreakpoint(breakpointAdd); - } - } - breakpointAdd = -1; - } - if (breakpointRemove != -1) { - if (breakpointRemove >= 0 && breakpointRemove < breakpoints.size()) { - int address = breakpoints.remove(breakpointRemove); - if (compiler != null) { - compiler.removeBreakpoint(address); - } - } else { - int index = breakpoints.indexOf(breakpointRemove); - if (index != -1) { - breakpoints.remove(index); - if (compiler != null) { - compiler.removeBreakpoint(breakpointRemove); - } - } - } - breakpointRemove = -1; - } - } - - public int[] getBreakpoints() { - int[] rc = new int[breakpoints.size()]; - for (int i = 0; i < rc.length; i++) { - rc[i] = breakpoints.get(i); - } - return rc; - } - - // move this elswehere - private static int getParam(int index) { - if (index < 4) { - return regs[4 + index]; - } - return Refs.addressSpace.read32(regs[R_SP] + 0x10 + 4 * (index - 4)); - } - - // move this elsewhere - public static void debugPrintf() { - if (logPrintf.isInfoEnabled()) { - String fmt = readString(regs[4]); - StringBuilder s = new StringBuilder(); - - int param = 1; - int perc = fmt.indexOf('%'); - while (perc != -1) { - s.append(fmt.substring(0, perc)); - - boolean leadingZero = false; - boolean firstDigit = false; - int digits = 0; - - outer: - do { - int c = fmt.charAt(++perc); - switch (c) { - case's': - s.append(readString(getParam(param++))); - break outer; - case'x': - if (digits != 0) { - if (leadingZero) { - s.append(MiscUtil.toHex(getParam(param++), digits)); - } else { - s.append(MiscUtil.toHex(getParam(param++), digits)); - } - } else { - s.append(Integer.toHexString(getParam(param++))); - } - break outer; - case'd': - s.append(getParam(param++)); - break outer; - case'.': - case'-': - case'h': - break; - default: - if (c >= '0' && c <= '9') { - if (firstDigit) { - leadingZero = c == '0'; - firstDigit = false; - } - digits = digits * 10 + (int) (c - '0'); - } else { - break outer; - } - break; - } - } while (true); - - fmt = fmt.substring(perc + 1); - perc = fmt.indexOf('%'); - } - s.append(fmt); - String str = s.toString(); - while (str.endsWith("\n") || str.endsWith("\r")) { - str = str.substring(0, str.length() - 1); - } - logPrintf.info(str); - } - } - - private static String readString(int address) { - String rc = ""; - do { - int val = Refs.addressSpace.read8(address++); - if (val != 0) { - rc += (char) val; - } else { - break; - } - } while (true); - return rc; - } - - public static void debugA0() { - switch (regs[9]) { - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - // boring c library - break; - case 0x3f: // printf - // handled elsewhere - break; - default: - System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: A0 " + MiscUtil.toHex(regs[9], 2)); - } - } - - public static void debugB0() { - switch (regs[9]) { - case 0x3d: // putchar - // part of printf (too verbose) - break; - default: - System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: B0 " + MiscUtil.toHex(regs[9], 2)); - } - } - - public static void debugC0() { - switch (regs[9]) { - default: - System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: C0 " + MiscUtil.toHex(regs[9], 2)); - } - } - - public static void debugDeliverEvent() { - System.out.println(MiscUtil.toHex(regs[31], 8) + "BIOS: DeliverEvent " + MiscUtil.toHex(regs[4], 8) + ", " + MiscUtil.toHex(regs[5], 8) + ", " + MiscUtil.toHex(regs[6], 8)); - } - - private static int totalBreakouts; - - /** - * called when the instruction cache is flushed - */ - private static void cacheCleared() { - // remove any RAM based code units -/* for( Iterator i = codeUnits.keySet().iterator(); i.hasNext(); ) { - Integer a = (Integer)i.next(); - int address = a.intValue(); - if (!AddressSpaceImpl.isBIOS( address)) { - i.remove(); - } - } */ - totalBreakouts++; - if (compiler != null) { - compiler.clearCache(); - if (inCompiler[executionDepth]) { - ContinueExecutionException e = ContinueExecutionException.SKIP_CURRENT; - if (logCache.isDebugEnabled()) { - logCache.debug("cacheCleared in compiler depth=" + executionDepth + "; throwing ContinueExecutionException..."); - } - throw e; - } else { - if (logCache.isDebugEnabled()) { - logCache.debug("cacheCleared in interpreter depth=" + executionDepth + "; continuing interpreting..."); - } - } - } - } - - public ClassGen modifyClass(String classname, ClassGen cgen) { - ConstantPoolGen cp = cgen.getConstantPool(); - - // regular decode - - Method m = cgen.containsMethod("invoke", "(I)V"); - MethodGen mg = JPSXClassLoader.emptyMethod(cgen, m); - - InstructionList il = mg.getInstructionList(); - il.append(new ILOAD(0)); - il.append(new BIPUSH((byte) 26)); - il.append(new ISHR()); - - InstructionHandle[] handles = new InstructionHandle[64]; - int[] matches = new int[64]; - for (int i = -32; i < 32; i++) { - int j = i; - if (j < 0) j = j + 64; - matches[i + 32] = i; - CPUInstruction inst = decoding[j]; - handles[i + 32] = il.append(new ILOAD(0)); - switch (j) { - case 0: - il.append(new INVOKESTATIC(cp.addMethodref(DECODER_CLASS, "invokeSpecial", "(I)V"))); - break; - case 1: - il.append(new INVOKESTATIC(cp.addMethodref(DECODER_CLASS, "invokeRegImm", "(I)V"))); - break; - default: - checkInstruction(inst); - il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); - break; - } - il.append(new RETURN()); - } - InstructionHandle def = il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); - il.append(new RETURN()); - il.insert(handles[0], new TABLESWITCH(matches, handles, def)); - mg.setMaxLocals(); - mg.setMaxStack(); - cgen.replaceMethod(m, mg.getMethod()); - il.dispose(); - - // special decode - - m = cgen.containsMethod("invokeSpecial", "(I)V"); - mg = JPSXClassLoader.emptyMethod(cgen, m); - - il = mg.getInstructionList(); - il.append(new ILOAD(0)); - il.append(new BIPUSH((byte) 63)); - il.append(new IAND()); - - handles = new InstructionHandle[64]; - matches = new int[64]; - for (int i = 0; i < 64; i++) { - matches[i] = i; - CPUInstruction inst = decodingSPECIAL[i]; - handles[i] = il.append(new ILOAD(0)); - checkInstruction(inst); - il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); - il.append(new RETURN()); - } - def = il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); - il.append(new RETURN()); - il.insert(handles[0], new TABLESWITCH(matches, handles, def)); - mg.setMaxLocals(); - mg.setMaxStack(); - cgen.replaceMethod(m, mg.getMethod()); - il.dispose(); - - // regimm decode - - m = cgen.containsMethod("invokeRegImm", INTERPRET_SIGNATURE); - mg = JPSXClassLoader.emptyMethod(cgen, m); - - il = mg.getInstructionList(); - il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(UTIL_CLASS, "bits_rt", "(I)I"))); - - handles = new InstructionHandle[32]; - matches = new int[32]; - for (int i = 0; i < 32; i++) { - matches[i] = i; - CPUInstruction inst = decodingREGIMM[i]; - handles[i] = il.append(new ILOAD(0)); - checkInstruction(inst); - il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); - il.append(new RETURN()); - } - def = il.append(new ILOAD(0)); - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); - il.append(new RETURN()); - il.insert(handles[0], new TABLESWITCH(matches, handles, def)); - mg.setMaxLocals(); - mg.setMaxStack(); - cgen.replaceMethod(m, mg.getMethod()); - il.dispose(); - return cgen; - } - - public void restoreInterpreterState() { - if (inCompiler[executionDepth]) { - compiler.restoreInterpreterState(); - } - } - - // todo threading? - public final int getReg(int reg) { - if (inCompiler[executionDepth]) { - return compiler.getReg(reg); - } else { - return regs[reg]; - } - } - - public final void setReg(int reg, int val) { - if (inCompiler[executionDepth]) { - compiler.setReg(reg, val); - } else { - regs[reg] = val; - } - } - - // todo recheck this; this is a hack to avoid problems with certain versions of HotSpot (perhaps 1.4?) - private static boolean breakHotspot; - - public static final void interpret_invalid(final int ci) { - breakHotspot = false; - Refs.scp.signalReservedInstructionException(); - } - - public String disassemble(int address, int ci) { - CPUInstruction inst = decodeInstruction(ci); - CPUInstructionDisassembler disassembler = instructionDisassemblers.get(inst.getName()); - if (disassembler != null) - return disassembler.disassemble(inst, address, ci); - else - return "(" + inst.getName() + ")"; - } - - /** - * Method should be called from any code which - * is returning from blah - */ - public static void safeReturn() { - } - - // ------------- utility functions - - public static void dumpRegs() { - String s = MiscUtil.toHex(reg_pc, 8); - for (int i = 0; i < 32; i++) { - s += " " + MiscUtil.toHex(regs[i], 8); - } - System.out.println(s); - } - - /** - * Control flow instruction for use by R3000 instruction implementation - * - * @param relativeToDelay target address relative to the delay slot - */ - public void interpreterBranch(int relativeToDelay) { - delayedPCDelta = relativeToDelay; - } - - /** - * Control flow instruction for use by R3000 instruction implementation - * - * @param relativeToDelay target address relative to the delay slot - * @param target the target address - */ - public void interpreterJump(int relativeToDelay, int target) { - delayedPCDelta = relativeToDelay; - interpretedJumpTarget = target; - } - - /** - * Control flow instruction for use by R3000 instruction implementation - * - * @param relativeToDelay target address relative to the delay slot - * @param target the target address - * @param retAddr the return address - */ - public void interpreterJumpAndLink(int relativeToDelay, int target, int retAddr) { - delayedPCDelta = relativeToDelay; - interpretedJumpAndLinkTarget = target; - interpretedJumpAndLinkRetAddr = retAddr; - } - - - public int[] getInterpreterRegs() { - return regs; - } - - public final int getPC() { - return reg_pc; - } - - public final int getLO() { - return reg_lo; - } - - public final int getHI() { - return reg_hi; - } - - public final void setPC(int pc) { - reg_pc = pc; - } - - public final void setLO(int lo) { - reg_lo = lo; - } - - public final void setHI(int hi) { - reg_hi = hi; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/core/SCPImpl.java b/src/runtime/java/org/jpsx/runtime/components/core/SCPImpl.java deleted file mode 100644 index 56d1015..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/core/SCPImpl.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.core; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.ContinueExecutionException; -import org.jpsx.api.components.core.ReturnFromExceptionException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.*; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.util.MiscUtil; - -public class SCPImpl extends SingletonJPSXComponent implements SCP, InstructionProvider { - private static final Logger log = Logger.getLogger("SCP"); - - private static long debugNextSecond; - private static int vsyncsTaken; - - private static final boolean debugSCP = log.isDebugEnabled(); - - private static final int STATUS_CU_3 = 0x80000000; - private static final int STATUS_CU_2 = 0x40000000; - private static final int STATUS_CU_1 = 0x20000000; - private static final int STATUS_CU_0 = 0x10000000; - private static final int STATUS_RE = 0x02000000; // is this supported? - private static final int STATUS_BEV = 0x00400000; - private static final int STATUS_TS = 0x00200000; - private static final int STATUS_PE = 0x00100000; // parity - private static final int STATUS_CM = 0x00080000; - private static final int STATUS_PZ = 0x00080000; - private static final int STATUS_SWC = 0x00020000; - private static final int STATUS_ISC = 0x00010000; // cache - private static final int STATUS_IM7 = 0x00008000; - private static final int STATUS_IM6 = 0x00004000; - private static final int STATUS_IM5 = 0x00002000; - private static final int STATUS_IM4 = 0x00001000; - private static final int STATUS_IM3 = 0x00000800; - private static final int STATUS_IM2 = 0x00000400; - private static final int STATUS_IM1 = 0x00000200; - private static final int STATUS_IM0 = 0x00000100; - private static final int STATUS_KUO = 0x00000020; - private static final int STATUS_IEO = 0x00000010; - private static final int STATUS_KUP = 0x00000008; - private static final int STATUS_IEP = 0x00000004; - private static final int STATUS_KUC = 0x00000002; - private static final int STATUS_IEC = 0x00000001; - - private static final int STATUS_IMS = STATUS_IM7 | STATUS_IM6 | STATUS_IM5 | STATUS_IM4 | STATUS_IM3 | STATUS_IM2 | STATUS_IM1 | STATUS_IM0; - - private static final int STATUS_W = STATUS_CU_3 | STATUS_CU_2 | STATUS_CU_1 | STATUS_CU_0 | STATUS_RE | STATUS_BEV | - STATUS_TS | STATUS_PE | STATUS_CM | STATUS_PZ | STATUS_SWC | STATUS_ISC | STATUS_IMS | - STATUS_KUO | STATUS_IEO | STATUS_KUP | STATUS_IEP | STATUS_KUC | STATUS_IEC; - - private static final int CAUSE_BD = 0x80000000; - private static final int CAUSE_CE = 0x30000000; - private static final int CAUSE_CE_SHIFT = 28; - private static final int CAUSE_IP7 = 0x00008000; - private static final int CAUSE_IP6 = 0x00004000; - private static final int CAUSE_IP5 = 0x00002000; - private static final int CAUSE_IP4 = 0x00001000; - private static final int CAUSE_IP3 = 0x00000800; - private static final int CAUSE_IP2 = 0x00000400; - private static final int CAUSE_IP1 = 0x00000200; - private static final int CAUSE_IP0 = 0x00000100; - - private static final int CAUSE_CODE = 0x0000003c; - private static final int CAUSE_CODE_SHIFT = 2; - - private static final int CAUSE_W = CAUSE_IP0 | CAUSE_IP1; - - private static final int REG_INDEX = 0; - private static final int REG_RAND = 1; - private static final int REG_TLBLO = 2; - private static final int REG_BPC = 3; - private static final int REG_CTXT = 4; - private static final int REG_BPA = 5; - private static final int REG_PIDMASK = 6; - private static final int REG_DGIC = 7; - private static final int REG_BADVADDR = 8; - private static final int REG_BDAM = 9; - private static final int REG_TLBHI = 10; - private static final int REG_BPCM = 11; - private static final int REG_STATUS = 12; - private static final int REG_CAUSE = 13; - private static final int REG_EPC = 14; - private static final int REG_PRID = 15; // ID - unimplemented - - private static int status = 0; - private static int cause = 0; - - private static int errorEPC = 0; - private static int EPC = 0; - - private static boolean causeIV; - private static boolean causeBD; - private static int causeCE; - private static int causeIPS; - - private static AddressSpace addressSpace; - private static R3000 r3000; - private static Quartz quartz; - private static Scheduler scheduler; - private static IRQController irqController; - private static int[] interpreterRegs; - - public SCPImpl() { - super("JPSX System Control Processor"); - } - - public void begin() { - signalResetException(); - } - - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - r3000 = CoreComponentConnections.R3000.resolve(); - interpreterRegs = r3000.getInterpreterRegs(); - irqController = CoreComponentConnections.IRQ_CONTROLLER.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - scheduler = CoreComponentConnections.SCHEDULER.resolve(); - } - - public void addInstructions(InstructionRegistrar registrar) { - log.info("Adding COP0 instructions..."); - final CPUInstruction i_eret = new CPUInstruction("eret", SCPImpl.class, 0, CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE); - final CPUInstruction i_mfc0 = new CPUInstruction("mfc0", SCPImpl.class, 0, CPUInstruction.FLAG_WRITES_RT); - // note this needs references_pc because it can cause a return from exception exception - final CPUInstruction i_mtc0 = new CPUInstruction("mtc0", SCPImpl.class, 0, CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_REFERENCES_PC); - - CPUInstruction i_cop0 = new CPUInstruction("cop0", SCPImpl.class, 0, 0) { - public CPUInstruction subDecode(int ci) { - switch (R3000.Util.bits_rs(ci)) { - case 0: - return i_mfc0; - case 4: - return i_mtc0; - case 16: - return i_eret; - } - return r3000.getInvalidInstruction(); - } - }; - registrar.setInstruction(16, i_cop0); - } - - public static void interpret_cop0(final int ci) { - switch (R3000.Util.bits_rs(ci)) { - case 0: - interpret_mfc0(ci); - return; - case 4: - interpret_mtc0(ci); - return; - case 16: - interpret_eret(ci); - return; - } - _signalReservedInstructionException(); - } - - public static void interpret_mtc0(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int sel = ci & 0x7; - int value = interpreterRegs[rt]; - - writeRegister(rd, sel, value); - } - - public static void interpret_mfc0(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int sel = ci & 0x7; - int value = readRegister(rd, sel); - if (rt != 0) - interpreterRegs[rt] = value; - } - - private static void writeRegister(int reg, int sel, int value) { - switch ((sel << 16) + reg) { - case REG_STATUS: - status = (status & ~STATUS_W) | (value & STATUS_W); - addressSpace.enableMemoryWrite((status & STATUS_ISC) == 0); - break; - case REG_CAUSE: - cause = (cause & ~CAUSE_W) | (value & CAUSE_W); - break; - default: - if (log.isDebugEnabled()) - log.debug("SCP: write " + reg + ":" + sel + " " + MiscUtil.toHex(value, 8)); - } - } - - private static int readRegister(int reg, int sel) { - int rc = 0; - switch ((sel << 16) + reg) { - case REG_STATUS: - rc = status; - break; - case REG_CAUSE: - rc = cause; - break; - case REG_EPC: - rc = EPC; - break; - default: - if (log.isDebugEnabled()) { - log.debug("SCP: read " + reg + ":" + sel); - } - } - return rc; - } - - public static void interpret_eret(final int ci) { - // fudge, because PSX BIOS seems to do - // - // jr new_pc - // eret - // - // which is invalid according to r3000 docs; still we can check - // for a JR. - // - // this is a bit of a hack, it doesn't take care of branching directly - // to the ERET, however this would only be bad if the ERET was - // in a delay slot and that was branched to, which seems unlikely - all - // in all I'm very unhappy about this; perhaps revisit when we - // support BD correctly! - - // make sure the regs are written back in case we came from the compiler - r3000.restoreInterpreterState(); - int prevci = addressSpace.internalRead32(r3000.getPC() - 4); - if ((prevci & 0xfc1fffff) == 8) { - EPC = interpreterRegs[R3000.Util.bits_rs(prevci)]; - } else { - throw new IllegalStateException("Expected ERET preceeded by JR"); - } - returnFromException(); - } - - public void init() { - super.init(); - status = 0; - cause = 0; - CoreComponentConnections.SCP.set(this); - CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); - } - - public void signalResetException() { - status = STATUS_BEV; - r3000.setPC(0xbfc00000); - } - - private static boolean getStatusBEV() { - return 0 != (status & STATUS_BEV); - } - - private static void setCauseCE(int val) { - cause = (cause & ~CAUSE_CE) | ((val << CAUSE_CE_SHIFT) & CAUSE_CE); - } - - private static void setCauseExcCode(int val) { - cause = (cause & ~CAUSE_CODE) | ((val << CAUSE_CODE_SHIFT) & CAUSE_CODE); - } - - private static int getCauseExcCode() { - return (cause & CAUSE_CODE) >> CAUSE_CODE_SHIFT; - } - - // todo fix these - private static int getCauseIPS() { - return 0; - } - - private static int getStatusIMS() { - return 0; - } - - public void signalIntegerOverflowException() { - throw new IllegalStateException("INT OVERFLOW"); - } - - public void signalBreakException() { - throw new IllegalStateException("BREAK"); - } - - public void signalReservedInstructionException() { - _signalReservedInstructionException(); - } - - public static void _signalReservedInstructionException() { - throw new IllegalStateException("RESERVED INSTRUCTION"); - } - - public void signalSyscallException() { - if (debugSCP) { - r3000.restoreInterpreterState(); - log.debug("SYSCALL " + interpreterRegs[4]); - } - signalExceptionHelper(EXCEPT_SYSCALL, 0, true); - } - - public boolean shouldInterrupt() { - return _shouldInterrupt(); - } - - private static boolean _shouldInterrupt() { - return (0 != (cause & status & 0xff00)) && (0 != (status & STATUS_IEC)); - } - - public void signalInterruptException() { - if (debugSCP) log.debug("interrupt!"); - if (false) { - if (0 != (1 & irqController.getIRQRequest() & irqController.getIRQMask())) { - vsyncsTaken++; - } - long time = quartz.nanoTime(); - if (time > debugNextSecond) { - log.info("VSYNC/SEC " + vsyncsTaken); - debugNextSecond = time + Quartz.SEC; - vsyncsTaken = 0; - } - } - signalExceptionHelper(EXCEPT_INTERRUPT, 0, false); - } - - - public void setInterruptLine(int line, boolean raised) { - // todo assert range - if (raised) { - cause |= 1 << (line + 8); - } else { - cause &= ~(1 << (line + 8)); - } - checkBreakout(); - // wake up the cpu thread if it is blocked - scheduler.cpuThreadNotify(); - } - - protected static void checkBreakout() { - if (_shouldInterrupt()) { - // need to cause an interrupt - r3000.requestBreakout(); - } - } - - private static void signalExceptionHelper(int type, int faultingCoprocessor, boolean expectSkip) { - // we expect PC to be correct already - r3000.restoreInterpreterState(); - if (debugSCP) log.debug("Exception " + type); - int vectorOffset = 0; - // todo, currently recoverable exceptions aren't - // currently unsupported in the delay slot - if (false/* && r3000.executingDelaySlot()*/) { - cause |= CAUSE_BD; - EPC = r3000.getPC() - 4; - } else { - cause &= ~CAUSE_BD; - EPC = r3000.getPC(); - } -// if (type==EXCEPT_TLB_REFILL_L || type==EXCEPT_TLB_REFILL_S) -// vectorOffset = 0; -// else if (type==EXCEPT_INTERRUPT && getCauseIV()) -// vectorOffset = 0x200; -// else -// vectorOffset = 0x180; - vectorOffset = 0x80; - setCauseCE(faultingCoprocessor); - setCauseExcCode(type); - - status = (status & 0xffffffc0) | ((status << 2) & 0x3c); - - int pc; - if (getStatusBEV()) { - // not sure about this - pc = 0xbfc00200 + vectorOffset; - } else { - pc = 0x80000080; - } - - //System.out.println("about to take exception vector at "+MiscUtil.toHex(pc,8)+" pc was "+MiscUtil.toHex(m_EPC,8)); - executeException(pc, expectSkip); - } - - public int currentExceptionType() { - if (0 != (status & 3)) { - return -1; - } - return getCauseExcCode(); - } - - public static void executeException(int pc, boolean expectSkip) { - int exppc = r3000.getPC(); - int expsp = interpreterRegs[R3000.R_SP]; - - if (debugSCP) { - log.debug("take exception r_pc " + MiscUtil.toHex(r3000.getPC(), 8) + " sp " + MiscUtil.toHex(interpreterRegs[R3000.R_SP], 8) + " go to " + MiscUtil.toHex(pc, 8)); - } - - // quick hack for now - if (expectSkip) exppc += 4; - - r3000.setPC(pc); - r3000.executeFromPC(); - - //System.out.println("return from exception r_pc "+MiscUtil.toHex( r3000.getPC(), 8)+" sp "+MiscUtil.toHex( interpreterRegs[R3000.R_SP], 8)); - // todo check what happened if we were in delay slot - if (r3000.getPC() != exppc || interpreterRegs[R3000.R_SP] != expsp) { - log.debug("unexpected execution flow: pc " + MiscUtil.toHex(r3000.getPC(), 8) + "," + MiscUtil.toHex(exppc, 8) + " sp " + MiscUtil.toHex(interpreterRegs[R3000.R_SP], 8) + "," + MiscUtil.toHex(expsp, 8)); - throw ContinueExecutionException.DONT_SKIP_CURRENT; - } else { - // todo if expect skip, then we can also just return, because the next instruction will be invoked - // we want to reset m_currentPCDelta to 0, and m_delayedPCDelta to 4 - // so that we continue there. - //if (expectSkip) r3000.tempHackForException(); - if (expectSkip) { - r3000.setPC(r3000.getPC() - 4); - } - } - } - - public static void returnFromException() { - status = (status & 0xffffffc0) | ((status >> 2) & 0xf); - //System.out.println("return from execption to pc "+MiscUtil.toHex( pc, 8)); - // todo cope with delay slot! - checkBreakout(); - r3000.setPC(EPC); - throw ReturnFromExceptionException.INSTANCE; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java deleted file mode 100644 index ea83f53..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.apache.bcel.classfile.JavaClass; -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.ContinueExecutionException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -import java.lang.ref.SoftReference; - -// todo check threading -/** - * The CodeUnit class represents all that is known about - * a particular piece sequence R3000 code. - *

- * It embodies the various states that a piece - * of code can be in (flow analyzed, stage 1 compiled, etc.) - */ -public class CodeUnit { - Logger log = Logger.getLogger("CodeUnit"); - /** - * Used by the compiled code to determine - * which version of the code to use - *

- * Note this is also used as a guard to ensure visibility between threads - */ - public volatile boolean useStage2; - /** - * Used by the compiled code, to determine - * when to move through the state machine... - * when this counts down to zero, countComplete() is called. - *

- * This is not volatile, since it is repeatedly updated by the processor thread, and only - * rarely modified by another thread. it is however guaranteed to be visible, since the processor - * thread reads useStage2 before reading this, and non processor threads write useStage2 afterwards - */ - public int count = MultiStageCompiler.Settings.stage2Threshold; - - private Class stage2Class; - private int state; - - // base address of code unit - protected final int base; // todo accessor - private int end; - private final boolean rom; - - private Executable executable; - protected boolean linksFollowed; // todo accessor - private volatile boolean stage1Ready; - //private boolean stage2Ready; - - // todo accessor - protected int stage2Version; - - private int preBreakpointState; - private boolean preBreakpointUseStage2; - private int breakpointCount; - - private static final int STATE_STAGE1 = 0; - private static final int STATE_WAITING_FOR_STAGE2 = 1; - private static final int STATE_STAGE2 = 2; - private static final int STATE_BREAKPOINT = 3; - - // todo it is not clear this is safe to share in the presence of code modification - private SoftReference flowInfoRef = new SoftReference(null); - private SoftReference stage1JavaClassRef = new SoftReference(null); - - public CodeUnit(int base) { - this.base = base; - rom = AddressSpace.Util.isBIOS(base); - } - - public final int getBase() { - return base; - } - - public final boolean isROM() { - return rom; - } - - public Executable getExecutable() { - return executable; - } - - public void setExecutable(Executable executable) { - this.executable = executable; - } - - /** - * unsynchronzied, since different threads should - * use different flow analyzers. - * - * may return null for a garbage method if not called on the execution thread - */ - public FlowAnalyzer.FlowInfo getFlowInfo(FlowAnalyzer flowAnalyzer, boolean executionThread) { - FlowAnalyzer.FlowInfo rc = (FlowAnalyzer.FlowInfo) flowInfoRef.get(); - if (rc == null) { - rc = flowAnalyzer.buildFlowGraph(base, executionThread); - if (rc != null) { - end = rc.end; - flowInfoRef = new SoftReference(rc); - } - } - return rc; - } - - /** - * Get the JavaClass representation of this unit. - *

- * This method may be called from the execution or background - * compilation thread; in either case it is not synchronized, - * since we don't want the execution thread to wait on the - * background thread if they end up compiling the same class. - * - * this may return null if not on the execution thread for garbage code - */ - public JavaClass getStage1JavaClass(Stage1Generator generator, boolean executionThread) { - // note while not synchronized, once stage1Ready is set - // we know for sure that we don't want to do any - // background compilation - if (!executionThread && stage1Ready) - return null; - - JavaClass rc = (JavaClass) stage1JavaClassRef.get(); - if (rc == null) { - rc = generator.createJavaClass(this, executionThread); - if (!executionThread) { - stage1JavaClassRef = new SoftReference(rc); - } else { - //System.out.println("*** COMPILE IN EXEC THREAD "+MiscUtil.toHex( base, 8)); - } - } - return rc; - } - - public void stage1ClassReady() { - stage1Ready = true; - // note we may miss clearing the soft reference, but oh well! - stage1JavaClassRef.clear(); - // make sure we know about any breakpoints - MultiStageCompiler.enumerateBreakpoints(this); - } - - // This can return null on non java thread for garbage code - public JavaClass getStage2JavaClass(Stage2Generator generator, boolean executionThread) { - return generator.createJavaClass(this, executionThread); - } - - public void stage2ClassReady(Class stage2Class) { - //stage2Ready = true; - this.stage2Class = stage2Class; - count = Integer.MAX_VALUE; - state = STATE_STAGE2; - stage2Version++; - useStage2 = true; - } - - public void stage2ClassBroken() { - // shouldn't be able to happen when we have a breakpoint in the function - assert state != STATE_BREAKPOINT; - // todo setting for this - if (stage2Version < 5) { - try { - stage2Class.getField("replaced").setBoolean(null, true); - } catch (Throwable ignore) { - assert false; - } - if (log.isDebugEnabled()) { - log.debug("Re-write " + MiscUtil.toHex(base, 8) + " version " + (stage2Version + 1)); - } - count = MultiStageCompiler.Settings.stage2Threshold; - state = STATE_STAGE1; - } else { - // just give up - if (log.isDebugEnabled()) { - log.debug("Too many rewrites for " + MiscUtil.toHex(base, 8)); - } - state = STATE_WAITING_FOR_STAGE2; - } - useStage2 = false; - } - - public void breakpointAdded(int address) { - if (stage1Ready) { - assert end != 0; - if (address >= base && address < end) { - breakpointCount++; - if (breakpointCount == 1) { - log.info("HAVE BREAKPOINT IN " + MiscUtil.toHex(base, 8)); - preBreakpointState = state; - preBreakpointUseStage2 = useStage2; - state = STATE_BREAKPOINT; - count = 0; - useStage2 = false; - } - } - } - } - - public void breakpointRemoved(int address) { - if (stage1Ready) { - assert end != 0; - if (address >= base && address < end) { - breakpointCount--; - if (breakpointCount == 0) { - count = MultiStageCompiler.Settings.stage2Threshold; - state = preBreakpointState; - useStage2 = preBreakpointUseStage2; - } - } - } - } - - public void countComplete() { - switch (state) { - case STATE_STAGE1: - state = STATE_WAITING_FOR_STAGE2; - count = Integer.MAX_VALUE; - if (MultiStageCompiler.Settings.enableSecondStage) { - MultiStageCompiler.registerForStage2(this); - } - break; - case STATE_BREAKPOINT: - // break out into the interpreter - CoreComponentConnections.R3000.resolve().setPC(base); - count = 0; - //System.out.println( "entered compiled function that has a breakpoint!" ); - throw ContinueExecutionException.DONT_SKIP_CURRENT; - default: - count = Integer.MAX_VALUE; - break; - } - } - - public boolean stage1Ready() - { - return stage1Ready; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java deleted file mode 100644 index f805e96..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.apache.log4j.Logger; - -// TODO allow for complete generator - -public class CompilerClassLoader extends ClassLoader { - private static final Logger logger = Logger.getLogger(MultiStageCompiler.CATEGORY); - private final String description; - - public CompilerClassLoader(String description, ClassLoader parent) { - super(parent); - this.description = description; - } - - public Class findClass(final String name) throws ClassNotFoundException { - // make sure we haven't defined it already - Class c = findLoadedClass(name); - if (c == null) { - if (logger.isDebugEnabled()) { - logger.debug(description + ": findClass " + name); - } - // Note it is a bit confusing, that because of the delegation model, it is generally - // the rom loader that gets to generate the class here; however this call actually - // generates the class using the rom or current ram loader as appropriate - c = MultiStageCompiler.generateClass(name); - } - return c; - } - - public Class createClass(final String name, byte[] classData) { - if (logger.isDebugEnabled()) { - logger.debug(description + ": defineClass " + name); - } - return defineClass(name, classData, 0, classData.length, null); - } - - public String toString() { - return description; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Executable.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Executable.java deleted file mode 100644 index ca490ae..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Executable.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -public interface Executable { - public int e(int returnAddress, boolean jump); -} diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java deleted file mode 100644 index d40f353..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -import java.util.Stack; - -// todo cope with method > MAX_R3000_METHOD_INSTRUCTIONS -// todo remove maxBlockSize stuff - -public class FlowAnalyzer { - private static final boolean debugFlow = false; - /** - * contains a block value if the corresponding timestamp is correct, - * however, only guaranteed to be the correct BasicBlock if the - * offset is a branch target. Note, we can have - * dangling references to BasicBlocks here, however the number - * is limited, so we don't care. - */ - private final BasicBlock[] blocks = new BasicBlock[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - private final BasicBlock[] branchTargets = new BasicBlock[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - - // if timeStamps correct, then block/flags are valid - private final int[] timeStamps = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - private final byte[] flags = new byte[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - - private static final byte VISITED = 1; - private static final byte BLOCK_START = 2; - private static final byte DELAY_SLOT = 4; - private static final byte CONDITIONAL_BRANCH = 8; - private static final byte UNCONDITIONAL_BRANCH = 16; - - private int currentTimeStamp; - - private int currentBase; - private int blockCount; - private Stack pendingPaths = new Stack(); - private static final Integer i0 = 0; - - private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); - - // note high offset so it isn't seen as a back branch - public final BasicBlock UNKNOWN_BRANCH_TARGET = new BasicBlock(0, 0x40000000, BasicBlock.UNKNOWN_TARGET); - - /** - * Traces execution flow from an entry point. - *

- * BasicBlocks are constructed for all reachable code paths - * starting at the base address, subject to the limit - * {@link MultiStageCompiler.Settings#maxR3000InstructionsPerUnit}.
- *

- * In the case that this limit is exceeded, - * special blocks will be emitted to handle branching - * out of the block.
- *

- * As a side of this function, the following - * array members are populated for use by the caller - * - * @param base the entry point - * @return the entry-point {@link BasicBlock} or null if the method appears to be garbage (only for intendedForExecutionThread flow analyzers) - */ - public FlowInfo buildFlowGraph(int base, boolean executionThread) { - return buildFlowGraph(base, 800, executionThread); - } - - public FlowInfo buildFlowGraph(int base, int maxBlockSize, boolean executionThread) { - int instructionCount = 0; - - currentBase = base; - if (debugFlow) System.out.println("buildFlowGraph " + MiscUtil.toHex(base, 8)); - assert 0 == (base & 3); - - currentTimeStamp++; - blockCount = 0; - - BasicBlock firstExtraBlock = null; - BasicBlock lastExtraBlock = null; - - pendingPaths.push(i0); - - - // We might be speculatively analyzing empty memory, so we OR all the instructions together - int ciOR = 0; - - int max = 0; - while (!pendingPaths.isEmpty()) { - int offset = pendingPaths.pop(); - - if (timeStamps[offset] == currentTimeStamp && 0 != (flags[offset] & VISITED)) { - if (0 != (flags[offset] & DELAY_SLOT)) { - // todo graham 12/23/14 - this doesn't make much sense... - // todo it seems like we should be caring if it was already a BLOCK_START - - // nasty case of branching to delay slot which has already been - // visited; however the flow might previously have stopped exactly - // at the delay slot. since the delay slot may not be a branch instruction - // (or if it was would still have another delay slot following), - // we try the next instruction also in case it has never been visited - if (debugFlow) { - System.out.println("RARE: Checking code beyond branched-to delay-slot at " + MiscUtil.toHex(base + offset * 4, 8)); - } - // note this has the side effect of always making the delay slot a single instruction block; - offset++; - } else { - // starting a block which has already been visited, so nothing to do - continue; - } - } - - // side effect is to create block if necessary - getBlock(offset); - - boolean flowOut = false; - - // todo we don't actually handle the case where the method is bigger than this - int end = MultiStageCompiler.Settings.maxR3000InstructionsPerUnit - 1; // -1 in case we need delay slot - int blockLimit = offset + maxBlockSize; - byte nextFlags = 0; - - for (; offset < end; offset++) { - if (offset >= blockLimit && 0 == nextFlags) { - // not delay slot or anything else of interest... - // end our block, but continue where we left off. - pendingPaths.push(offset); - break; - } - if (timeStamps[offset] == currentTimeStamp) { - // run into something we've seen before, so just update the flags - flags[offset] |= nextFlags; - // if we've already actually been here, then quit; - // otherwise we're flowing into a branch target - // we haven't yet visited - if (0 != (flags[offset] & VISITED)) { - break; - } - flags[offset] |= VISITED; - } else { - timeStamps[offset] = currentTimeStamp; - flags[offset] = (byte) (nextFlags | VISITED); - } - nextFlags = 0; - int address = base + (offset << 2); - int ci = addressSpace.internalRead32(address); - ciOR |= ci; - CPUInstruction inst = r3000.decodeInstruction(ci); - - int iFlags = inst.getFlags(); - - if (!executionThread && 0 != (iFlags & CPUInstruction.FLAG_INVALID)) { - // don't like invalid instructions when working in a background thread - // because we might be analyzing garbage. - if (debugFlow) { - System.out.println("Probable garbage at " + MiscUtil.toHex(base, 8) + " because of invalid instruction"); - } - return null; - } - if (0 != (iFlags & CPUInstruction.FLAG_BRANCH)) { - int branchType = inst.getBranchType(ci); - if (0 == (iFlags & CPUInstruction.FLAG_LINK)) { - // note we are a non-linking instruction, so there - // we cannot have both conditional branch and - // register target... which would be bad. - if (0 != (iFlags & (CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_IMM_FAR_TARGET))) { - int target; - if (0 != (iFlags & CPUInstruction.FLAG_IMM_NEAR_TARGET)) { - target = address + 4 + R3000.Util.signed_branch_delta(ci); - } else { - // todo assert Far target - target = ((address + 4) & 0xf0000000) | ((ci & 0x3fffff) << 2); - } - int targetOffset = (target - base) >> 2; - if (targetOffset < 0 || targetOffset >= MultiStageCompiler.Settings.maxR3000InstructionsPerUnit) { - branchTargets[offset] = new BasicBlock(currentBase, targetOffset, BasicBlock.JUMP_WRAPPER); - if (firstExtraBlock == null) { - firstExtraBlock = lastExtraBlock = branchTargets[offset]; - } else { - lastExtraBlock.next = branchTargets[offset]; - lastExtraBlock = branchTargets[offset]; - } - blockCount++; - } else { - branchTargets[offset] = getBlock(targetOffset); - //flags[targetOffset] |= BLOCK_START; - pendingPaths.push(targetOffset); - } - } else { - branchTargets[offset] = UNKNOWN_BRANCH_TARGET; - } - - if (branchType == CPUInstruction.BRANCH_ALWAYS) { - flags[offset] |= UNCONDITIONAL_BRANCH; - } else { - flags[offset] |= CONDITIONAL_BRANCH; - flowOut = true; - } - - // done after the next instruction (delay slot) - end = offset + 2; - nextFlags = DELAY_SLOT; - } - } - } - if (offset > max) { - max = offset; - } - if (flowOut) { - // want to move straight on to next block - pendingPaths.push(offset); - } - } - if (!executionThread && ciOR == 0) { - // all NOPs and then we fell off the end - if (debugFlow) { - System.out.println("Garbage empty-ness at " + MiscUtil.toHex(base, 8)); - } - return null; - } - - BasicBlock block = null; - BasicBlock flowingInBlock = null; - - for (int offset = 0; offset < max; offset++) { - if (timeStamps[offset] == currentTimeStamp) { - assert (0 != (flags[offset] & VISITED)); - - if (0 != (flags[offset] & BLOCK_START)) { - if (block != null) { - block.next = blocks[offset]; - } - block = blocks[offset]; - if (flowingInBlock != null) { - flowingInBlock.flowOut = block; - } - flowingInBlock = block; - } - if (0 != (flags[offset] & DELAY_SLOT)) { - block.includesDelaySlot = true; - } - block.size++; - instructionCount++; - if (0 != (flags[offset] & (CONDITIONAL_BRANCH | UNCONDITIONAL_BRANCH))) { - block.branchOffset = offset; - block.branchOut = branchTargets[offset]; - if (0 != (flags[offset] & UNCONDITIONAL_BRANCH)) { - flowingInBlock = null; - } - } - } - } - - if (debugFlow) { - for (int offset = 0; offset < max; offset++) { - if (timeStamps[offset] == currentTimeStamp) { - int address = base + (offset << 2); - String debug = MiscUtil.toHex(address, 8) + " "; - if (0 != (flags[offset] & BLOCK_START)) { - System.out.println("--- " + blocks[offset]); - debug += "*"; - } else { - debug += " "; - } - if (0 != (flags[offset] & UNCONDITIONAL_BRANCH)) { - if (branchTargets[offset] == null) { - debug += "UBR"; - } else { - debug += "UB" + branchTargets[offset].type; - } - } else if (0 != (flags[offset] & CONDITIONAL_BRANCH)) { - debug += "CB" + branchTargets[offset].type; - } else { - debug += " "; - } - if (0 != (flags[offset] & DELAY_SLOT)) { - debug += "D"; - } else { - debug += " "; - } - - int ci = addressSpace.internalRead32(address); - debug += " " + r3000.disassemble(address, ci); - System.out.println(debug); - } - } - } - assert (block.next == null); - block.next = firstExtraBlock; - - FlowInfo rc = new FlowInfo(); - rc.root = blocks[0]; - rc.instructionCount = instructionCount; - rc.blockCount = blockCount; - rc.base = base; - rc.end = base + max * 4; - return rc; - } - - protected BasicBlock getBlock(int offset) { - if (timeStamps[offset] != currentTimeStamp) { - timeStamps[offset] = currentTimeStamp; - flags[offset] = 0; - } - if (0 == (flags[offset] & BLOCK_START)) { - flags[offset] |= BLOCK_START; - blocks[offset] = new BasicBlock(currentBase, offset); - blockCount++; - } - return blocks[offset]; - } - - // note this class should be immutable with accessors... it may be - // shared by more than one thread - public static class BasicBlock { - /** - * block this flows into, or null if it always branches (e.g. ends with jr) - *

- * Note that more than one block may flow into another block - * because we need to create a dummy block when someone - * branches to a delay slot - */ - public BasicBlock flowOut; - /** - * block this branches to, or null if it doesn't end with a branch - */ - public BasicBlock branchOut; - - /** - * linked list of blocks in ascending offset order - */ - public BasicBlock next; - - /** - * configure instruction offset within enclsoing method - */ - public int offset; - - /** - * offset of branch instruction - */ - public int branchOffset; - - public int base; - /** - * number of instructions in the method - */ - public int size; - - public boolean includesDelaySlot; - - public int type; - - public static final int NORMAL = 0; - public static final int JUMP_WRAPPER = 1; - public static final int UNKNOWN_TARGET = 2; - - public BasicBlock(int base, int offset) { - this.base = base; - this.offset = offset; - } - - public BasicBlock(int base, int offset, int type) { - this.base = base; - this.offset = offset; - this.type = type; - } - - public String toString() { - String rc; - if (size == 0) { - rc = "unvisited block " + MiscUtil.toHex(base + offset * 4, 8); - } else { - rc = "block " + MiscUtil.toHex(base + offset * 4, 8) + "->" + MiscUtil.toHex(base + offset * 4 + size * 4, 8); - if (flowOut != null) { - rc += " flow " + MiscUtil.toHex(base + flowOut.offset * 4, 8); - } - if (branchOut != null) { - rc += " branch " + MiscUtil.toHex(base + branchOut.offset * 4, 8); - if (!includesDelaySlot) { - rc += " missing-delay-slot"; - } - } - } - return rc; - } - } - - public static class FlowInfo { - public BasicBlock root; - public int instructionCount; - public int base; - public int end; - public int blockCount; - - public String toString() { - return "FlowInfo@" + Integer.toHexString(hashCode()) + " ic=" + instructionCount + " base=" + MiscUtil.toHex( base, 8 ) + " bc=" + blockCount; - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java deleted file mode 100644 index 0d3400a..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.apache.bcel.classfile.JavaClass; -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.ContinueExecutionException; -import org.jpsx.api.components.core.ImmediateBreakoutException; -import org.jpsx.api.components.core.ReturnFromExceptionException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.NativeCompiler; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.*; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -import java.lang.reflect.Field; -import java.util.LinkedList; -import java.util.Map; - -// todo, compilation shouldn't fail it should just make a class which throws ContinueExecutionException - -// todo set addressSpace.tagAddressAccess based on whether we're doing 2 stage compile - -// todo, cope with compilation errors caused by data being overwritten in another thread - -// todo consider caching byte code for instruction cache flush - -// todo look for and follow "switch tables" - -// todo handle usuallyRAMRegs better - we could detect methods which obviously set SP to weird values for example - -public class MultiStageCompiler extends SingletonJPSXComponent implements NativeCompiler { - public static final String CATEGORY = "Compiler"; - private static final Logger log = Logger.getLogger(CATEGORY); - - public static final byte TAG_UNWRITTEN_REGS = AddressSpace.TAG_RESERVED_FOR_COMPILER; - public static final byte TAG_DELAY_SLOT = AddressSpace.TAG_RESERVED_FOR_COMPILER_2; - - - protected static Stage1Generator immediateGenerator; - // for use if we need to figure out what the real stage2 generator - // would have done (to fixup unwritten regs when we mispredict memory access - // and have to return to the interpreter); - // note we can't use the real one since it is not thread safe - private static Stage2Generator fixupStage2Generator; - - protected static CompilerClassLoader ramLoader; - protected static CompilerClassLoader romLoader; - protected static int ramLoaderCount = 0; - - protected static final Map romUnits = CollectionsFactory.newHashMap(); - protected static final Map ramUnits = CollectionsFactory.newHashMap(); - - protected static CompilationBroker broker; - - private static final int MAX_BREAKPOINTS = 64; - - private static final int[] breakpoints = new int[MAX_BREAKPOINTS]; - private static int breakpointLimit; - - private static class Refs extends FinalResolvedConnectionCache { - public static final int[] interpreterRegs = CoreComponentConnections.R3000.resolve().getInterpreterRegs(); - } - - private static R3000 r3000; - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - r3000 = CoreComponentConnections.R3000.resolve(); - } - - protected static class ExecutionContext { - public int nativeDepth; - public boolean cacheStale; - } - - protected static int contextDepth = 0; - protected static ExecutionContext context; - protected static final int MAX_CONTEXT_DEPTH = 4; - protected static final ExecutionContext[] contexts; - - protected static boolean ownRegs; - private static AddressSpace addressSpace; - - public MultiStageCompiler() { - super("JPSX Multi-Stage Compiler"); - } - - /** - * Number of jr/jalr calls within native code... we - * limit these if they get to big, in case we're - * not running functions as we suspect... e.g. - * Final Fantasy has a state machine with jal which recurses - * consuming no stack rather than returning! - */ - - static { - contexts = new ExecutionContext[MAX_CONTEXT_DEPTH]; - for (int i = 0; i < MAX_CONTEXT_DEPTH; i++) { - contexts[i] = new ExecutionContext(); - } - context = contexts[0]; - } - - protected static class Settings extends FinalComponentSettings { - // todo, assert this happens late enough - public static final boolean enableSpeculativeCompilation = getComponent().getBooleanProperty("speculativeCompilation", true); - public static final boolean enableSecondStage = getComponent().getBooleanProperty("stage2", true); - public static final boolean secondStageInBackground = true; - public static final int minSizeForSpeculativeCompile = 50; - public static final int maxNativeDepth = 100; - public static final int stage2Threshold = 30; - public static final int maxR3000InstructionsPerUnit = 8000; -// 1 at Assembler temporary. -// 2- 3 v0-v1 Subroutine return values -// 4- 7 a0-a3 Subroutine arguments -// 8-15 t0-t7 Temporaries, may be changed by subroutines -//16-23 s0-s7 Register variables, must be saved by subs. -//24-25 t8-t9 Temporaries, may be changed by subroutines -//26-27 k0-k1 Reserved for the kernel -//28 gp Global pointer -//29 sp Stack pointer -//30 fp(s8) 9th register variable, subs can use this as a frame - // pointer - //31 ra Return address - public static final int savedOnCallRegs = 0x30ff0001; - // We assume these are RAM at first (in this case just SP) - public static final int usuallyRAMRegs = 0x20000000; - public static final boolean saveClasses = getComponent().getBooleanProperty("saveClasses", false); - public static final boolean biosInterruptWorkaround = true; - public static final boolean printCode = getComponent().getBooleanProperty("printCode", false); - protected static final boolean addLineNumbers = true; - protected static final boolean debugPC = false; - protected static final boolean profiling = false; - protected static final boolean megaTrace = false; - protected static final boolean printRare = getComponent().getBooleanProperty("printRare", false); - protected static final boolean statistics = getComponent().getBooleanProperty("statistics", false); - protected static final boolean dumpMemoryMisPredictions = false; - // todo printCode here just because the print code stuff doesn't work properly with basic blocks that have been split into separate methods - // todo the larger number can cause some branches to become too large - protected static final int maxMethodInstructionCount = printCode?8000:800; // todo justify this choice of number - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.NATIVE_COMPILER.set(this); - JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); - machine.addInitializer(JPSXMachine.PRIORITY_FREEZE_SETTINGS, new Runnable() { - @Override - public void run() { - Settings.setComponent(MultiStageCompiler.this); - log.info("printCode " + Settings.printCode); - log.info("Speculative compilation enabled = " + Settings.enableSpeculativeCompilation); - log.info("Second stage enabled = " + Settings.enableSecondStage); - } - }); - } - - public void begin() { - immediateGenerator = new Stage1Generator("c1gen.out", true); - romLoader = new CompilerClassLoader("ROM classloader", MultiStageCompiler.class.getClassLoader()); - broker = new CompilationBroker(); - broker.begin(); - clearCache(); - } - - public boolean jumpAndLink(int address, int returnAddress) { - int oldNativeDepth = contexts[contextDepth].nativeDepth; - - context = contexts[++contextDepth]; - assert !context.cacheStale; - - CodeUnit unit = getCodeUnit(address); - - Executable exec = unit.getExecutable(); - if (exec == null) { - exec = makeExecutable(unit); - if (exec == null) { - return false; - } - } - - context.nativeDepth = oldNativeDepth; - if (!ownRegs) { - interpreterToCompiler(); - } - int retaddr = exec.e(returnAddress, false); - compilerToInterpreter(); - assert retaddr == returnAddress; - assert oldNativeDepth == context.nativeDepth : "nativeDepth mismatch for " + MiscUtil.toHex(address, 8) + " " + oldNativeDepth + "!=" + context.nativeDepth; - contextDepth--; - assert contextDepth >= 0; - r3000.setPC(retaddr); - return true; - } - - /** - * Note this method is always called in the execution thread - * either from the classloader, or from jumpAndLink - */ - protected static Executable makeExecutable(CodeUnit unit) { - assert r3000.isExecutionThread(); - JavaClass jclass = unit.getStage1JavaClass(immediateGenerator, true); - Class clazz = createClass(unit, jclass); - unit.stage1ClassReady(); - try { - Executable executable = (Executable) clazz.newInstance(); - Field field = clazz.getField("unit"); - field.set(executable, unit); - broker.registerLinkedFunctions(unit, true); - unit.setExecutable(executable); - return executable; - } catch (Throwable t) { - t.printStackTrace(); - throw new IllegalStateException("could not create/cast to CodeUnit " + clazz.getName()); - } - } - - public void clearCache() { - log.debug("clearCache"); - synchronized (MultiStageCompiler.class) { - broker.reset(); - ramLoaderCount++; - // we delegate to the rom loader for bios functions - ramLoader = new CompilerClassLoader("RAM classloader " + ramLoaderCount, romLoader); - synchronized (ramUnits) { - ramUnits.clear(); - } - // make sure we know that we cannot continue executing code - // in any higher nested execution levels - // todo this should be 0...? - for (int i = 1; i < contextDepth; i++) { - contexts[i].cacheStale = true; - } - } - } - - public boolean exceptionInCompiler(Throwable t) { -// System.out.println("Exception in compiler depth="+contextDepth+" "+t.getClass().getName()); - assert contextDepth >= 1; - context = contexts[--contextDepth]; - compilerToInterpreter(); - if (t instanceof ReturnFromExceptionException || t instanceof ContinueExecutionException) { - // don't need to update PC - return true; - } - - StackTraceElement trace[] = t.getStackTrace(); - int exceptionPC = -1; - int base = 0; - String className = null; - for (int i = 0; i < trace.length; i++) { - className = trace[i].getClassName(); - if (className.length() == 10 && className.startsWith("_")) { - String methodName = trace[i].getMethodName(); - if (methodName.equals(Stage1Generator.STATIC_METHOD) || methodName.startsWith(Stage1Generator.UNINLINED_METHOD_PREFIX)) { - exceptionPC = base = MiscUtil.parseHex(className.substring(2)); - int ln = trace[i].getLineNumber(); - if (ln >= 0) { - exceptionPC += ln * 4; - } - break; - // todo constant - } else if (methodName.equals(Stage1Generator.NORMAL_METHOD)) { - System.out.println("Can't get PC!"); - break; - } - } - } - if (exceptionPC != -1) { - int restartPC; - if (0 != (addressSpace.getTag(exceptionPC) & TAG_DELAY_SLOT)) { - // todo we don't currently cope with a mis-prediction in a direct jump to a delay slot instruction - // todo we need the compiler to make separate code for both cases; hopefully this is a pathological case anyway - restartPC = exceptionPC - 4; - if (log.isDebugEnabled()) { - int ci = addressSpace.internalRead32(restartPC); - log.debug("Java exception was in delay slot at " + MiscUtil.toHex(exceptionPC, 8) + - " rewinding to branch instruction " + MiscUtil.toHex(restartPC, 8) + ": " + r3000.disassemble(restartPC, ci)); - } - } else { - restartPC = exceptionPC; - } - r3000.setPC(restartPC); - if (!className.startsWith(Stage1Generator.CLASS_NAME_PREFIX)) { - // Note using exceptionPC seems to make sense, since the code for that instruction actually happens - // before the preceding branch (which itself can't have changed any constant registers anyway) - if (0 != (addressSpace.getTag(exceptionPC) & TAG_UNWRITTEN_REGS)) { - // if we get here it is because we have had a memory mis-predict, but we cannot safely - // restart, because we omitted code to update actual register values during this basic block. - // what we need to do here, is to re-examine the code unit, and figure out what the register values must have been (i.e. - // for any CR at this location, and update those). - if (log.isDebugEnabled()) { - log.debug("NEED REG WRITEBACK AT " + MiscUtil.toHex(exceptionPC, 8)); - } - // we gave regs to interpreter above so we must claim them back - interpreterToCompiler(); - fixupUnwrittenCompilerRegs(base, exceptionPC); - compilerToInterpreter(); - } - if (t.getClass() == ArrayIndexOutOfBoundsException.class) { - // could be due to mis-predicted memory access - int ci = addressSpace.internalRead32(exceptionPC); - CPUInstruction inst = r3000.decodeInstruction(ci); - if (0 != (inst.getFlags() & CPUInstruction.FLAG_MEM)) { - if (log.isDebugEnabled()) { - log.debug("***** Mispredicted memory access at " + MiscUtil.toHex(exceptionPC, 8)); - } - if (Settings.dumpMemoryMisPredictions) { - String dis = r3000.disassemble(exceptionPC, ci); - System.out.println("MemoryFail at " + MiscUtil.toHex(exceptionPC, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); - t.printStackTrace(); - System.out.println("r0 " + MiscUtil.toHex(Refs.interpreterRegs[0], 8) + " r1 " + MiscUtil.toHex(Refs.interpreterRegs[1], 8) + " r2 " + MiscUtil.toHex(Refs.interpreterRegs[2], 8) + " r3 " + MiscUtil.toHex(Refs.interpreterRegs[3], 8) + " pc " + MiscUtil.toHex(r3000.getPC(), 8)); - System.out.println("r4 " + MiscUtil.toHex(Refs.interpreterRegs[4], 8) + " r5 " + MiscUtil.toHex(Refs.interpreterRegs[5], 8) + " r6 " + MiscUtil.toHex(Refs.interpreterRegs[6], 8) + " r7 " + MiscUtil.toHex(Refs.interpreterRegs[7], 8) + " lo " + MiscUtil.toHex(r3000.getLO(), 8)); - System.out.println("r8 " + MiscUtil.toHex(Refs.interpreterRegs[8], 8) + " r9 " + MiscUtil.toHex(Refs.interpreterRegs[9], 8) + " r10 " + MiscUtil.toHex(Refs.interpreterRegs[10], 8) + " r11 " + MiscUtil.toHex(Refs.interpreterRegs[11], 8) + " hi " + MiscUtil.toHex(r3000.getHI(), 8)); - System.out.println("r12 " + MiscUtil.toHex(Refs.interpreterRegs[12], 8) + " r13 " + MiscUtil.toHex(Refs.interpreterRegs[13], 8) + " r14 " + MiscUtil.toHex(Refs.interpreterRegs[14], 8) + " r15 " + MiscUtil.toHex(Refs.interpreterRegs[15], 8)); - System.out.println("r16 " + MiscUtil.toHex(Refs.interpreterRegs[16], 8) + " r17 " + MiscUtil.toHex(Refs.interpreterRegs[17], 8) + " r18 " + MiscUtil.toHex(Refs.interpreterRegs[18], 8) + " r19 " + MiscUtil.toHex(Refs.interpreterRegs[19], 8)); - System.out.println("r20 " + MiscUtil.toHex(Refs.interpreterRegs[20], 8) + " r21 " + MiscUtil.toHex(Refs.interpreterRegs[21], 8) + " r22 " + MiscUtil.toHex(Refs.interpreterRegs[22], 8) + " r23 " + MiscUtil.toHex(Refs.interpreterRegs[23], 8)); - System.out.println("r24 " + MiscUtil.toHex(Refs.interpreterRegs[24], 8) + " r25 " + MiscUtil.toHex(Refs.interpreterRegs[25], 8) + " r26 " + MiscUtil.toHex(Refs.interpreterRegs[26], 8) + " r27 " + MiscUtil.toHex(Refs.interpreterRegs[27], 8)); - System.out.println("r28 " + MiscUtil.toHex(Refs.interpreterRegs[28], 8) + " r29 " + MiscUtil.toHex(Refs.interpreterRegs[29], 8) + " r30 " + MiscUtil.toHex(Refs.interpreterRegs[30], 8) + " r31 " + MiscUtil.toHex(Refs.interpreterRegs[31], 8)); - } - - CodeUnit unit = getCodeUnit(base); - assert unit.useStage2; - unit.stage2ClassBroken(); - return true; - } - } - } - // This exception is allowed anywhere - return t instanceof ImmediateBreakoutException; - } else { - log.warn("PC could not be calculated from stack trace, maybe you need -XX:-OmitStackTraceInFastThrow?"); - } - return false; - } - - public void interrupt() { - isInterrupted = true; - } - - public synchronized boolean addBreakpoint(int address) { - boolean ok = false; - for (int i = 0; i < breakpointLimit; i++) { - if (breakpoints[i] == -1) { - breakpoints[i] = address; - ok = true; - break; - } - } - if (!ok) { - if (breakpointLimit == MAX_BREAKPOINTS) { - return false; - } - breakpoints[breakpointLimit++] = address; - } - Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; - synchronized (map) { - for (CodeUnit unit : map.values()) { - unit.breakpointAdded(address); - } - } - // make sure we know that we should not continue executing code - // in any higher nested execution levels - for (int i = 1; i < contextDepth; i++) { - contexts[i].cacheStale = true; - } - return true; - } - - public synchronized void removeBreakpoint(int address) { - for (int i = 0; i < breakpointLimit; i++) { - if (breakpoints[i] == address) { - breakpoints[i] = -1; - if (i == breakpointLimit - 1) { - breakpointLimit--; - } - Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; - synchronized (map) { - for (CodeUnit unit : map.values()) { - unit.breakpointRemoved(address); - } - } - return; - } - } - assert false : "attempt to remove non-existent breakpoint " + MiscUtil.toHex(address, 8); - } - - public static void enumerateBreakpoints(CodeUnit unit) { - for (int i = 0; i < breakpointLimit; i++) { - if (breakpoints[i] != -1) { - unit.breakpointAdded(breakpoints[i]); - } - } - } - - public int getReg(int index) { - assert false; - return 0; - } - - public void setReg(int index, int value) { - assert false; - } - - /** - * called by the class loader when a referenced - * but not yet generated class is executed - */ - public static Class generateClass(String classname) throws ClassNotFoundException { - // Note we only expect C1 classes, as those are the only ones defined on demand - // C2 classes are generated in the background, and other classes should exist - if (classname.startsWith(Stage1Generator.CLASS_NAME_PREFIX)) { - int address = MiscUtil.parseHex(classname.substring(2)); - CodeUnit unit = getCodeUnit(address); - Executable executable = makeExecutable(unit); - // todo; what if this fails? - return executable.getClass(); - } else { - throw new IllegalStateException("findClass not called for C1: " + classname); - } - } - - protected static Class createClass(CodeUnit unit, - JavaClass jclass) { - if (AddressSpace.Util.isBIOS(unit.getBase())) { - return romLoader.createClass(jclass.getClassName(), jclass.getBytes()); - } else { - return ramLoader.createClass(jclass.getClassName(), jclass.getBytes()); - } - } - - protected static void returnToInterpreter(int address) { - compilerToInterpreter(); - r3000.setPC(address); - throw ContinueExecutionException.DONT_SKIP_CURRENT; - } - - public static void registerForStage2(CodeUnit unit) { - broker.registerForStage2(unit); - } - - protected static CodeUnit getCodeUnit(int address) { - Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; - Integer key = address; - synchronized (map) { - CodeUnit rc = map.get(key); - if (rc == null) { - rc = new CodeUnit(address); - map.put(key, rc); - } - return rc; - } - } - - protected static class CompilationBroker implements Runnable { - protected LinkedList unitsToFollow = new LinkedList(); - protected LinkedList unitsForStage1 = new LinkedList(); - protected LinkedList unitsForStage2 = new LinkedList(); - - protected FlowAnalyzer linkFlowAnalyzer = new FlowAnalyzer(); - protected Stage1Generator stage1Generator; - protected Stage2Generator stage2Generator; - protected int resetCount; - - public CompilationBroker() { - if (Settings.enableSpeculativeCompilation) { - stage1Generator = new Stage1Generator("c1specgen.out", false); - } - if (Settings.enableSecondStage) { - stage2Generator = new Stage2Generator("c2gen.out", !Settings.secondStageInBackground); - } - } - - public void begin() { - if (Settings.enableSpeculativeCompilation || - (Settings.enableSecondStage && Settings.secondStageInBackground)) { - log.info("Starting background compilation thread"); - Thread t = new Thread(this, "Background compilation"); - t.setPriority(Thread.NORM_PRIORITY - 2); // low priority - t.start(); - } - } - - public synchronized void registerLinkedFunctions(CodeUnit unit, boolean executionThread) { - if (!Settings.enableSpeculativeCompilation || unit.linksFollowed || unit.isROM()) { - return; - } - if (executionThread) { - // when called from the main compile thread, we - // put the function to the head of the list - unitsToFollow.addFirst(unit); - notify(); - } else { - // ones we follow go at end, i.e. the go behind any functions we - // have actually executed - unitsToFollow.addLast(unit); - } - } - - public synchronized void registerForStage2(CodeUnit unit) { - if (Settings.enableSecondStage) { - if (Settings.secondStageInBackground) { - unitsForStage2.add(unit); - notify(); - } else { - //System.out.println( "foreground stage2 compile " + MiscUtil.toHex( unit.getBase(), 8 ) ); - JavaClass jclass = unit.getStage2JavaClass(stage2Generator, true); - Class clazz = createClass(unit, jclass); - unit.stage2ClassReady(clazz); - } - } - } - - // todo: since we're compiling in the background it is possible we'll compile - // something that it is being overwritten... - public void run() { - try { - while (true) { - CodeUnit linkUnit = null; - CodeUnit c1Unit = null; - CodeUnit c2Unit = null; - int priorResetCount = 0; - synchronized (this) { - priorResetCount = resetCount; - if (unitsToFollow.size() > 0) { - // first priority is to follow any new links - linkUnit = (CodeUnit) unitsToFollow.removeFirst(); - } else if (unitsForStage1.size() > 0) { - // second priority is speculative compile - c1Unit = (CodeUnit) unitsForStage1.removeFirst(); - } else if (unitsForStage2.size() > 0) { - // third priority is stage 2 compile - c2Unit = (CodeUnit) unitsForStage2.removeFirst(); - } else { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - if (linkUnit != null && !linkUnit.linksFollowed) { - //System.out.println("Follow links "+MiscUtil.toHex( linkUnit.getBase(), 8)); - followLinks(linkUnit, false); - } else if (c1Unit != null) { - // simply get the java class - //System.out.println("Spec compile "+MiscUtil.toHex( c1Unit.getBase(), 8)); - // todo graham 12/21/14, I put this synchronized block in before I went on vacation 2 weeks - // todo and can't remember what it is for - seems like it would have like a comment - // todo anyway the only thing that it shares synchronization with is instruction cache clear - // todo so there must have been some issues with compilation during the clearing of other data - // todo structures. anyways, I'm leaving it as is for now since it is not time critical - // todo you'd expect this would affect the stage2 compiler too. - // todo in any case we need better exception handling here anyway, since we may be compiling - // todo R3000 code that is being overwritten prior to an instruction cache clear - synchronized (MultiStageCompiler.class) { - JavaClass jclass = c1Unit.getStage1JavaClass(stage1Generator, false); - } - } else if (c2Unit != null) { - //System.out.println("background stage2 compile "+MiscUtil.toHex( c2Unit.getBase(), 8)); - JavaClass jclass = c2Unit.getStage2JavaClass(stage2Generator, false); - // todo state machine handling here seems flaky - if (jclass != null) { - // todo fix this; - // a) resetCount is not protected; - // b) don't want to delay - // synchronized( this) { - if (resetCount == priorResetCount) { - // only create the class if we haven't been reset - Class clazz = createClass(c2Unit, jclass); - c2Unit.stage2ClassReady(clazz); - } - // } - } - } - } - } catch (Throwable t) { - log.error(this + " exits abnormally:", t); - // todo fix this - RuntimeConnections.MACHINE.resolve().close(); - } - } - - public synchronized void reset() { - unitsToFollow.clear(); - unitsForStage1.clear(); - unitsForStage2.clear(); - resetCount++; - } - - protected void followLinks(CodeUnit unit, boolean executionThread) { - FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(linkFlowAnalyzer, executionThread); - if (flowInfo != null) { - if (!unit.stage1Ready() && flowInfo.instructionCount > Settings.minSizeForSpeculativeCompile) { - //System.out.println(">>>>>>>>>>>> should compile "+MiscUtil.toHex( unit.base, 8)); - unitsForStage1.add(unit); - } - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { - for (int offset = block.offset; offset < block.offset + block.size; offset++) { - int address = flowInfo.base + offset * 4; - int ci = addressSpace.internalRead32(address); - CPUInstruction inst = r3000.decodeInstruction(ci); - int iFlags = inst.getFlags(); - if (0 != (iFlags & CPUInstruction.FLAG_LINK)) { - if (0 != (iFlags & CPUInstruction.FLAG_IMM_FAR_TARGET)) { - int target = ((address + 4) & 0xf0000000) | ((ci & 0x3fffff) << 2); - // System.out.println(MiscUtil.toHex( target, 8)+" called from "+MiscUtil.toHex( address, 8)); - if (!AddressSpace.Util.isBIOS(target)) { - registerLinkedFunctions(getCodeUnit(target), false); - } - } - } - } - } - } - // todo should we set this to true for flowInfo == null ? - unit.linksFollowed = true; - } - } - } - - /** - * for use of compiled code, since we always know what - * register an instruction uses, there's no point - * in taking the hit of an array lookup - */ - public static int reg_1; - public static int reg_2; - public static int reg_3; - public static int reg_4; - public static int reg_5; - public static int reg_6; - public static int reg_7; - public static int reg_8; - public static int reg_9; - public static int reg_10; - public static int reg_11; - public static int reg_12; - public static int reg_13; - public static int reg_14; - public static int reg_15; - public static int reg_16; - public static int reg_17; - public static int reg_18; - public static int reg_19; - public static int reg_20; - public static int reg_21; - public static int reg_22; - public static int reg_23; - public static int reg_24; - public static int reg_25; - public static int reg_26; - public static int reg_27; - public static int reg_28; - public static int reg_29; - public static int reg_30; - public static int reg_31; - public static boolean isInterrupted; - - public static final String INTERPRETER_TO_COMPILER_METHOD = "interpreterToCompiler"; - - public static void interpreterToCompiler() { - assert !ownRegs; - reg_1 = Refs.interpreterRegs[1]; - reg_2 = Refs.interpreterRegs[2]; - reg_3 = Refs.interpreterRegs[3]; - reg_4 = Refs.interpreterRegs[4]; - reg_5 = Refs.interpreterRegs[5]; - reg_6 = Refs.interpreterRegs[6]; - reg_7 = Refs.interpreterRegs[7]; - reg_8 = Refs.interpreterRegs[8]; - reg_9 = Refs.interpreterRegs[9]; - reg_10 = Refs.interpreterRegs[10]; - reg_11 = Refs.interpreterRegs[11]; - reg_12 = Refs.interpreterRegs[12]; - reg_13 = Refs.interpreterRegs[13]; - reg_14 = Refs.interpreterRegs[14]; - reg_15 = Refs.interpreterRegs[15]; - reg_16 = Refs.interpreterRegs[16]; - reg_17 = Refs.interpreterRegs[17]; - reg_18 = Refs.interpreterRegs[18]; - reg_19 = Refs.interpreterRegs[19]; - reg_20 = Refs.interpreterRegs[20]; - reg_21 = Refs.interpreterRegs[21]; - reg_22 = Refs.interpreterRegs[22]; - reg_23 = Refs.interpreterRegs[23]; - reg_24 = Refs.interpreterRegs[24]; - reg_25 = Refs.interpreterRegs[25]; - reg_26 = Refs.interpreterRegs[26]; - reg_27 = Refs.interpreterRegs[27]; - reg_28 = Refs.interpreterRegs[28]; - reg_29 = Refs.interpreterRegs[29]; - reg_30 = Refs.interpreterRegs[30]; - reg_31 = Refs.interpreterRegs[31]; -// System.out.println("i->c"); - ownRegs = true; - } - - public void restoreInterpreterState() { - compilerToInterpreter(); - } - - public static final String COMPILER_TO_INTERPRETER_METHOD = "compilerToInterpreter"; - - public static void compilerToInterpreter() { - if (ownRegs) { -// System.out.println("c->i"); - ownRegs = false; - Refs.interpreterRegs[1] = reg_1; - Refs.interpreterRegs[2] = reg_2; - Refs.interpreterRegs[3] = reg_3; - Refs.interpreterRegs[4] = reg_4; - Refs.interpreterRegs[5] = reg_5; - Refs.interpreterRegs[6] = reg_6; - Refs.interpreterRegs[7] = reg_7; - Refs.interpreterRegs[8] = reg_8; - Refs.interpreterRegs[9] = reg_9; - Refs.interpreterRegs[10] = reg_10; - Refs.interpreterRegs[11] = reg_11; - Refs.interpreterRegs[12] = reg_12; - Refs.interpreterRegs[13] = reg_13; - Refs.interpreterRegs[14] = reg_14; - Refs.interpreterRegs[15] = reg_15; - Refs.interpreterRegs[16] = reg_16; - Refs.interpreterRegs[17] = reg_17; - Refs.interpreterRegs[18] = reg_18; - Refs.interpreterRegs[19] = reg_19; - Refs.interpreterRegs[20] = reg_20; - Refs.interpreterRegs[21] = reg_21; - Refs.interpreterRegs[22] = reg_22; - Refs.interpreterRegs[23] = reg_23; - Refs.interpreterRegs[24] = reg_24; - Refs.interpreterRegs[25] = reg_25; - Refs.interpreterRegs[26] = reg_26; - Refs.interpreterRegs[27] = reg_27; - Refs.interpreterRegs[28] = reg_28; - Refs.interpreterRegs[29] = reg_29; - Refs.interpreterRegs[30] = reg_30; - Refs.interpreterRegs[31] = reg_31; - } - } - - /** - * called by compiled code, when it detects - * that isInterrupted is true - */ - public static final String INTERRUPTED_METHOD = "c_interrupted"; - - public static void c_interrupted(int address) { - r3000.setPC(address); - isInterrupted = false; - r3000.compilerInterrupted(); - // check to see if we should return to the interpreter - if (context.cacheStale) { - context.cacheStale = false; - throw ContinueExecutionException.DONT_SKIP_CURRENT; - } - if (!ownRegs) { - interpreterToCompiler(); - } - } - - /** - * called by compiled code when it executes - * an instruction whose side effects are unknown - */ - public static final String SAFE_RETURN_METHOD = "c_safe_return"; - - public static void c_safe_return() { - if (!ownRegs) { - interpreterToCompiler(); - } - } - - public static final String JUMP_METHOD = "c_jump"; - - public static int c_jump(int address, int returnAddress) { - context.nativeDepth++; - if (context.nativeDepth > Settings.maxNativeDepth) { - log.debug("STACK OVERFLOW; COLLAPSING..."); - returnToInterpreter(address); - } - //if (Debug.traceExecutionFlow) { - // System.out.println("Indirect compiled jump "+MiscUtil.toHex( address,8)+" with retaddr "+MiscUtil.toHex( returnAddress, 8)); - //} - CodeUnit unit = getCodeUnit(address); - - Executable exec = unit.getExecutable(); - if (exec == null) { - exec = makeExecutable(unit); - if (exec == null) { - returnToInterpreter(address); - } - } - int rc = exec.e(returnAddress, true); - context.nativeDepth--; - return rc; - } - - public static final String CALL_METHOD = "c_call"; - - public static void c_call(int address, int returnAddress) { - context.nativeDepth++; - if (context.nativeDepth > Settings.maxNativeDepth) { - log.debug("STACK OVERFLOW; COLLAPSING..."); - returnToInterpreter(address); - } - //if (Debug.traceExecutionFlow) { - // System.out.println("Indirect compiled jump "+MiscUtil.toHex( address,8)+" with retaddr "+MiscUtil.toHex( returnAddress, 8)); - //} - CodeUnit unit = getCodeUnit(address); - - Executable exec = unit.getExecutable(); - if (exec == null) { - exec = makeExecutable(unit); - if (exec == null) { - // this unconditionally throws exception - returnToInterpreter(address); - } - } - assert exec != null; - int rc = exec.e(returnAddress, false); - assert (rc == returnAddress) : "call to unit should always return to the right spot"; - context.nativeDepth--; - } - - public static void traceEnterUnit(int address, int returnAddress, boolean jump) { - System.out.println("Entering compiled unit " + MiscUtil.toHex(address, 8) + " retaddr=" + MiscUtil.toHex(returnAddress, 8) + " jump=" + jump + " r31=" + MiscUtil.toHex(reg_31, 8)); - } - - public static void traceCheckJumpTarget(int target, int returnAddress) { - System.out.println("Check jump target " + MiscUtil.toHex(target, 8) + ", retaddr " + MiscUtil.toHex(returnAddress, 8)); - } - - public static void traceDirectCall(int address, int returnAddress) { - System.out.println("Direct compiled call " + MiscUtil.toHex(address, 8) + " with retaddr " + MiscUtil.toHex(returnAddress, 8)); - } - - public static void traceDirectJump(int address, int returnAddress) { - System.out.println("Direct compiled jump " + MiscUtil.toHex(address, 8) + " with retaddr " + MiscUtil.toHex(returnAddress, 8)); - } - - public static void traceLeaveUnit(int address) { - System.out.println("Leaving compiled unit " + MiscUtil.toHex(address, 8)); - } - - /** - * If we got here, then we are trying to return to the interpreter due to an exception - * in stage2 compiled code, but the register values aren't all correct since the stage2 - * compiler deferred writing the values back until later and didn't expect to need the - * value at this point; this is a rare occurrence, and as such we don't mind taking the - * hit, which involves going back and figuring out what registers have constant values at this point. - *

- * Note that being able to do this relies on the fact that we only omit writing back registers - * whose values are constant; not that we calculate at run time - * - * @param pc - */ - private void fixupUnwrittenCompilerRegs(int base, int pc) { - if (fixupStage2Generator == null) { - fixupStage2Generator = new Stage2Generator("c2fixup.out", true); - } - CodeUnit unit = getCodeUnit(base); - assert unit.useStage2; - fixupStage2Generator.fixupUnwrittenRegs(unit, pc); - } -} - -// when we execute a class for the first time, we want to follow all links and make sure we have a JavaClass -// available for large methods (note they may have been destroyed)... - - diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java deleted file mode 100644 index b5eb9e9..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.ConstantPool; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.*; -import org.apache.log4j.Logger; -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.CompilationContext; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.R3000Impl; -import org.jpsx.runtime.util.ClassUtil; -import org.jpsx.runtime.util.MiscUtil; -import org.jpsx.runtime.util.Timing; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Set; - -// todo background generators need to save the state as atomically as possible (copying the instructions basically) -// todo the FlowInfo needs to be in sync too - the fact that we share that though means that we can (in the future) -// todo quickly detect differences between the actual code and the cached flow graph (without having to regen the -// todo flow graph)... stage2 generators should probably take a hash of the code from stage 1 to make sure all is kosher -public class Stage1Generator implements CompilationContext { - public static final Logger log = Logger.getLogger("Stage1"); - - protected static final String CLASS_NAME_PREFIX = "_1"; - protected static final String STATIC_METHOD = "s"; - protected static final String NORMAL_METHOD = "e"; - protected static final String UNINLINED_METHOD_PREFIX = "_"; - - protected final FlowAnalyzer analyzer = new FlowAnalyzer(); - - // state shared with sub-class - protected final int[] opCodes = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected final CPUInstruction[] instructions = new CPUInstruction[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected final int[] regsRead = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected final int[] regsWritten = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected final int[] flags = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected PrintStream codeWriter; - - private final int[] simulateRegs = new int[32]; - private final InstructionList[] instructionLists = new InstructionList[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - private final HashMap extraInstructionLists = new HashMap(); - private final InstructionHandle[] endHandles = MultiStageCompiler.Settings.printCode ? (new InstructionHandle[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]) : null; - private final InstructionList printCodeIL = new InstructionList(); - - private String codeFilename; - - private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); - - /** - * Generators are not thread safe, and they also can assert in pertinent places that they are being called from the correct - * thread, as this stuff gets a bit complicated/messy. - */ - protected final boolean intendedForExecutionThread; - - public Stage1Generator(String codeFilename, boolean intendedForExecutionThread) { - this.codeFilename = codeFilename; - this.intendedForExecutionThread = intendedForExecutionThread; - if (MultiStageCompiler.Settings.printCode) { - try { - codeWriter = new PrintStream(new FileOutputStream(codeFilename)); - } catch (IOException e) { - throw new InvalidConfigurationException("can't open " + codeFilename + " for output", e); - } - } - } - - protected final String R3000_CLASS = r3000.getClass().getName(); - protected static final String COMPILER_CLASS = MultiStageCompiler.class.getName(); - protected final String ADDRESS_SPACE_CLASS = addressSpace.getMainStaticInterfaceClassName(); - protected final String HW_CLASS = addressSpace.getHardwareStaticInterfaceClassName(); - - protected static final String EXECUTABLE_CLASS = Executable.class.getName(); - protected static final String CODEUNIT_CLASS = CodeUnit.class.getName(); - protected static final String CODEUNIT_SIGNATURE = ClassUtil.signatureOfClass(CODEUNIT_CLASS); - - protected static final int LOCAL_RETADDR = 0; - protected static final int LOCAL_JUMP = 1; - protected static final int LOCAL_PRIVATE_TEMP = 2; - protected static final int LOCAL_TEMP0 = 3; - protected static final int LOCAL_LAST = 8; - - protected static final int MINIMUM_INSTRUCTIONS_PER_METHOD = 4; - - protected static final int ALL_REGS = 0xffffffff; - protected static final int WRITABLE_REGS = 0xfffffffe; - - protected String getClassNamePrefix(CodeUnit unit) { - return CLASS_NAME_PREFIX; - } - - protected int getMaxMethodInstructionCount() { - return MultiStageCompiler.Settings.maxMethodInstructionCount; - } - - protected boolean shouldPrintCode() { - return true; - } - - protected void emitMethodHeader(InstructionList il) { - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new PUSH(contextCP, contextBase)); - il.append(new ILOAD(LOCAL_RETADDR)); - il.append(new ILOAD(LOCAL_JUMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceEnterUnit", "(IIZ)V"))); - } - FieldGen fg = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, Type.getType(CODEUNIT_SIGNATURE), "unit", contextCP); - contextClassGen.addField(fg.getField()); - il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE))); - il.append(new GETFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "useStage2", "Z"))); - IFEQ ifeq = new IFEQ(null); - il.append(ifeq); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(Stage2Generator.CLASS_NAME_PREFIX, contextBase), STATIC_METHOD, "(IZ)I"))); - il.append(new IRETURN()); - ifeq.setTarget(il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE)))); - il.append(new GETFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "count", "I"))); - il.append(new ISTORE(LOCAL_TEMP0)); - il.append(new ILOAD(LOCAL_TEMP0)); - IFLE ifle = new IFLE(null); - il.append(ifle); - il.append(new IINC(LOCAL_TEMP0, -1)); - il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE))); - il.append(new ILOAD(LOCAL_TEMP0)); - il.append(new PUTFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "count", "I"))); - GOTO gt = new GOTO(null); - il.append(gt); - ifle.setTarget(il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE)))); - il.append(new INVOKEVIRTUAL(contextCP.addMethodref(CODEUNIT_CLASS, "countComplete", "()V"))); - gt.setTarget(il.append(new NOP())); - - } - - protected void emitBlockHeader(InstructionList il) { - contextDelaySlotEmitted = false; - } - - protected void emitBlockFooter(InstructionList il) { - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - // make sure we got all the code - int size = contextBlock.size; - if (size != 0) { - if (contextBlock.branchOut != null && contextBlock.includesDelaySlot) { - // don't want to count the delay slot, which will be output by the branch anyway - size--; - } - assert size > 0; - endHandles[contextBlock.offset + size - 1] = il.getEnd(); - } - } - contextDelaySlotEmitted = false; - } - - protected void initBlockStructures(FlowAnalyzer.FlowInfo flowInfo) { - noInterruptCheck = false; - extraInstructionLists.clear(); - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - if (block.size != 0) { - if (instructionLists[block.offset] == null) { - instructionLists[block.offset] = new InstructionList(); - } else { - // instruction list should be empty - assert null == instructionLists[block.offset].getStart(); - } - } - for (int offset = block.offset; offset < block.offset + block.size; offset++) { - int address = flowInfo.base + offset * 4; - int ci = addressSpace.internalRead32(address); - opCodes[offset] = ci; - CPUInstruction inst = r3000.decodeInstruction(ci); - instructions[offset] = inst; - int iFlags = inst.getFlags(); - flags[offset] = iFlags; - regsRead[offset] = 0; - regsWritten[offset] = 0; - if (0 != (iFlags & CPUInstruction.FLAG_READS_RS)) { - regsRead[offset] |= 1 << R3000.Util.bits_rs(ci); - } - if (0 != (iFlags & CPUInstruction.FLAG_READS_RT)) { - regsRead[offset] |= 1 << R3000.Util.bits_rt(ci); - } - if (0 != (iFlags & CPUInstruction.FLAG_WRITES_RT)) { - regsWritten[offset] |= 1 << R3000.Util.bits_rt(ci); - } - if (0 != (iFlags & CPUInstruction.FLAG_WRITES_RD)) { - regsWritten[offset] |= 1 << R3000.Util.bits_rd(ci); - } - if (MultiStageCompiler.Settings.biosInterruptWorkaround) { - if (0 != (regsWritten[offset] & 0x0c000000)) { - noInterruptCheck = true; - } - } - if (0 != (iFlags & CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE)) { - regsRead[offset] = ALL_REGS; - regsWritten[offset] |= WRITABLE_REGS; - } else if (0 != (iFlags & CPUInstruction.FLAG_LINK)) { - regsRead[offset] = ALL_REGS; - regsWritten[offset] |= ~MultiStageCompiler.Settings.savedOnCallRegs; - } - regsWritten[offset] &= WRITABLE_REGS; - } - } - if (MultiStageCompiler.Settings.biosInterruptWorkaround && noInterruptCheck) { - if (log.isDebugEnabled()) { - log.debug("*** BIOS BUG WORKAROUND FOR " + MiscUtil.toHex(flowInfo.base, 8)); - } - } - } - - public String getClassName(String prefix, int base) { - return prefix + MiscUtil.toHex(base, 8); - } - - protected void emitICodeUnitMethods() { - contextClassGen.addInterface(EXECUTABLE_CLASS); - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.INT, new Type[]{Type.INT, Type.BOOLEAN}, new String[]{"retAddr", "jump"}, "e", contextClassGen.getClassName(), il, contextCP); - - il.append(new ILOAD(1)); - il.append(new ILOAD(2)); - il.append(new INVOKESTATIC(contextCP.addMethodref(contextClassGen.getClassName(), STATIC_METHOD, "(IZ)I"))); - il.append(new IRETURN()); - mg.setMaxLocals(); - mg.setMaxStack(); - contextClassGen.addMethod(mg.getMethod()); - il.dispose(); - } - - protected void emitMethods(FlowAnalyzer.FlowInfo flowInfo) { - emitICodeUnitMethods(); - emitStaticExecuteMethod(flowInfo); - } - - protected void emitStaticExecuteMethod(FlowAnalyzer.FlowInfo flowInfo) { - InstructionList methodIL = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, Type.INT, new Type[]{Type.INT, Type.BOOLEAN}, new String[]{"retAddr", "jump"}, STATIC_METHOD, contextClassGen.getClassName(), methodIL, contextCP); - - if (R3000Impl.Settings.skipShell && !R3000Impl.shellHit && contextBase == 0x80030000) { - R3000Impl.shellHit = true; - methodIL.append(new ILOAD(LOCAL_RETADDR)); - methodIL.append(new IRETURN()); - } else { - emitDebugs(methodIL); - - emitMethodHeader(methodIL); - - Set methodBlocks = CollectionsFactory.newHashSet(); - - int maxCount = getMaxMethodInstructionCount(); - if (flowInfo.instructionCount > maxCount) { - if (log.isDebugEnabled()) { - log.debug("Too many instructions in " + Integer.toHexString(flowInfo.base)); - } - // too many instructions, we want to sort basic blocks - // by size, and choose to inline the code up to the branch - // from each one - //System.out.println("sorting for "+flowInfo.instructionCount); - FlowAnalyzer.BasicBlock sizedBlocks[] = new FlowAnalyzer.BasicBlock[flowInfo.blockCount]; - int index = 0; - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - sizedBlocks[index++] = block; - } - Arrays.sort(sizedBlocks, new Comparator() { - public int compare(FlowAnalyzer.BasicBlock b1, FlowAnalyzer.BasicBlock b2) { - return getSizeWithoutBranch(b2) - getSizeWithoutBranch(b1); - } - }); - int instructionCount = flowInfo.instructionCount; - for (int i = 0; i < sizedBlocks.length && instructionCount > maxCount; i++) { - int size = getSizeWithoutBranch(sizedBlocks[i]); - if (size < MINIMUM_INSTRUCTIONS_PER_METHOD) { - break; - } - //System.out.println("collapsing block "+(i+1)+"/"+sizedBlocks.length+" size "+sizedBlocks[i].size); - instructionCount -= size; - methodBlocks.add(sizedBlocks[i]); - if (log.isDebugEnabled()) { - log.debug(" must call to "+sizedBlocks[i]+" size "+getSizeWithoutBranch(sizedBlocks[i])); - } - } - //System.out.println("final instruction count "+instructionCount); - } - - contextMethodGen = mg; - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - contextBlock = block; - if (MultiStageCompiler.Settings.printRare && block.branchOut != null && !block.includesDelaySlot) { - System.out.println(block); - } - - InstructionList blockIL = getInstructionList(block); - emitBlockHeader(blockIL); - if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { - int size = block.size; - if (block.branchOut != null && block.includesDelaySlot) { - // don't want to count the delay slot, which will be output by the branch anyway - size--; - } - if (methodBlocks.contains(block)) { - String methodname = UNINLINED_METHOD_PREFIX + block.offset; - InstructionList innerMethodIL = new InstructionList(); - MethodGen mgInner = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, Type.VOID, new Type[]{}, new String[]{}, methodname, contextClassGen.getClassName(), innerMethodIL, contextCP); - // emit head of block - int headSize = getSizeWithoutBranch(block); - contextMethodGen = mgInner; - emitCode(innerMethodIL, 0, headSize); - innerMethodIL.append(new RETURN()); - contextMethodGen = mg; - addMethod(mgInner); - blockIL.append(new INVOKESTATIC(contextCP.addMethodref(contextClassGen.getClassName(), methodname, "()V"))); - if (headSize != size) { - // emit branch part - emitCode(blockIL, headSize, size); - } - } else { - // emit whole block - emitCode(blockIL, 0, size); - } - if (block.branchOut != null && !block.includesDelaySlot && block.flowOut != null) { - // if we are missing our delay slot, and flow into the next block, it - // should be a single instruction which just flows into the next block - // (i.e. a delay slot instruction) - assert (block.flowOut.size == 1); - assert (block.flowOut.branchOut == null); - assert (block.flowOut.flowOut != null); - // we want to skip it, since we've already executed the delay slot - blockIL.append(new GOTO(getStartHandle(block.flowOut.flowOut))); - } - } else if (block.type == FlowAnalyzer.BasicBlock.JUMP_WRAPPER) { - emitJump(blockIL, contextBase + (block.offset << 2)); - } - emitBlockFooter(blockIL); - } - - // block instructions are only appended after all code is generated, since append removes - // the instructions from the block instruction lists - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - methodIL.append(getInstructionList(block)); - } - methodIL.append(new ILOAD(LOCAL_RETADDR)); - methodIL.append(new IRETURN()); - - } - - addMethod(mg); - } - - protected InstructionList getInstructionList(FlowAnalyzer.BasicBlock block) { - if (block.size != 0) { - return instructionLists[block.offset]; - } else { - InstructionList rc = (InstructionList) extraInstructionLists.get(block); - if (rc == null) { - rc = new InstructionList(); - extraInstructionLists.put(block, rc); - } - return rc; - } - } - - protected void disassemble(int index) { - int address = contextBase + (index << 2); - String prefix = ""; - if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_DELAY_SLOT)) { - prefix += "D"; - } else { - prefix += " "; - } - String prefix1 = ""; - String suffix = ""; - int ci = opCodes[index]; - String dis = r3000.disassemble(address, ci); - codeWriter.println(" " + prefix + " " + prefix1 + " " + MiscUtil.toHex(address, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis + suffix); - } - - protected void addMethod(MethodGen mg) { - mg.setMaxLocals(LOCAL_LAST); - mg.setMaxStack(); - Method m = mg.getMethod(); - if (m.getCode().getCode().length > 8000) { - if (log.isDebugEnabled()) { - log.debug(contextClassGen.getClassName() + "." + m.getName() + " has " + (m.getCode().getCode().length) + " bytes bytcode"); - } - } - contextClassGen.addMethod(m); - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - printCodeIL.append(mg.getInstructionList()); - } else { - mg.getInstructionList().dispose(); - } - } - - protected void emitConstructor() { - contextClassGen.addEmptyConstructor(Constants.ACC_PUBLIC); - } - - // PERF:addr:blocks:instructions:flow:initBlock:emitMethods:getJavaClass:createClass - - // can return null if not on execution thread for garbage looking code - public JavaClass createJavaClass(CodeUnit unit, boolean executionThread) { - return createJavaClass(unit, getClassName(getClassNamePrefix(unit), unit.getBase()), executionThread); - } - - // can return null if not on execution thread for garbage looking code - public JavaClass createJavaClass(CodeUnit unit, String classname, boolean executionThread) { - assert executionThread == this.intendedForExecutionThread; - contextUnit = unit; - contextBase = unit.getBase(); - contextClassGen = new ClassGen(classname, "java.lang.Object", - "", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null); - contextCP = contextClassGen.getConstantPool(); - - emitConstructor(); - long t0 = 0; - StringBuilder perf = null; - if (MultiStageCompiler.Settings.statistics) { - perf = new StringBuilder(); - t0 = Timing.nanos(); - } - FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(analyzer, executionThread);//analyzer.buildFlowGraph( contextBase, getMaxMethodInstructionCount()); - if (flowInfo == null) { - return null; - } - contextUnitIsGarbage = false; - if (MultiStageCompiler.Settings.statistics) { - long t1 = Timing.nanos() - t0; - perf.append("PERF:"); - perf.append(MiscUtil.toHex(unit.getBase(), 8)); - perf.append(':'); - perf.append(flowInfo.blockCount); - perf.append(':'); - perf.append(flowInfo.instructionCount); - perf.append(':'); - perf.append(t1); - t0 = Timing.nanos(); - } - initBlockStructures(flowInfo); - if (MultiStageCompiler.Settings.statistics) { - long t1 = Timing.nanos() - t0; - perf.append(':'); - perf.append(t1); - t0 = Timing.nanos(); - } - emitMethods(flowInfo); - if (contextUnitIsGarbage) { - return null; - } - if (MultiStageCompiler.Settings.statistics) { - long t1 = Timing.nanos() - t0; - perf.append(':'); - perf.append(t1); - t0 = Timing.nanos(); - } - JavaClass jclass = contextClassGen.getJavaClass(); - if (MultiStageCompiler.Settings.statistics) { - long t1 = Timing.nanos() - t0; - perf.append(':'); - perf.append(t1); - } - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - ConstantPool cp = jclass.getConstantPool(); - codeWriter.println(getClassNamePrefix(unit) + " unit at " + MiscUtil.toHex(contextBase, 8)); - InstructionHandle h = printCodeIL.getStart(); - InstructionHandle hLast = null; - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - codeWriter.println(" " + block); - - int size = block.size; - if (block.branchOut != null && block.includesDelaySlot) { - // don't want to count the delay slot, which will be output by the branch anyway - size--; - } - for (int index = block.offset; index < block.offset + size; index++) { - disassemble(index); - if (0 != (flags[index] & CPUInstruction.FLAG_BRANCH)) { - // disassemble delay slot - disassemble(index + 1); - } - InstructionHandle hEnd = endHandles[index]; - assert (hEnd != null); - if (hEnd != hLast) { - while (h != null) { - String bo = "" + h.getPosition(); - while (bo.length() < 5) { - bo = " " + bo; - } - codeWriter.println(bo + " " + h.getInstruction().toString(cp)); - hLast = h; - h = h.getNext(); - if (hLast == hEnd) - break; - } - } - if (0 != (flags[index] & CPUInstruction.FLAG_BRANCH)) { - // skip delay slot - index++; - } - } - } - printCodeIL.dispose(); - } - - if (MultiStageCompiler.Settings.saveClasses) { - try { - jclass.dump(codeFilename + classname + ".class"); - } catch (IOException ioe) { - } - } - return jclass; - } - - protected int getSizeWithoutBranch(FlowAnalyzer.BasicBlock b) { - if (b.branchOut == null) { - return b.size; - } else { - return b.branchOffset - b.offset; - } - } - - protected void emitCode(InstructionList il, int startOffset, int endOffset) { - startOffset += contextBlock.offset; - endOffset += contextBlock.offset; - for (contextOffset = startOffset; contextOffset < endOffset && !contextUnitIsGarbage; contextOffset++) { - // skip the instruction after an instruction which emitted a delay slot - if (contextDelaySlotEmitted) { - contextDelaySlotEmitted = false; - } else { - emitContextInstruction(il); - } - } - } - - protected void emitDebugs(InstructionList il) { - if (contextBase == 0xbfc018e0) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugPrintf", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - - if (!R3000Impl.Settings.debugBIOS) return; - - // todo, register functions s.t. the compiler can insert these also! - if (contextBase == 0x00001b44) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugDeliverEvent", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - - if (contextBase == 0xa0) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugA0", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - - if (contextBase == 0xb0) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugB0", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - - if (contextBase == 0xc0) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugC0", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - } - - public void emitContextInstruction(InstructionList il) { - contextAddress = contextBase + (contextOffset << 2); - - InstructionHandle endHandle = null; - - if (MultiStageCompiler.Settings.addLineNumbers) { - endHandle = il.getEnd(); - } - - if (MultiStageCompiler.Settings.profiling && contextOffset == contextBlock.offset) { - il.append(new PUSH(contextCP, contextAddress)); - il.append(new INVOKESTATIC(contextCP.addMethodref("jsx.core.NativeCompiler", "blockUsed", "(I)V"))); - } - - if (MultiStageCompiler.Settings.megaTrace) { - il.append(new PUSH(contextCP, contextAddress)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "dumpState", "(I)V"))); - } - - if (contextBlock.branchOut != null && contextBlock.branchOffset == contextOffset) { - assert 0 != (flags[contextOffset] & CPUInstruction.FLAG_BRANCH) : contextBlock + " " + MiscUtil.toHex(contextAddress, 8); - if (contextBlock.branchOut.offset <= contextBlock.offset) { - emitBreakoutCheck(il); - } - } - - // certain instructions require us to set the PC correctly - // todo check for delay slot! - if (MultiStageCompiler.Settings.debugPC || 0 != (flags[contextOffset] & (CPUInstruction.FLAG_REFERENCES_PC | - CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE | - CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE))) { - il.append(new PUSH(contextCP, contextAddress)); - il.append(new PUTSTATIC(contextCP.addFieldref(R3000_CLASS, "reg_pc", "I"))); - } - - emitContextInstructionGuts(il); - - if (0 != (flags[contextOffset] & CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE)) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - - if (MultiStageCompiler.Settings.addLineNumbers) { - // no point if we didn't add any code - if (endHandle != il.getEnd()) { - InstructionHandle first = endHandle == null ? il.getStart() : endHandle.getNext(); - // note the TAG_DELAY_SLOT will allow the exception handling code that uses the line numbers - // to know to re-execute from the previous instruction, however that doesn't take care of the - // case of code that branches directly to a delay slot. - // todo we don't handle that well today, but should be making separate basic blocks, and - // todo we could mark the code for that case with a special line number (e.g. very big) - // todo to tell the exception handling code not to step back - contextMethodGen.addLineNumber(first, contextOffset); - } - } - - if (contextIsDelaySlot) { - addressSpace.orTag(contextAddress, MultiStageCompiler.TAG_DELAY_SLOT); - } - - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - endHandle = il.getEnd(); - if (endHandle == null) endHandle = il.append(new NOP()); - endHandles[contextOffset] = endHandle; - } - } - - protected void emitBreakoutCheck(InstructionList il) { - if (!noInterruptCheck) { - // todo delay slot - il.append(new GETSTATIC(contextCP.addFieldref(COMPILER_CLASS, "isInterrupted", "Z"))); - IFEQ ieq = new IFEQ(null); - il.append(ieq); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERRUPTED_METHOD, "(I)V"))); - ieq.setTarget(il.append(new NOP())); - } - } - - protected void emitContextInstructionGuts(InstructionList il) { - // should simulate instructions which just read r0 - if (regsRead[contextOffset] == 1 && 0 != (flags[contextOffset] & CPUInstruction.FLAG_SIMULATABLE) && instructions[contextOffset].simulate(opCodes[contextOffset], simulateRegs)) { - for (int i = 1; i < 32; i++) { - if ((regsWritten[contextOffset] & (1 << i)) != 0) { - il.append(new PUSH(contextCP, simulateRegs[i])); - emitSetReg(il, i); - } - } - } else { - instructions[contextOffset].compile(this, contextAddress, opCodes[contextOffset], il); - } - } - - public InstructionHandle getStartHandle(FlowAnalyzer.BasicBlock block) { - InstructionHandle rc = getInstructionList(block).getStart(); - if (rc == null) { - rc = getInstructionList(block).append(new NOP()); - } - return rc; - } - // ------------- ICompilationContext - - // todo remove this, and pass to compiler - - public ConstantPoolGen getConstantPoolGen() { - return contextCP; - } - - protected boolean noInterruptCheck; - protected FlowAnalyzer.BasicBlock contextBlock; - protected int contextBase; - protected int contextOffset; - protected int contextAddress; - protected MethodGen contextMethodGen; - protected ConstantPoolGen contextCP; - protected ClassGen contextClassGen; - protected AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); - protected boolean contextDelaySlotEmitted; - protected boolean contextIsDelaySlot; - protected CodeUnit contextUnit; - protected boolean contextUnitIsGarbage; - - protected void invokeStaticMethod(java.lang.reflect.Method method) { - - } - - public void emitInterpretedInstruction(InstructionList il, int ci, String clazz, String method) { - - if (0 != (flags[contextOffset] & CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE)) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - } else { - int readsReg = getReadsReg(); - for (int r = 1; r < 32; r++) { - if (0 != (readsReg & (1 << r))) { - // R3000Impl.regs[r] = CompiledR3000.reg_r; - il.append(new GETSTATIC(contextCP.addFieldref(R3000_CLASS, "regs", "[I"))); - - il.append(new PUSH(contextCP, r)); - if (0 != (getConstantRegs() & (1 << r))) { - il.append(new PUSH(contextCP, getRegValue(r))); - } else { - emitGetReg(il, r); - } - il.append(new IASTORE()); - } - } - } - - il.append(new PUSH(contextCP, ci)); - il.append(new INVOKESTATIC(contextCP.addMethodref(clazz, method, "(I)V"))); - - if (0 != (flags[contextOffset] & (CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE))) { - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } else { - int writesReg = getWritesReg(); - for (int r = 1; r < 32; r++) { - if (0 != (writesReg & (1 << r))) { - // CompiledR3000.reg_r = R3000Impl.reg[r]; - il.append(new GETSTATIC(contextCP.addFieldref(R3000_CLASS, "regs", "[I"))); - il.append(new PUSH(contextCP, r)); - il.append(new IALOAD()); - emitSetReg(il, r); - } - } - } - } - - public void emitGetReg(InstructionList il, int reg) { - il.append(new GETSTATIC(contextCP.addFieldref(COMPILER_CLASS, "reg_" + reg, "I"))); - } - - public void emitSetReg(InstructionList il, int reg) { - assert reg != 0; - il.append(new PUTSTATIC(contextCP.addFieldref(COMPILER_CLASS, "reg_" + reg, "I"))); - } - - public int getRegValue(int reg) { - assert reg == 0; - return 0; - } - - public int getConstantRegs() { - return 1; - } - - public int getWritesReg() { - return regsWritten[contextOffset]; - } - - public int getReadsReg() { - return regsRead[contextOffset]; - } - - public void emitJump(InstructionList il, int address) { - il.append(new PUSH(contextCP, address)); - emitJump(il); - } - - public void emitJump(InstructionList il) { - // this is decompilable (uses local var target) - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - InstructionHandle loop = il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new ILOAD(LOCAL_RETADDR)); - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new ILOAD(LOCAL_RETADDR)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceCheckJumpTarget", "(II)V"))); - } - IF_ICMPEQ icmpeq = new IF_ICMPEQ(null); - il.append(icmpeq); - - il.append(new ILOAD(LOCAL_JUMP)); - IFEQ ieq = new IFEQ(null); - il.append(ieq); - - icmpeq.setTarget(il.append(new ILOAD(LOCAL_PRIVATE_TEMP))); - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new PUSH(contextCP, contextBase)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceLeaveUnit", "(I)V"))); - } - il.append(new IRETURN()); - ieq.setTarget(il.append(new ILOAD(LOCAL_PRIVATE_TEMP))); - il.append(new ILOAD(LOCAL_RETADDR)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.JUMP_METHOD, "(II)I"))); - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new GOTO(loop)); - } - - public InstructionHandle getBranchTarget(int address) { - if (!intendedForExecutionThread && contextBlock.branchOut == null) { - contextUnitIsGarbage = true; - // a branch to ourselves - return getStartHandle(contextBlock); - } - assert contextBlock.branchOut != null : "null branch target - wanted " + MiscUtil.toHex(address, 8) + " base = " + MiscUtil.toHex(contextBlock.base, 8); - assert contextBase + (contextBlock.branchOut.offset << 2) == address : - contextBlock + ": Expected branch target " + MiscUtil.toHex(contextBase + (contextBlock.branchOut.offset << 2), 8) + " != actual " + MiscUtil.toHex(address, 8); - - if (MultiStageCompiler.Settings.printRare && address == contextAddress) { - System.out.println("Branch to self at " + MiscUtil.toHex(address, 8)); - } - return getStartHandle(contextBlock.branchOut); - } - - public void emitCall(InstructionList il, int address, int retAddr) { - if (R3000Impl.Settings.dumpRegsOnCall && R3000Impl.shouldDumpRegs(address)) { - il.append(new PUSH(contextCP, address)); - il.append(new PUTSTATIC(contextCP.addFieldref(R3000_CLASS, "reg_pc", "I"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "dumpRegs", "()V"))); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); - } - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new PUSH(contextCP, address)); - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceDirectCall", "(II)V"))); - } - - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagClearPollCounters", "()V"))); - - if (AddressSpace.Util.isBIOS(contextAddress) && !AddressSpace.Util.isBIOS(address)) { - // calling from bios to ram must be indirect... note this is probably rare. - // todo i've seen the BIOS classloader have ram classes; I wonder why - //System.out.println( "Emitting bios to ram call" ); - il.append(new PUSH(contextCP, address)); - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); - } else { - il.append(new PUSH(contextCP, retAddr)); - il.append(new PUSH(contextCP, 0)); - il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(CLASS_NAME_PREFIX, address), STATIC_METHOD, "(IZ)I"))); - il.append(new POP()); - } - } - - /** - * Used for JALR etc where the address to call is at the top - * of the JVM stack - */ - public void emitCall(InstructionList il, int retAddr) { -/* if (R3000Impl.Settings.dumpRegsOnCall) { - il.append( new DUP()); - il.append( new PUTSTATIC( contextCP.addFieldref( R3000_CLASS, "reg_pc", "I" ) ) ); - il.append( new INVOKESTATIC( contextCP.addMethodref( COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V" ) ) ); - il.append( new INVOKESTATIC( contextCP.addMethodref( R3000_CLASS, "dumpRegs", "()V" ) ) ); - il.append( new INVOKESTATIC( contextCP.addMethodref( COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V" ) ) ); - }*/ - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagClearPollCounters", "()V"))); - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); - } - - public void emitReadMem8(InstructionList il, int address, boolean signed) { - rr.mem = null; - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); - return; - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); - } - if (signed) { - switch (address & 3) { - case 2: - il.append(new PUSH(contextCP, 8)); - il.append(new ISHL()); - break; - case 1: - il.append(new PUSH(contextCP, 16)); - il.append(new ISHL()); - break; - case 0: - il.append(new PUSH(contextCP, 24)); - il.append(new ISHL()); - break; - } - il.append(new PUSH(contextCP, 24)); - il.append(new ISHR()); - } else { - switch (address & 3) { - case 3: - il.append(new PUSH(contextCP, 24)); - il.append(new ISHR()); - break; - case 2: - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - break; - case 1: - il.append(new PUSH(contextCP, 8)); - il.append(new ISHR()); - break; - } - il.append(new PUSH(contextCP, 0xff)); - il.append(new IAND()); - } - } - - public void emitReadMem8(InstructionList il, int reg, int offset) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead8", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); - } - - public void emitReadMem16(InstructionList il, int address, boolean signed) { - rr.mem = null; - if (0 == (address & 1)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); - return; - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - if (signed) { - if (0 == (address & 2)) { - il.append(new PUSH(contextCP, 16)); - il.append(new ISHL()); - } - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - } else { - if (0 != (address & 2)) { - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - } - il.append(new PUSH(contextCP, 0xffff)); - il.append(new IAND()); - } - } - - public void emitReadMem16(InstructionList il, int reg, int offset) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead16", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - - public void emitReadMem32(InstructionList il, int address, boolean forceAlign) { - rr.mem = null; - if (forceAlign) { - address &= ~3; - } - if (0 == (address & 3)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "_read32", "(I)I"))); - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "read32", "(I)I"))); - } - } - - public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); - } - - public void emitWriteMem8(InstructionList il, int address, InstructionList il2) { - InstructionList il3 = new InstructionList(); - emitReadMem32(il3, address, true); - switch (address & 3) { - case 0: - il3.append(new PUSH(contextCP, 0xffffff00)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new IOR()); - break; - case 1: - il3.append(new PUSH(contextCP, 0xffff00ff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new PUSH(contextCP, 8)); - il3.append(new ISHL()); - il3.append(new IOR()); - break; - case 2: - il3.append(new PUSH(contextCP, 0xff00ffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new PUSH(contextCP, 16)); - il3.append(new ISHL()); - il3.append(new IOR()); - break; - default: - il3.append(new PUSH(contextCP, 0xffffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 24)); - il3.append(new ISHL()); - il3.append(new IOR()); - } - emitWriteMem32(il, address, il3, true); - il3.dispose(); - } - - public void emitWriteMem8(InstructionList il, int reg, int offset) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8", "(II)V"))); - } - - public void emitWriteMem16(InstructionList il, int address, InstructionList il2) { - if ((address & 1) != 0) { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); - } else { - InstructionList il3 = new InstructionList(); - // il3.stack(0) = oldvalue - emitReadMem32(il3, address, true); - switch (address & 3) { - case 0: - // il3.stack(1) = mask; - il3.append(new PUSH(contextCP, 0xffff0000)); - il3.append(new IAND()); - // il3.stack(0) = maskedOldValue; - il3.append(il2); - // il3.stack(1) = newvalue; - il3.append(new PUSH(contextCP, 0xffff)); - // il3.stack(2) = mask; - il3.append(new IAND()); - // il3.stack(1) = maskedNewValue; - il3.append(new IOR()); - // il3.stack(0) = newMemValue - break; - default: - il3.append(new PUSH(contextCP, 0xffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 16)); - il3.append(new ISHL()); - il3.append(new IOR()); - } - emitWriteMem32(il, address, il3, true); - il3.dispose(); - } - } - - public void emitWriteMem16(InstructionList il, int reg, int offset) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); - } - - public void emitWriteMem32(InstructionList il, int address, InstructionList il2, boolean forceAlign) { - rr.mem = null; - if (forceAlign) { - address &= ~3; - } - if (0 == (address & 3)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(il2); - il.append(new IASTORE()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(il2); - il.append(new IASTORE()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - /* - il.append( new GETSTATIC( contextCP.addFieldref( ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append( new PUSH( contextCP, rr.offset)); - il.append( il2); - il.append( new IASTORE());*/ - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); - } else { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - } - - public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList il2, boolean forceAlign) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { - il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); - il.append(new PUSH(contextCP, contextAddress)); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); - il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); - } - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - - public void emitDelaySlot(InstructionList il) { - contextOffset++; - contextIsDelaySlot = true; - emitContextInstruction(il); - contextIsDelaySlot = false; - contextDelaySlotEmitted = true; - contextOffset--; - //assert 0!=(flags[contextOffset]&Instruction.FLAG_BRANCH); - //if (delaySlot==null) { - // delaySlot = new CompilationContext1( mg, contextCP); - //} - //delaySlot.compile( contextAddress+4, il); - //delaySlotEmitted = true; - } - - public final int getTempLocal(int index) { - int rc = LOCAL_TEMP0 + index; - if (rc >= LOCAL_LAST) - throw new IllegalStateException("too many locals!"); - return rc; - } - - // ---- -} \ No newline at end of file diff --git a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java b/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java deleted file mode 100644 index a5cdc0e..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.emulator.compiler; - -import org.apache.bcel.Constants; -import org.apache.bcel.generic.*; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.R3000Impl; -import org.jpsx.runtime.util.MiscUtil; - -import java.util.Stack; - -// todo is this true now? - -// note while it is tempting to omit the intervening write of reg8 here, -// -// addiu r8, r4, r0 -// lw r8, r8[4] -// -// we cannot do so (unless we know the value of r4 at compile time), because -// a memory type misprediction of the memory read in the lw instruction would -// cause us to have to re-execute the second instruction in the interpreter, and we wouldn't have -// a good way to figure out the true value of r8. -// -// Note, that it might be possible to do this, but it would involve more complicated -// code to figure out what we had done when we compiled the code, and then simulate the instructions we skipped. -// -// In the meanwhile, we just cope with figuring out what registers are constant at the re-execute - -// point, and write all of those back -public class Stage2Generator extends Stage1Generator { - protected static String CLASS_NAME_PREFIX = "_2"; - - private static final int READ_TAG_MASK = (AddressSpace.TAG_RAM | - AddressSpace.TAG_SCRATCH | - AddressSpace.TAG_HW | - AddressSpace.TAG_BIOS | - AddressSpace.TAG_PAR | - AddressSpace.TAG_POLL) & 0xff; - - private int getRegsOffset = -1; - private int[] regsAtOffset = new int[32]; - private int CRAtOffset = 0; - private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); - - public Stage2Generator(String codeFilename, boolean intendedForExecutionThread) { - super(codeFilename, intendedForExecutionThread); - } - - protected String getClassNamePrefix(CodeUnit unit) { - return "_" + (2 + unit.stage2Version); - } - - protected String getNextClassNamePrefix(CodeUnit unit) { - return "_" + (3 + unit.stage2Version); - } - - protected void emitBreakoutCheck(InstructionList il) { - // write back regs before the breakout check - writeBackRegs(il, ALL_REGS); - super.emitBreakoutCheck(il); - } - - protected void emitMethodHeader(InstructionList il) { - // don't emit all the junk that Compiler1 does - FieldGen fg = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, Type.BOOLEAN, "replaced", contextCP); - contextClassGen.addField(fg.getField()); - - il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "replaced", "Z"))); - IFEQ ifeq = new IFEQ(null); - il.append(ifeq); - il.append(new ILOAD(0)); - il.append(new ILOAD(1)); - il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(getNextClassNamePrefix(contextUnit), contextBase), STATIC_METHOD, "(IZ)I"))); - il.append(new IRETURN()); - ifeq.setTarget(il.append(new NOP())); - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new PUSH(contextCP, contextBase)); - il.append(new ILOAD(LOCAL_RETADDR)); - il.append(new ILOAD(LOCAL_JUMP)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceEnterUnit", "(IIZ)V"))); - } - if (false/*Debug.dumpRegsOnCall*/) { - il.append(new PUSH(contextCP, contextBase)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "dumpState", "(I)V"))); - } - } - - protected static final boolean debugCR = true; - - protected BlockInfo[] blockInfo = new BlockInfo[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - /** - * Instructions that can safely be omitted because they have constant input and the - * output can be determined by simulation - */ - protected boolean[] simulated = new boolean[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; - protected Stack dirtyBlocks = new Stack(); - protected int visitCount; - - protected class BlockInfo { - public BlockInfo(FlowAnalyzer.BasicBlock bb) { - this.bb = bb; - } - - FlowAnalyzer.BasicBlock bb; - boolean dirty; - boolean visited; - - int ICR; - int OCR; - int[] incomingRegValues = new int[32]; - int[] outgoingRegValues = new int[32]; - - public String toString() { - return "visited " + visited + " dirty " + dirty + " ICR " + MiscUtil.toHex(ICR, 8) + " OCR " + MiscUtil.toHex(OCR, 8) + " " + bb; - } - - public void updateIncoming(final int CR, final int[] regValues) { - // incoming constant regs are ANDed with what we knew before, unless we're - // not initialized yet (ICR==0) - int newICR = ICR == 0 ? CR : (CR & ICR); - - int stillConstant = ICR & newICR; - int nowConstant = (newICR ^ ICR) & newICR; - - int mask = 2; - for (int bit = 1; bit < 32; bit++) { - if (0 != (stillConstant & mask)) { - // check that the reg value isn't different for any "constant" register, - // meaning that it isn't constant. - if (incomingRegValues[bit] != regValues[bit]) { - newICR &= ~mask; - } - } else if (0 != (nowConstant & mask)) { - incomingRegValues[bit] = regValues[bit]; - } - mask <<= 1; - } - // note we will always be dirty at least once since ICR is initially zero - if (newICR != ICR) { - ICR = newICR; - dirty = true; - dirtyBlocks.push(this); - } - assert 1 == (ICR & 1); - } - - public void visit() { - if (dirty) { - if (debugCR) { - visitCount++; - } - //System.out.println( "visit "+this); - if (!visited) { - for (int i = 1; i < 32; i++) { - outgoingRegValues[i] = incomingRegValues[i]; - } - } - int oldOCR = OCR; - OCR = ICR; - simulate(!visited); - // after the first time through OCR should always be a subset of oldOCR - assert !visited || 0 == (OCR & ~oldOCR); - assert 1 == (OCR & 1); - dirty = false; - if (!visited || OCR != oldOCR) { - visited = true; - BlockInfo bbFlow = null; - BlockInfo bbBranch = null; - int scoreFlow = -1; - int scoreBranch = -1; - - if (bb.flowOut != null && bb.flowOut.type == FlowAnalyzer.BasicBlock.NORMAL) { - bbFlow = blockInfo[bb.flowOut.offset]; - // todo score - } - if (bb.branchOut != null && bb.branchOut.type == FlowAnalyzer.BasicBlock.NORMAL) { - bbBranch = blockInfo[bb.branchOut.offset]; - // todo score - } - - - if (scoreBranch > scoreFlow) { - bbBranch.updateIncoming(OCR, outgoingRegValues); - if (bbFlow != null) { - bbFlow.updateIncoming(OCR, outgoingRegValues); - } - } else if (scoreFlow > scoreBranch) { - bbFlow.updateIncoming(OCR, outgoingRegValues); - if (bbBranch != null) { - bbBranch.updateIncoming(OCR, outgoingRegValues); - } - } else { - if (bbBranch != null) { - bbBranch.updateIncoming(OCR, outgoingRegValues); - } - if (bbFlow != null) { - bbFlow.updateIncoming(OCR, outgoingRegValues); - } - } - } - } - } - - protected void simulateCalculate(int offset) { - if (0 != (flags[offset] & CPUInstruction.FLAG_SIMULATABLE) && - regsRead[offset] == (regsRead[offset] & OCR) && - instructions[offset].simulate(opCodes[offset], outgoingRegValues)) { - simulated[offset] = true; - OCR |= regsWritten[offset]; - } else { - OCR &= ~regsWritten[offset]; - simulated[offset] = false; - } - } - - protected void simulateNoCalculate(int offset) { - if (simulated[offset]) { - if (regsRead[offset] == (regsRead[offset] & OCR)) { - OCR |= regsWritten[offset]; - } else { - OCR &= ~regsWritten[offset]; - simulated[offset] = false; - } - } else { - OCR &= ~regsWritten[offset]; - } - } - - protected void simulate(boolean calculateValues) { - if (calculateValues) { - for (int offset = bb.offset; offset < bb.offset + bb.size; offset++) { - // special case to figure out constant regs at a particular location - if (offset == getRegsOffset) { - for (int i = 0; i < 32; i++) regsAtOffset[i] = outgoingRegValues[i]; - CRAtOffset = OCR; - } - if (0 != (flags[offset] & CPUInstruction.FLAG_BRANCH)) { - // re-order so that - simulateCalculate(offset + 1); - simulateCalculate(offset); - offset++; - } else { - simulateCalculate(offset); - } - } - } else { - for (int offset = bb.offset; offset < bb.offset + bb.size; offset++) { - // special case to figure out constant regs at a particular location - if (offset == getRegsOffset) { - for (int i = 0; i < 32; i++) regsAtOffset[i] = outgoingRegValues[i]; - CRAtOffset = OCR; - } - if (0 != (flags[offset] & CPUInstruction.FLAG_BRANCH)) { - // re-order so that - simulateNoCalculate(offset + 1); - simulateNoCalculate(offset); - offset++; - } else { - simulateNoCalculate(offset); - } - } - } - } - } - - - protected void initBlockStructures(FlowAnalyzer.FlowInfo flowInfo) { - super.initBlockStructures(flowInfo); - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { - blockInfo[block.offset] = new BlockInfo(block); - } - } - if (debugCR) { - visitCount = 0; - } - assert (dirtyBlocks.isEmpty()); - blockInfo[0].updateIncoming(1, new int[32]); - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - codeWriter.println("..."); - } - while (!dirtyBlocks.isEmpty()) { - ((BlockInfo) dirtyBlocks.pop()).visit(); - } - if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { - if (debugCR) { - codeWriter.println("CR took " + visitCount + " iterations for " + flowInfo.blockCount + " blocks: " + (visitCount / (double) flowInfo.blockCount)); - for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { - if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { - BlockInfo info = blockInfo[block.offset]; - codeWriter.println("--- " + info); - for (int offset = block.offset; offset < block.offset + block.size; offset++) { - int address = flowInfo.base + offset * 4; - int ci = addressSpace.internalRead32(address); - String debug = simulated[offset] ? "* " : " "; - debug += MiscUtil.toHex(address, 8) + " " + r3000.disassemble(address, ci); - codeWriter.println(debug); - } - } - } - } - } - } - - protected void emitBlockHeader(InstructionList il) { - if (contextBlock.type == FlowAnalyzer.BasicBlock.NORMAL) { - BlockInfo blockInfo = this.blockInfo[contextBlock.offset]; - contextRegValues = blockInfo.incomingRegValues; - contextCR = blockInfo.ICR; - // ICR is initialized to zero, so code that is never reached needs to have r0 set - if (contextCR == 0 && !blockInfo.visited) { - contextCR = 1; - } - assert 1 == (contextCR & 1); - contextUnwrittenRegs = 0; - } - super.emitBlockHeader(il); - } - - protected void emitBlockFooter(InstructionList il) { - writeBackRegs(il, ALL_REGS); - super.emitBlockFooter(il); - } - - protected void emitContextInstructionGuts(InstructionList il) { - if (0 != (flags[contextOffset] & (CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE))) { - writeBackRegs(il, ALL_REGS); - } - // note this function would be pretty broken if branch instructions were simulatable! - if (simulated[contextOffset]) { - instructions[contextOffset].simulate(opCodes[contextOffset], contextRegValues); -/* if (printCode && shouldPrintCode()) { - InstructionHandle endHandle = il.getEnd(); - if (endHandle == null) { - endHandle = il.append( new NOP() ); - } - endHandles[contextOffset] = endHandle; - }*/ - contextUnwrittenRegs |= regsWritten[contextOffset]; - contextCR |= regsWritten[contextOffset]; - } else { - // todo fix this; we only need to write back regs which aren't constant (unless the instruction - // doesn't observe constant regs) - writeBackRegs(il, regsRead[contextOffset]); - if (contextUnwrittenRegs != 0) { - // record the fact that we have unwritten regs - addressSpace.orTag(contextAddress, MultiStageCompiler.TAG_UNWRITTEN_REGS); - } - instructions[contextOffset].compile(this, contextAddress, opCodes[contextOffset], il); - contextUnwrittenRegs &= ~regsWritten[contextOffset]; - assert 0 == (regsWritten[contextOffset] & 1); - contextCR &= ~regsWritten[contextOffset]; - } - // write back registers before call/branch - if (contextIsDelaySlot) { - writeBackRegs(il, ALL_REGS); - } - } - - protected void writeBackRegs(InstructionList il, int regs) { - int toWrite = contextUnwrittenRegs & regs; - if (toWrite != 0) { - for (int reg = 1; reg < 32; reg++) { - if (0 != (toWrite & (1 << reg))) { - il.append(new PUSH(contextCP, contextRegValues[reg])); - emitSetReg(il, reg); - } - } - contextUnwrittenRegs &= ~regs; - } - } - - protected int[] contextRegValues; - protected int contextCR; - protected int contextUnwrittenRegs; - - public int getRegValue(int reg) { - assert 0 != (contextCR & (1 << reg)); - return contextRegValues[reg]; - } - - public int getConstantRegs() { - assert (1 == (contextCR & 1)); - return contextCR; - } - - protected void disassemble(int index) { - int address = contextBase + (index << 2); - String prefix = ""; - if (simulated[index]) { - prefix = "X"; - } else { - prefix = " "; - } - // graham 12/23/14 commented this out as it makes no sense contextCR is not necessarily the constant registers for this instruction -// if (regsRead[index] == (contextCR & regsRead[index])) { -// prefix += "C"; -// } else { -// prefix += " "; -// } - if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_UNWRITTEN_REGS)) { - prefix += ">"; - } else { - prefix += " "; - } - if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_DELAY_SLOT)) { - prefix += "D"; - } else { - prefix += " "; - } - String prefix1 = ""; - String suffix = ""; - int ci = opCodes[index]; - String dis = r3000.disassemble(address, ci); - codeWriter.println(" " + prefix + " " + prefix1 + " " + MiscUtil.toHex(address, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis + suffix); - } - - public void emitCall(InstructionList il, int address, int retAddr) { - if (R3000Impl.Settings.traceExecutionFlow) { - il.append(new PUSH(contextCP, address)); - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceDirectCall", "(II)V"))); - } - - if (AddressSpace.Util.isBIOS(contextAddress) && !AddressSpace.Util.isBIOS(address)) { - // calling from bios to ram must be indirect... note this is probably rare. - System.out.println("Emitting bios to ram call"); - il.append(new PUSH(contextCP, address)); - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); - } else { - il.append(new PUSH(contextCP, retAddr)); - il.append(new PUSH(contextCP, 0)); - il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(Stage1Generator.CLASS_NAME_PREFIX, address), STATIC_METHOD, "(IZ)I"))); - il.append(new POP()); - } - } - - /** - * Used for JALR etc where the address to call is at the top - * of the JVM stack - */ - public void emitCall(InstructionList il, int retAddr) { - il.append(new PUSH(contextCP, retAddr)); - il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); - } - - public void emitReadMem8(InstructionList il, int address, boolean signed) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // we must do tag==0 since this means we haven't executed this statement yet - if (tag == 0 || 0 != (tag & AddressSpace.TAG_POLL)) { - il.append(new PUSH(contextCP, address)); - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll8", "(I)V"))); - } - rr.mem = null; - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); - return; - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); - } - if (signed) { - switch (address & 3) { - case 2: - il.append(new PUSH(contextCP, 8)); - il.append(new ISHL()); - break; - case 1: - il.append(new PUSH(contextCP, 16)); - il.append(new ISHL()); - break; - case 0: - il.append(new PUSH(contextCP, 24)); - il.append(new ISHL()); - break; - } - il.append(new PUSH(contextCP, 24)); - il.append(new ISHR()); - } else { - switch (address & 3) { - case 3: - il.append(new PUSH(contextCP, 24)); - il.append(new ISHR()); - break; - case 2: - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - break; - case 1: - il.append(new PUSH(contextCP, 8)); - il.append(new ISHR()); - break; - } - il.append(new PUSH(contextCP, 0xff)); - il.append(new IAND()); - } - } - - public void emitReadMem8(InstructionList il, int reg, int offset) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - if (0 == tag || 0 != (tag & AddressSpace.TAG_POLL)) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll8", "(I)V"))); - tag &= ~AddressSpace.TAG_POLL; - } - switch (tag) { - case AddressSpace.TAG_RAM: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Ram", "(I)I"))); - break; - case AddressSpace.TAG_SCRATCH: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Scratch", "(I)I"))); - break; - case AddressSpace.TAG_BIOS: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Bios", "(I)I"))); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); - } - } - - public void emitReadMem16(InstructionList il, int address, boolean signed) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // we must do tag==0 since this means we haven't executed this statement yet - if (tag == 0 || 0 != (tag & AddressSpace.TAG_POLL)) { - il.append(new PUSH(contextCP, address)); - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll16", "(I)V"))); - } - rr.mem = null; - if (0 == (address & 1)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); - return; - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - if (signed) { - if (0 == (address & 2)) { - il.append(new PUSH(contextCP, 16)); - il.append(new ISHL()); - } - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - } else { - if (0 != (address & 2)) { - il.append(new PUSH(contextCP, 16)); - il.append(new ISHR()); - } - il.append(new PUSH(contextCP, 0xffff)); - il.append(new IAND()); - } - } - - public void emitReadMem16(InstructionList il, int reg, int offset) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - if (0 == tag || 0 != (tag & AddressSpace.TAG_POLL)) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll16", "(I)V"))); - tag &= ~AddressSpace.TAG_POLL; - } - switch (tag) { - case AddressSpace.TAG_RAM: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Ram", "(I)I"))); - break; - case AddressSpace.TAG_SCRATCH: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Scratch", "(I)I"))); - break; - case AddressSpace.TAG_BIOS: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Bios", "(I)I"))); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); - } - } - - public void emitReadMem32(InstructionList il, int address, boolean forceAlign) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // we must do tag==0 since this means we haven't executed this statement yet - if (tag == 0) { - // this only calls _checkPoll32 sometimes - il.append(new PUSH(contextCP, contextAddress)); - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); - } else if (0 != (tag & AddressSpace.TAG_POLL)) { - il.append(new PUSH(contextCP, address)); - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll32", "(I)V"))); - } - rr.mem = null; - if (forceAlign) { - address &= ~3; - } - if (0 == (address & 3)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(new IALOAD()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read32", "(I)I"))); - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); - } - } - - public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - // we must do tag==0 since this means we haven't executed this statement yet - if (tag == 0) { - il.append(new PUSH(contextCP, contextAddress)); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - // this only calls _checkPoll32 sometimes - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); - } else if (0 != (tag & AddressSpace.TAG_POLL)) { - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll32", "(I)V"))); - tag &= ~AddressSpace.TAG_POLL; - } - switch (tag) { - case AddressSpace.TAG_RAM: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.RAM_AND)); - il.append(new IAND()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(new IALOAD()); - break; - case AddressSpace.TAG_SCRATCH: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.SCRATCH_XOR)); - il.append(new IXOR()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(new IALOAD()); - break; - case AddressSpace.TAG_BIOS: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.BIOS_XOR)); - il.append(new IXOR()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(new IALOAD()); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read32", "(I)I"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); - } - } - - public void emitWriteMem8(InstructionList il, int address, InstructionList il2) { - InstructionList il3 = new InstructionList(); - emitReadMem32(il3, address, true); - switch (address & 3) { - case 0: - il3.append(new PUSH(contextCP, 0xffffff00)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new IOR()); - break; - case 1: - il3.append(new PUSH(contextCP, 0xffff00ff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new PUSH(contextCP, 8)); - il3.append(new ISHL()); - il3.append(new IOR()); - break; - case 2: - il3.append(new PUSH(contextCP, 0xff00ffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 0xff)); - il3.append(new IAND()); - il3.append(new PUSH(contextCP, 16)); - il3.append(new ISHL()); - il3.append(new IOR()); - break; - default: - il3.append(new PUSH(contextCP, 0xffffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 24)); - il3.append(new ISHL()); - il3.append(new IOR()); - } - emitWriteMem32(il, address, il3, true); - il3.dispose(); - } - - public void emitWriteMem8(InstructionList il, int reg, int offset) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - switch (tag) { - case AddressSpace.TAG_RAM: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Ram", "(II)V"))); - break; - case AddressSpace.TAG_SCRATCH: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Scratch", "(II)V"))); - break; - case AddressSpace.TAG_BIOS: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Bios", "(II)V"))); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write8", "(II)V"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8", "(II)V"))); - } - } - - public void emitWriteMem16(InstructionList il, int address, InstructionList il2) { - if ((address & 1) != 0) { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); - } else { - InstructionList il3 = new InstructionList(); - // il3.stack(0) = oldvalue - emitReadMem32(il3, address, true); - switch (address & 3) { - case 0: - // il3.stack(1) = mask; - il3.append(new PUSH(contextCP, 0xffff0000)); - il3.append(new IAND()); - // il3.stack(0) = maskedOldValue; - il3.append(il2); - // il3.stack(1) = newvalue; - il3.append(new PUSH(contextCP, 0xffff)); - // il3.stack(2) = mask; - il3.append(new IAND()); - // il3.stack(1) = maskedNewValue; - il3.append(new IOR()); - // il3.stack(0) = newMemValue - break; - default: - il3.append(new PUSH(contextCP, 0xffff)); - il3.append(new IAND()); - il3.append(il2); - il3.append(new PUSH(contextCP, 16)); - il3.append(new ISHL()); - il3.append(new IOR()); - } - emitWriteMem32(il, address, il3, true); - il3.dispose(); - } - } - - public void emitWriteMem16(InstructionList il, int reg, int offset) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - switch (tag) { - case AddressSpace.TAG_RAM: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Ram", "(II)V"))); - break; - case AddressSpace.TAG_SCRATCH: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Scratch", "(II)V"))); - break; - case AddressSpace.TAG_BIOS: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Bios", "(II)V"))); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write16", "(II)V"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new SWAP()); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); - } - } - - public void emitWriteMem32(InstructionList il, int address, InstructionList il2, boolean forceAlign) { - rr.mem = null; - if (forceAlign) { - address &= ~3; - } - if (0 == (address & 3)) { - addressSpace.resolve(address, rr); - if (rr.tag == AddressSpace.TAG_RAM) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(il2); - il.append(new IASTORE()); - } else if (rr.tag == AddressSpace.TAG_SCRATCH) { - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(il2); - il.append(new IASTORE()); - } else if (rr.tag == AddressSpace.TAG_BIOS) { - // just read the address to make sure TAG is correct - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - il.append(new PUSH(contextCP, rr.offset)); - il.append(il2); - il.append(new IALOAD()); - il.append(new POP()); - } else if (rr.tag == AddressSpace.TAG_HW) { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); - } else { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - } else { - il.append(new PUSH(contextCP, address)); - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - } - - public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList il2, boolean forceAlign) { - int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; - // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that - if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { - tag = AddressSpace.TAG_RAM; - } - switch (tag) { - case AddressSpace.TAG_RAM: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.RAM_AND)); - il.append(new IAND()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(il2); - il.append(new IASTORE()); - break; - case AddressSpace.TAG_SCRATCH: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.SCRATCH_XOR)); - il.append(new IXOR()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(il2); - il.append(new IASTORE()); - break; - case AddressSpace.TAG_BIOS: - il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - il.append(new PUSH(contextCP, AddressSpace.BIOS_XOR)); - il.append(new IXOR()); - il.append(new PUSH(contextCP, 2)); - il.append(new ISHR()); - il.append(il2); - // just read to check TAG_ is correct - il.append(new IALOAD()); - il.append(new POP()); - break; - case AddressSpace.TAG_HW: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); - break; - default: - emitGetReg(il, reg); - if (offset != 0) { - il.append(new PUSH(contextCP, offset)); - il.append(new IADD()); - } - if (forceAlign) { - il.append(new PUSH(contextCP, 0xfffffffc)); - il.append(new IAND()); - } - il.append(il2); - il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); - } - } - - protected boolean shouldPrintCode() { - return true; - } - - public void fixupUnwrittenRegs(CodeUnit unit, int pc) { - // todo we could keep the info we needed here about in soft reference I guess; even so we need this code - assert r3000.isExecutionThread(); - assert intendedForExecutionThread; - FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(analyzer, true); - getRegsOffset = (pc - unit.base) >> 2; - initBlockStructures(flowInfo); - if (0 != (CRAtOffset & 0x00000002)) { - MultiStageCompiler.reg_1 = regsAtOffset[1]; - } - if (0 != (CRAtOffset & 0x00000004)) { - MultiStageCompiler.reg_2 = regsAtOffset[2]; - } - if (0 != (CRAtOffset & 0x00000008)) { - MultiStageCompiler.reg_3 = regsAtOffset[3]; - } - if (0 != (CRAtOffset & 0x00000010)) { - MultiStageCompiler.reg_4 = regsAtOffset[4]; - } - if (0 != (CRAtOffset & 0x00000020)) { - MultiStageCompiler.reg_5 = regsAtOffset[5]; - } - if (0 != (CRAtOffset & 0x00000040)) { - MultiStageCompiler.reg_6 = regsAtOffset[6]; - } - if (0 != (CRAtOffset & 0x00000080)) { - MultiStageCompiler.reg_7 = regsAtOffset[7]; - } - if (0 != (CRAtOffset & 0x00000100)) { - MultiStageCompiler.reg_8 = regsAtOffset[8]; - } - if (0 != (CRAtOffset & 0x00000200)) { - MultiStageCompiler.reg_9 = regsAtOffset[9]; - } - if (0 != (CRAtOffset & 0x00000400)) { - MultiStageCompiler.reg_10 = regsAtOffset[10]; - } - if (0 != (CRAtOffset & 0x00000800)) { - MultiStageCompiler.reg_11 = regsAtOffset[11]; - } - if (0 != (CRAtOffset & 0x00001000)) { - MultiStageCompiler.reg_12 = regsAtOffset[12]; - } - if (0 != (CRAtOffset & 0x00002000)) { - MultiStageCompiler.reg_12 = regsAtOffset[13]; - } - if (0 != (CRAtOffset & 0x00004000)) { - MultiStageCompiler.reg_14 = regsAtOffset[14]; - } - if (0 != (CRAtOffset & 0x00008000)) { - MultiStageCompiler.reg_15 = regsAtOffset[15]; - } - if (0 != (CRAtOffset & 0x00010000)) { - MultiStageCompiler.reg_16 = regsAtOffset[16]; - } - if (0 != (CRAtOffset & 0x00020000)) { - MultiStageCompiler.reg_17 = regsAtOffset[17]; - } - if (0 != (CRAtOffset & 0x00040000)) { - MultiStageCompiler.reg_18 = regsAtOffset[18]; - } - if (0 != (CRAtOffset & 0x00080000)) { - MultiStageCompiler.reg_19 = regsAtOffset[19]; - } - if (0 != (CRAtOffset & 0x00100000)) { - MultiStageCompiler.reg_20 = regsAtOffset[20]; - } - if (0 != (CRAtOffset & 0x00200000)) { - MultiStageCompiler.reg_21 = regsAtOffset[21]; - } - if (0 != (CRAtOffset & 0x00400000)) { - MultiStageCompiler.reg_22 = regsAtOffset[22]; - } - if (0 != (CRAtOffset & 0x00800000)) { - MultiStageCompiler.reg_23 = regsAtOffset[23]; - } - if (0 != (CRAtOffset & 0x01000000)) { - MultiStageCompiler.reg_24 = regsAtOffset[24]; - } - if (0 != (CRAtOffset & 0x02000000)) { - MultiStageCompiler.reg_25 = regsAtOffset[25]; - } - if (0 != (CRAtOffset & 0x04000000)) { - MultiStageCompiler.reg_26 = regsAtOffset[26]; - } - if (0 != (CRAtOffset & 0x08000000)) { - MultiStageCompiler.reg_27 = regsAtOffset[27]; - } - if (0 != (CRAtOffset & 0x10000000)) { - MultiStageCompiler.reg_28 = regsAtOffset[28]; - } - if (0 != (CRAtOffset & 0x20000000)) { - MultiStageCompiler.reg_29 = regsAtOffset[29]; - } - if (0 != (CRAtOffset & 0x40000000)) { - MultiStageCompiler.reg_30 = regsAtOffset[30]; - } - if (0 != (CRAtOffset & 0x80000000)) { - MultiStageCompiler.reg_31 = regsAtOffset[31]; - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java b/src/runtime/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java deleted file mode 100644 index df09aa4..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware; - -import org.jpsx.api.components.hardware.cd.CDAudioSink; -import org.jpsx.api.components.hardware.cd.CDDrive; -import org.jpsx.api.components.hardware.gpu.Display; -import org.jpsx.api.components.hardware.gpu.DisplayManager; -import org.jpsx.api.components.hardware.sio.SerialPort; -import org.jpsx.bootstrap.connection.SimpleConnection; - -/** - * Stock connections used by the base JPSX hardware implementations - */ -public class HardwareComponentConnections { - public static final SimpleConnection CD_DRIVE = SimpleConnection.create("CD Drive", CDDrive.class); - public static final SimpleConnection CD_AUDIO_SINK = SimpleConnection.create("CD Audio Sink", CDAudioSink.class); - public static final SimpleConnection LEFT_PORT_INSTANCE = SimpleConnection.create("Left Serial Port", SerialPort.class); - public static final SimpleConnection RIGHT_PORT_INSTANCE = SimpleConnection.create("Right Serial Port", SerialPort.class); - public static final SimpleConnection DISPLAY = SimpleConnection.create("JPSX GPU Display", Display.class); - public static final SimpleConnection DISPLAY_MANAGER = SimpleConnection.create("JPXS GPU Display Manager", DisplayManager.class); -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java b/src/runtime/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java deleted file mode 100644 index 887b2b1..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.bios; - -import org.jpsx.api.InvalidConfigurationException; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.IntBuffer; -import java.nio.channels.FileChannel; - -/** - * ImageBIOS is a simple component which maps - * a file base image of an R3000 BIOS into - * the PSX address base. This file can be - * a real PSX BIOS image, though it need not be - */ -public class ImageBIOS extends JPSXComponent { - private static final int ADDRESS = 0xbfc00000; - // todo get size from file! - private static final int SIZE = 0x80000; - - public ImageBIOS() { - super("JPSX BIOS using ROM image"); - } - - public void init() { - super.init(); - CoreComponentConnections.ALL_POPULATORS.add(new Runnable() { - public void run() { - populateMemory(); - } - }); - } - - private void populateMemory() { - String filename = "bios.bin"; - //MiscUtil.consoleOut( "Loading bios " + filename + "..." ); - try { - RandomAccessFile in = new RandomAccessFile(filename, "r"); - AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); - AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - addressSpace.resolve(ADDRESS, SIZE, true, rr); - - FileChannel channel = in.getChannel(); - ByteBuffer bytebuf = ByteBuffer.allocateDirect(SIZE); - bytebuf.order(ByteOrder.LITTLE_ENDIAN); - IntBuffer intbuf = bytebuf.asIntBuffer(); - bytebuf.clear(); - - if (SIZE != channel.read(bytebuf, 0)) { - throw new InvalidConfigurationException("BIOS image " + filename + " is not the correct size"); - } - intbuf.rewind(); - intbuf.get(rr.mem); - channel.close(); - } catch (IOException e) { - throw new InvalidConfigurationException("Can't load BIOS image " + filename, e); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/cd/CD.java b/src/runtime/java/org/jpsx/runtime/components/hardware/cd/CD.java deleted file mode 100644 index 6f4f664..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/cd/CD.java +++ /dev/null @@ -1,1676 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.cd; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.cpu.SCP; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.ScheduledAction; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.api.components.hardware.cd.CDAudioSink; -import org.jpsx.api.components.hardware.cd.CDDrive; -import org.jpsx.api.components.hardware.cd.CDMedia; -import org.jpsx.api.components.hardware.cd.MediaException; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.DMAChannelOwnerBase; -import org.jpsx.runtime.components.core.IRQOwnerBase; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.CDUtil; -import org.jpsx.runtime.util.MiscUtil; - -// todo return the correct thing for audio/no disc -// todo filter! -// todo end of file! - -// todo no need for static - - -// note we are two times over-clocked; we just slow stuff down if streaming XA audio -/** - * New cd plan as follows: - *

- * All CD action is timing based; i.e. when spinning we update head position on interrupt. - * Data is read into buffers, Audio is passed straight along at the correct speed. - *

- * AudioSink should bufer after a reset. - *

- * it is up to native back end to read in bursts - */ -public class CD extends JPSXComponent implements MemoryMapped { - private static boolean rateLimit1 = false; - private static boolean rateLimit2 = true; - - private static final Logger log = Logger.getLogger("CD"); - /** - * Logs information on CD commands set by the PSX - */ - private static final Logger cmdLog = Logger.getLogger("CD.CMD"); - private static final boolean cmdLogDebug = cmdLog.isDebugEnabled(); - - /** - * The CD drive implementation - */ - private static CDDrive drive; - /** - * The current CD media, or null - */ - private static CDMedia media; - - private static XADecoder xaDecoder = new XADecoder(); - private static CDAudioSink cdAudioSink; - private static int cdFreq = 0; - - private static long rateLimitStartTime; - private static boolean rateLimitEnabled; - - // ratelimit1 stuff - // number of audio bytes we've fed - private static int actualAudioBytes; - - // ratelimit2 stuff - private static int actualSectors; - - private static final boolean traceCD = log.isTraceEnabled(); - private static final boolean softwareCDDA = true; - // Hardware addresses - public static final int ADDR_CD_REG0 = 0x1f801800; - public static final int ADDR_CD_REG1 = 0x1f801801; - public static final int ADDR_CD_REG2 = 0x1f801802; - public static final int ADDR_CD_REG3 = 0x1f801803; - - // 0, 1, 2, 3 as set by low 3 bits of reg0 - private static int regMode; - - // cdMode of the CD as set by CdlSetMode - private static int cdMode = 0; - - private static int filterFile = 0; - private static int filterChannel = 0; - - private static final int STATE_NONE = 0; - private static final int STATE_STANDBY = 1; - private static final int STATE_READN = 2; - private static final int STATE_READS = 3; - private static final int STATE_PLAY = 4; - private static final int STATE_SEEKL = 5; - private static final int STATE_SEEKP = 6; - private static final int STATE_PAUSE = 7; - private static final int STATE_STOP = 8; - - private static int substate; - private static int state; - - private static boolean interruptEnabled; - private static boolean seeking; - private static boolean sectorReady; - private static boolean sectorDismissed; - private static boolean someDataRead; - private static boolean waitForDataRead; - private static int waitForDataReadCounter; - - private static boolean resultCleared; - - private static int[] currentSector = new int[2352 / 4]; - private static int currentSectorOffset; - private static int currentSectorEnd; - - // reg0 status bits - private static final int REG0_UNKNOWN_READY3 = 0x08; - private static final int REG0_UNKNOWN_READY4 = 0x10; - private static final int REG0_RESULTS_READY = 0x20; - private static final int REG0_DATA_READY = 0x40; -// private static final int REG0_CMDINPROGRESS = 0x80; - - // reg3 status bits - - // not sure about error bits; sometime 0x1c is used as an error mask, sometimes 0x1d - private static final int REG3_CDDA_PLAYING = 0x80; - private static final int REG3_SEEKING = 0x40; - private static final int REG3_READING_DATA = 0x20; - private static final int REG3_SHELL_OPEN = 0x10; - private static final int REG3_SEEK_ERROR = 0x04; - private static final int REG3_STANDBY = 0x02; // spinning - private static final int REG3_ERROR = 0x01; - - // cdMode values - private static final int CD_MODE_DOUBLE_SPEED = 0x80; - // playing XA data - private static final int CD_MODE_XA = 0x40; - - private static final int CD_MODE_SIZE_MASK = 0x30; - private static final int CD_MODE_SIZE_2048 = 0x00; - private static final int CD_MODE_SIZE_2340 = 0x20; - //private static final int CD_MODE_SIZE_2328 = 0x10; - - private static final int CD_MODE_FILTER = 0x08; - // i guess this is supposed to send data while playing - private static final int CD_MODE_REPORT = 0x04; - // should pause at the end of a track - private static final int CD_MODE_AUTO_PAUSE = 0x02; - // playing DA data? - private static final int CD_MODE_DA = 0x01; - - // -------------------------------------------------------------------- - - private static IRQ irq; - private static AddressSpace addressSpace; - private static SCP scp; - private static Quartz quartz; - private static Scheduler scheduler; - - private static class IRQ extends IRQOwnerBase { - private boolean set; - - private boolean inIRQCleared; - private boolean inRaiseIRQ; - - private boolean pendingIRQ; - - public IRQ() { - super(IRQController.IRQ_CD, "CD"); - } - - public boolean isSet() { - return set; - } - - // not synched, because irq already synchronized - public void irqSet() { - assert !set; - if (false || traceCD) log.trace("Set CD interrupt"); - set = true; - } - - public void irqCleared() { - assert set; - if (false || traceCD) log.trace("Clear CD interrupt"); - set = false; - try { - synchronized (this) { - assert !inIRQCleared; - inIRQCleared = true; - // if we're in raise IRQ, then the irq is getting set anyway, - // so no point in checking for another one. - if (inRaiseIRQ) - return; - } - checkForIRQ(); - } finally { - synchronized (this) { - assert inIRQCleared; - inIRQCleared = false; - if (pendingIRQ) { - pendingIRQ = false; - if (!set) { - super.raiseIRQ(); - } - } - } - } - } - - public void raiseIRQ() { - // work around deadlock possibility: - // thread1: owns CD lock, and tries to signal CD interrupt (needs IRQ lock) - // thread2: clearing CD intterrupt (owns IRQ lock), waiting on CD lock - // - // to do this, we simply ask the irq clearing thread to signal the interrupt when it is done. - try { - synchronized (this) { - assert !inRaiseIRQ; - inRaiseIRQ = true; - // if we're in irqCleared(), then just - // get it to set the irq for us. - if (inIRQCleared) { - pendingIRQ = true; - return; - } - } - super.raiseIRQ(); - } finally { - synchronized (this) { - assert inRaiseIRQ; - inRaiseIRQ = false; - } - } - } - } - - // -------------------------------------------------------------------- - - public CD() { - super("JPSX CD Controller"); - } - - public void init() { - super.init(); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - irq = new IRQ(); - CoreComponentConnections.IRQ_OWNERS.add(irq); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new CDDMAChannel()); - } - - public void resolveConnections() { - drive = HardwareComponentConnections.CD_DRIVE.resolve(); - media = drive.getCurrentMedia(); - cdAudioSink = HardwareComponentConnections.CD_AUDIO_SINK.peek(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - scp = CoreComponentConnections.SCP.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - scheduler = CoreComponentConnections.SCHEDULER.resolve(); - } - - private static String getModeDescription(int mode) { - return "..."; - } - - private static synchronized void setCdMode(int newMode) { - if (traceCD && newMode != cdMode) { - log.trace("CD MODE: " + getModeDescription(cdMode)); - } - if (false && 0 != (newMode & CD_MODE_AUTO_PAUSE)) { - System.out.println("AutoPause"); - } - if (false && 0 != (newMode & CD_MODE_REPORT)) { - System.out.println("Report"); - } - cdMode = newMode; - } - - private static class CmdParameters { - private static final int MAX_PARAMS = 8; - private static final int params[] = new int[MAX_PARAMS]; - private static int count = 0; - - public void reset() { - count = 0; - } - - public void add(int b) { - if (traceCD) log.trace("CD: param " + count + " = " + MiscUtil.toHex(b, 2)); - params[count++] = b; - } - - public int get(int index) { - if (index < 0 || index > count) { - log.error("out of bounds in CD"); - throw new ArrayIndexOutOfBoundsException(index); - } - return params[index]; - } - } - - ; - - private static CmdParameters params = new CmdParameters(); - - private static class CmdResult { - private static final int MAX_RESULTS = 8; - - public static final int DATAREADY = 1; - public static final int COMPLETE = 2; - public static final int ACKNOWLEDGE = 3; - public static final int DATAEND = 4; - public static final int DISKERROR = 5; - - public int type; - public int[] results = new int[MAX_RESULTS]; - public int resultCount; - public int resultPos; - - public void add(int b) { - results[resultCount++] = b; - } - - public boolean remaining() { - return resultPos != resultCount; - } - - public int read() { - if (resultPos < resultCount) { - return results[resultPos++]; - } else { - throw new IllegalStateException("CD: read more results than available!"); - } - } - - public String toString() { - StringBuilder rc = new StringBuilder(); - for (int i = 0; i < resultCount; i++) { - rc.append(' '); - rc.append(MiscUtil.toHex(results[i], 2)); - } - return rc.toString(); - } - } - - private static CmdResult nullResult = new CmdResult(); - /** - * current result - */ - private static CmdResult currentResult = nullResult; - - // protected by CD.class monitor - private static CmdResult[] resultQueue = new CmdResult[16]; - // read==write implies empty; - private static int resultQueueNextRead = 0; - private static int resultQueueNextWrite = 0; - - private static class HeadLocation { - private int m, s, f; - - public HeadLocation() { - init(0); - } - - public void init(HeadLocation h) { - m = h.m; - s = h.s; - f = h.f; - } - - public void init(int m, int s, int f) { - this.m = m; - this.s = s; - this.f = f; - } - - public void init(int sec) { - sec += 150; - f = sec % 75; - sec /= 75; - s = sec % 60; - m = sec / 60; - } - - public int getM() { - return m; - } - - public int getS() { - return s; - } - - public int getF() { - return f; - } - - public int getSector() { - return CDUtil.toSector(m, s, f); - } - - /** - * simulate spinning of the CD in place - */ - public void nextSpin() { - f++; - if (f == 75) - f = 0; - } - - public void nextSequential() { - f++; - if (f == 75) { - f = 0; - s++; - if (s == 60) { - s = 0; - m++; - } - } - } - - public String toString() { - return MiscUtil.toHex(CDUtil.toBCD(m), 2) + "," + MiscUtil.toHex(CDUtil.toBCD(s), 2) + "," + MiscUtil.toHex(CDUtil.toBCD(f), 2); - } - } - - private static SectorThread sectorThread; - - private static HeadLocation lastSetLocation = new HeadLocation(); - private static boolean setLocDone; - private static HeadLocation currentLocation = new HeadLocation(); - - // commands - private static final int CdlNop = 1; - private static final int CdlSetLoc = 2; - private static final int CdlPlay = 3; - private static final int CdlFastForward = 4; - private static final int CdlRewind = 5; - private static final int CdlReadN = 6; - private static final int CdlStandby = 7; - private static final int CdlStop = 8; - private static final int CdlPause = 9; - private static final int CdlReset = 10; - private static final int CdlMute = 11; - private static final int CdlDemute = 12; - private static final int CdlSetFilter = 13; - private static final int CdlSetMode = 14; - private static final int CdlGetLocL = 16; - private static final int CdlGetLocP = 17; - private static final int CdlGetTN = 19; - private static final int CdlGetTD = 20; - private static final int CdlSeekL = 21; - private static final int CdlSeekP = 22; - private static final int CdlTest = 25; - private static final int CdlCheckID = 26; - private static final int CdlReadS = 27; - private static final int CdlHardReset = 28; - private static final int CdlReadTOC = 30; - - private static class CDDMAChannel extends DMAChannelOwnerBase { - public final int getDMAChannel() { - return DMAController.DMA_CD; - } - - static boolean first = true; - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if (false || traceCD) - log.trace("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - if (blocks == 0) blocks = 1; // ?? - int size = blocks * blockSize; - if (false || traceCD) - log.trace("size = " + (size * 4) + " remaining = " + (currentSectorEnd - currentSectorOffset)); - AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); - addressSpace.resolve(base, size * 4, true, rr); - if (0 != (base & 3) || 0 != (currentSectorOffset & 3)) { - throw new IllegalStateException("doh unaligned dma!"); - } - if (currentSectorOffset + (size * 4) > currentSectorEnd) { - throw new IllegalStateException("read off end of dma sector buffer"); - } - - int off = currentSectorOffset >> 2; - if (false && size == 8) { - log.trace(MiscUtil.toHex(currentSector[off], 8) + " " + - MiscUtil.toHex(currentSector[off + 1], 8) + " " + - MiscUtil.toHex(currentSector[off + 2], 8) + " " + - MiscUtil.toHex(currentSector[off + 3], 8) + " " + - MiscUtil.toHex(currentSector[off + 4], 8) + " " + - MiscUtil.toHex(currentSector[off + 5], 8) + " " + - MiscUtil.toHex(currentSector[off + 6], 8) + " " + - MiscUtil.toHex(currentSector[off + 7], 8)); - } - for (int i = 0; i < size; i++) { - rr.mem[rr.offset + i] = currentSector[off + i]; - } - currentSectorOffset += size << 2; - signalTransferComplete(); - setSomeDataRead(); - } - - public final String getName() { - return "CD"; - } - } - - public void registerAddresses(AddressSpaceRegistrar registration) { - registration.registerWrite8Callback(ADDR_CD_REG0, CD.class, "cdReg0Write"); - registration.registerWrite8Callback(ADDR_CD_REG1, CD.class, "cdReg1Write"); - registration.registerWrite8Callback(ADDR_CD_REG2, CD.class, "cdReg2Write"); - registration.registerWrite8Callback(ADDR_CD_REG3, CD.class, "cdReg3Write"); - registration.registerRead8Callback(ADDR_CD_REG0, CD.class, "cdReg0Read"); - registration.registerRead8Callback(ADDR_CD_REG1, CD.class, "cdReg1Read"); - registration.registerRead8Callback(ADDR_CD_REG2, CD.class, "cdReg2Read"); - registration.registerRead8Callback(ADDR_CD_REG3, CD.class, "cdReg3Read"); - } - - public void begin() { - sectorThread = new SectorThread(); - } - - // h/w access ----------------------------------------------------------------------------------- - - public static void cdReg0Write(int address, int value) { - if (traceCD) log.trace("CD_REG0_WRITE " + MiscUtil.toHex(value, 2)); - - regMode = (value & 3); - - //if (regMode==0) { - // if (traceCD) log.info("cdMode set to 0; reseting result ptr"); - // // reset the results pointer - // cdCurrentResultPos = 0; - //} - - if (0 != (value & 0xfc)) { - throw new IllegalStateException("CD: unknown reg0 write " + MiscUtil.toHex(value, 2)); - } - } - - public static int cdReg0Read(int address) { - - int rc = regMode; - - if (currentResult.remaining()) { - rc |= REG0_RESULTS_READY; - } - - if (currentSectorOffset != currentSectorEnd) { - rc |= REG0_DATA_READY; - } - - // todo, check this - rc |= REG0_UNKNOWN_READY3; // shell barfs early without this - rc |= REG0_UNKNOWN_READY4; // bios cannot read sector without this... - - if (traceCD) log.trace("CD_REG0_READ " + MiscUtil.toHex(rc, 2)); - return rc; - } - - public static void cdReg1Write(int address, int value) { - if (traceCD) log.trace("CD_REG1_WRITE " + MiscUtil.toHex(value, 2)); - - switch (regMode) { - case 0: - startCmd(value); - break; - case 3: - log.trace("CD set right volume " + MiscUtil.toHex(value, 2)); - if (cdAudioSink != null) { - cdAudioSink.setExternalCDAudioVolumeRight(value << 8); - } - break; - default: - throw new IllegalStateException("CD: unknown reg1 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); - } - } - - public static int cdReg1Read(int address) { - int rc = 0; - - switch (regMode) { - case 1: - rc = currentResult.read(); - break; - default: - throw new IllegalStateException("CD: unknown reg1 read: cdMode " + regMode); - } - if (traceCD) log.trace("CD_REG1_READ " + MiscUtil.toHex(rc, 2)); - return rc; - } - - public static void cdReg2Write(int address, int value) { - if (traceCD) log.trace("CD_REG2_WRITE " + MiscUtil.toHex(value, 2)); - - switch (regMode) { - case 0: - // writing command parameter - params.add(value); - break; - case 1: - // i think now that low bits are for IRQ (i.e. I know that 0x1f and 0x18 enable/disable - // interrupts, however I think the 0x18 do other stuff.. used mainly by bios/shell - // which are keen on 0x18 in all kinds of things :-) - if (0 == (value & 7)) { - if (traceCD) log.trace("CD: disabling interrupts"); - interruptEnabled = false; - } else if (7 == (value & 7)) { - if (traceCD) log.trace("CD: enabling interrupts"); - interruptEnabled = true; - } else { - throw new IllegalStateException("CD: unknown reg2 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); - } - - if (0 == (value & 0xf8)) { - } else if (0x18 == (value & 0xf8)) { - } else { - throw new IllegalStateException("CD: unknown reg2 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); - } - break; - case 2: - log.trace("CD set left volume " + MiscUtil.toHex(value, 2)); - if (cdAudioSink != null) { - cdAudioSink.setExternalCDAudioVolumeLeft(value << 8); - } - break; - default: - log.trace("CD ?set left volume low bits" + MiscUtil.toHex(value, 2)); - break; - } - } - - public static int cdReg2Read(int address) { - if (currentSectorOffset < currentSectorEnd) { - int val = currentSector[currentSectorOffset >> 2]; - switch (currentSectorOffset & 3) { - case 0: - val = val & 0xff; - break; - case 1: - val = (val >> 8) & 0xff; - break; - case 2: - val = (val >> 16) & 0xff; - break; - default: - val = (val >> 24) & 0xff; - break; - } - if (false || traceCD) log.trace("Read sector byte " + MiscUtil.toHex(val, 8)); - currentSectorOffset++; - setSomeDataRead(); - return val; - } else { - throw new IllegalStateException("read off end of sector buffer via reg2"); - } - } - - public static void cdReg3Write(int address, int value) { - if (traceCD) log.trace("CD_REG3_WRITE " + MiscUtil.toHex(value, 2)); - - switch (regMode) { - case 0: - if (value == 0x00) { - if (false || traceCD) { - log.trace("CD: dismiss sector"); - } - dismissSector(); - } else if (false || value == 0x80) { - if (false || traceCD) { - log.trace("CD: prepare sector results"); - } - prepareSector(); - } else { - throw new IllegalStateException("CD: unknown reg3 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); - } - break; - case 1: - if (7 == (value & 7)) { - if (traceCD) log.trace("CD: dismiss result"); - clearResult(); - } - if (0 != (value & 0x40)) { - // not sure what this does... - if (traceCD) log.trace("CD: 0140"); - } - if (0 != (value & 0xb8) && 0x18 != (value & 0xb8)) { - throw new IllegalStateException("CD: unknown reg3 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); - } - break; - case 2: - log.trace("CD ?set right volume low bits" + MiscUtil.toHex(value, 2)); - break; - default: - log.trace("CD ?commit volume"); - break; - } - } - - public static int cdReg3Read(int address) { - int rc = 0; - switch (regMode) { - case 0: - // todo figure out what this is - break; - case 1: - // to work around timing issues, we only make the result current when this register - // is read... - nextResult(); - rc = currentResult.type; - break; - default: - throw new IllegalStateException("CD: unknown reg3 read: cdMode " + regMode); - } - if (traceCD) log.trace("CD_REG3_READ " + MiscUtil.toHex(rc, 2)); - return rc; - } - - private static synchronized boolean resultQueueIsEmpty() { - return resultQueueNextWrite == resultQueueNextRead; - } - - private static synchronized void queueResult(CmdResult result) { - int write = resultQueueNextWrite; - - if (traceCD) log.trace("CD: queuing result " + result); - resultQueueNextWrite = (resultQueueNextWrite + 1) % resultQueue.length; - if (resultQueueNextWrite == resultQueueNextRead) { - throw new IllegalStateException("result queue full"); - } - - resultQueue[write] = result; - checkForIRQ(); - } - - private static synchronized void checkForIRQ() { - if (interruptEnabled && resultQueueNextRead != resultQueueNextWrite) { - if (false || traceCD) log.trace("CD: a result available; raising IRQ"); - irq.raiseIRQ(); - if (false || traceCD) log.trace("CD: done raising IRQ"); - } - } - - private static synchronized void clearResult() { - if (false || traceCD) log.trace("CD: clear result"); - resultCleared = true; - checkForIRQ(); - } - - private static synchronized void nextResult() { - if (!resultCleared) { - if (false || traceCD) log.trace("CD: nextResult: previous not reset, so not shifting"); - return; - } - if (resultQueueNextRead == resultQueueNextWrite) { - if (false || traceCD) log.trace("CD: nextResult: none"); - currentResult = nullResult; - resultCleared = true; - } else { - if (currentResult.type == CmdResult.DATAREADY && resultQueue[resultQueueNextRead].type == CmdResult.DATAREADY && irq.isSet()) { - if (false || traceCD) log.trace("CD: deferring sequential dataready with irq set"); - currentResult = nullResult; - resultCleared = true; - } else { - currentResult = resultQueue[resultQueueNextRead]; - resultQueue[resultQueueNextRead] = null; - resultQueueNextRead = (resultQueueNextRead + 1) % resultQueue.length; - resultCleared = false; - if (currentResult.type == CmdResult.DATAREADY) { - sectorReady = true; - } - if (false || traceCD) log.trace("CD: nextResult: " + currentResult); - } - } - } - - private static synchronized void clearResults() { - resultQueueNextRead = resultQueueNextWrite; - currentResult = nullResult; - } - - private static CmdResult newAckStatusResult() { - CmdResult res = new CmdResult(); - res.type = CmdResult.ACKNOWLEDGE; - res.add(getStatus()); - return res; - } - - private static CmdResult newDataReadyStatusResult() { - CmdResult res = new CmdResult(); - res.type = CmdResult.DATAREADY; - res.add(getStatus()); - return res; - } - - private static CmdResult newCompleteStatusResult() { - CmdResult res = new CmdResult(); - res.type = CmdResult.COMPLETE; - res.add(getStatus()); - return res; - } - - // this function called from r3000 thread; - private static void startCmd(int cmd) { - CmdResult res; - - switch (cmd) { - case CdlNop: - if (cmdLogDebug) cmdLog.debug("CdlNop"); - queueResult(newAckStatusResult()); - break; - - case CdlReset: - if (cmdLogDebug) cmdLog.debug("CdlReset"); - clearResults(); - // standby will abort any read etc. - setState(STATE_STANDBY); - setCdMode(0); - - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - - case CdlSetLoc: - // todo, check what to do if we're reading.. - lastSetLocation.init(CDUtil.fromBCD(params.get(0)), CDUtil.fromBCD(params.get(1)), CDUtil.fromBCD(params.get(2))); - setLocDone = true; - if (cmdLogDebug) cmdLog.debug("CdlSetLoc " + lastSetLocation); - queueResult(newAckStatusResult()); - break; - - case CdlTest: - switch (params.get(0)) { - case 0x20: - if (cmdLogDebug) cmdLog.debug("CdlTest: getVersion"); - res = new CmdResult(); - res.type = CmdResult.ACKNOWLEDGE; - res.add(0x98); - res.add(0x06); - res.add(0x10); - res.add(0xc3); - queueResult(res); - break; - default: - throw new IllegalStateException("Unknown CdlTest command 0x" + MiscUtil.toHex(params.get(0), 2)); - } - break; - - case CdlReadN: - if (cmdLogDebug) cmdLog.debug("CdlReadN"); - resetAudio(); - setState(STATE_READN); - queueResult(newAckStatusResult()); - break; - - case CdlStop: - if (cmdLogDebug) cmdLog.debug("CdlStop"); - setState(STATE_STOP); - clearResults(); - resetAudio(); - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - - case CdlStandby: - if (cmdLogDebug) cmdLog.debug("CdlStandby"); - setState(STATE_STANDBY); - clearResults(); - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - - case CdlPause: - if (cmdLogDebug) cmdLog.debug("CdlPause"); - setState(STATE_PAUSE); - clearResults(); - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - - case CdlSetMode: - if (cmdLogDebug) cmdLog.debug("CdlSetMode " + MiscUtil.toHex(params.get(0), 2)); - setCdMode(params.get(0)); - queueResult(newAckStatusResult()); - //if (true) throw new IllegalStateException("What?"); - break; - - case CdlCheckID: - // TODO, do this correctly; currently just saying we have a psx CD present - if (cmdLogDebug) cmdLog.debug("CdlCheckID"); - - queueResult(newAckStatusResult()); - - res = new CmdResult(); - res.type = CmdResult.ACKNOWLEDGE; - - int type = CDUtil.getMediaType(media); - - if (0 != (type & CDUtil.MEDIA_PRESENT)) { - boolean hasDataTracks = 0 != (type & CDUtil.MEDIA_HAS_DATA); - boolean hasAudioTracks = 0 != (type & CDUtil.MEDIA_HAS_AUDIO); - - boolean isPlayStationDisc = hasDataTracks; // duh clearly wrong - boolean genuinePlayStationDisc = isPlayStationDisc; - boolean isAudioDisk = hasAudioTracks && !hasDataTracks; - // todo figure out what happens if you put a copied PSX disc with audio in; should you be - // able to play the audio tracks? - - // bios always check [1] == 0x80... if so it'll try and boot as a playstation disc - // audio flag is only honored of [0] & 0x08 - // other flag of 0x40 means something else - perhaps disc with audio? - res.add(isAudioDisk ? 0x08 : 0x00); - res.add((isAudioDisk ? 0x10 : 0x00) | (genuinePlayStationDisc ? 0x00 : 0x80)); - res.add(0x00); - res.add(0x00); - res.type = CmdResult.COMPLETE; - } else { - res.type = CmdResult.DISKERROR; - // todo. check these - res.add(0); - res.add(0); - res.add(0); - res.add(0); - } - res.add('J'); - res.add('P'); - res.add('S'); - res.add('X'); - queueResult(res); - break; - - case CdlGetTN: - cmdLog.debug("CdlGetTN"); - - res = new CmdResult(); - // made up check - if (drive != null) { - res.type = CmdResult.ACKNOWLEDGE; - res.add(getStatus()); - res.add(CDUtil.toBCD(media.getFirstTrack())); - res.add(CDUtil.toBCD(media.getLastTrack())); - } else { - res.type = CmdResult.ACKNOWLEDGE; - } - queueResult(res); - break; - - case CdlGetTD: - int track = CDUtil.fromBCD(params.get(0)); - - if (traceCD) cmdLog.debug("CdlGetTD " + track); - - int msf = media.getTrackMSF(track); - - int m = (msf & 0xff0000) >> 16; - int s = (msf & 0xff00) >> 8; - int f = msf & 0xff; - - res = new CmdResult(); - res.type = CmdResult.ACKNOWLEDGE; - res.add(getStatus()); - res.add(m); - res.add(s); - res.add(f); - queueResult(res); - break; - - case CdlSeekL: - if (traceCD) cmdLog.debug("CdlSeekL"); - // what happens if we're playing - if (state == STATE_READN || state == STATE_READS) { - throw new IllegalStateException("SeekL while reading etc."); - //log.trace("seekl while reading!!!"); - } - - // i've seen seekl while playing; it.d have to close it. - setState(STATE_SEEKL); - queueResult(newAckStatusResult()); - break; - - case CdlSeekP: - if (traceCD) cmdLog.debug("CdlSeekP"); - // what happens if we're playing - if (false && state == STATE_PLAY || state == STATE_READN || state == STATE_READS) - throw new IllegalStateException("SeekP while playing/reading etc."); - setState(STATE_SEEKP); - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - - case CdlMute: - // todo implement - if (cmdLogDebug) cmdLog.debug("CdlMute"); - queueResult(newAckStatusResult()); - break; - - case CdlDemute: - // todo implement - if (cmdLogDebug) cmdLog.debug("CdlDemute"); - queueResult(newAckStatusResult()); - break; - - case CdlSetFilter: - filterFile = params.get(0); - filterChannel = params.get(1); - if (cmdLogDebug) cmdLog.debug("CdlSetFilter " + filterFile + " " + filterChannel); - queueResult(newAckStatusResult()); - break; - - case CdlPlay: - // todo check if this is always there - int tr = params.get(0); - if (cmdLogDebug) cmdLog.debug("CdlPlay " + tr); - if (media != null && tr >= media.getFirstTrack() && tr <= media.getLastTrack()) { - int playMSF = media.getTrackMSF(tr); - lastSetLocation.init(CDUtil.fromBCD((playMSF >> 16) & 0xff), CDUtil.fromBCD((playMSF >> 8) & 0xff), CDUtil.fromBCD(playMSF & 0xff)); - setLocDone = true; - } - resetAudio(); - setState(STATE_PLAY); - queueResult(newAckStatusResult()); - break; - case CdlFastForward: - // todo implement; note play needed to undo - if (cmdLogDebug) cmdLog.debug("CdlFastForward"); - queueResult(newAckStatusResult()); - break; - case CdlRewind: - // todo implement; note play needed to undo - if (cmdLogDebug) cmdLog.debug("CdlRewind"); - queueResult(newAckStatusResult()); - break; - case CdlGetLocL: - if (cmdLogDebug) cmdLog.debug("CdlGetLocL"); - queueResult(newAckStatusResult()); - // todo add 8 bytes of last read sector - break; - - case CdlGetLocP: - if (cmdLogDebug) cmdLog.debug("CdlGetLocP"); - //System.out.println("getlocl "+currentLocation); - // todo check this response; tombraider cares - // 5 bytes; tn, playing1/0 ?, m, s, f - res = new CmdResult(); - res.type = CmdResult.ACKNOWLEDGE; - track = getTrack(currentLocation.getM(), currentLocation.getS(), currentLocation.getF()); - res.add(CDUtil.toBCD(track)); - res.add(state == STATE_PLAY ? 1 : 0); - int trackMSF = track == 0 ? 0 : media.getTrackMSF(track); - int trackSector = CDUtil.toSector(CDUtil.fromBCD((trackMSF>>16)&0xff), CDUtil.fromBCD(((trackMSF)>>8)&0xff), CDUtil.fromBCD(trackMSF&0xff)); - int relativeSector = currentLocation.getSector() - trackSector; - res.add(relativeSector / (60*75)); - res.add((relativeSector / 75)%60); - res.add(relativeSector % 75); - res.add(CDUtil.toBCD(currentLocation.getM())); - res.add(CDUtil.toBCD(currentLocation.getS())); - res.add(CDUtil.toBCD(currentLocation.getF())); - queueResult(res); - //System.out.println(res); - break; - case CdlReadS: -// traceCD = true; - if (cmdLogDebug) cmdLog.debug("CdlReadS"); - resetAudio(); - setState(STATE_READS); - queueResult(newAckStatusResult()); - break; - case CdlReadTOC: - if (cmdLogDebug) cmdLog.debug("CdlReadTOC"); - drive.refreshMedia(); - media = drive.getCurrentMedia(); - queueResult(newAckStatusResult()); - queueResult(newCompleteStatusResult()); - break; - default: - throw new IllegalStateException("Unknown Cdl command " + cmd); - } - // doing this here for now... seems fair enough - params.reset(); - } - - private static int getStatus() { - int rc = 0; - - if (state != STATE_NONE) { - rc |= REG3_STANDBY; - } - - if (seeking) { - rc |= REG3_SEEKING; - } else { - if (state == STATE_PLAY) { - rc |= REG3_CDDA_PLAYING; - } - if (state == STATE_READN || state == STATE_READS) { - rc |= REG3_READING_DATA; - } - } - - //private static final int REG3_SHELL_OPEN = 0x10; - //private static final int REG3_SEEK_ERROR = 0x04; - //private static final int REG3_ERROR = 0x01; - return rc; - } - - private static synchronized void setState(int newState) { - log.trace("SET STATE " + newState); - state = newState; - substate = 0; - - if (setLocDone) { - currentLocation.init(lastSetLocation); - setLocDone = false; - } - sectorThread.newState(); - sectorReady = false; - sectorDismissed = true; - waitForDataReadCounter = 20; - someDataRead = true; - waitForDataRead = false; - // reset dma availability. - currentSectorOffset = currentSectorEnd = 0; - updateCallback(quartz.nanoTime()); - CD.class.notifyAll(); - } - - //private static int threes = 0; - - private static synchronized long updateCallback(long baseTime) { - long nextTime = 0L; - if (state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP) { - long period; - // note we - if (0 == (cdMode & CD_MODE_DOUBLE_SPEED)) { - period = Quartz.SEC / 150; - //if (threes != 0) period++; - } else { - period = Quartz.SEC / 300; - //if (threes == 2) period++; - } - //threes = threes++; - //if (threes == 3) threes = 0; - //if (0 != (cdMode & CD_MODE_XA)) period = ((period << 8) - period) >> 8; - - //if (state==STATE_READS) - // period = period * 300; - if (traceCD) log.info("adding clock callback"); - nextTime = baseTime + period; - if (!scheduler.isScheduled(sectorTick)) { - scheduler.schedule(baseTime + period, sectorTick); - } else { - if (traceCD) log.debug("clock callback already exists; skipping add"); - } - } - return nextTime; - } - - static int foobarCount = 0; - - static boolean toggle; - - private static synchronized long handleSectorTick(long currentTime) { - if (traceCD) log.info("enter callback; state=" + state); - switch (state) { - case STATE_SEEKL: - if (substate == 0) { - if (sectorThread.sectorsReady(true)) { - queueResult(newCompleteStatusResult()); - substate = 1; - } - } - break; - case STATE_SEEKP: - currentLocation.nextSpin(); - break; - case STATE_PLAY: - if (sectorThread.sectorsReady(substate == 0)) { - substate = 1; - if (sectorThread.filterDASector()) { - // todo maybe this should be result queue is not full - if (0 != (cdMode & CD_MODE_REPORT) && resultQueueIsEmpty()) { - CmdResult res = new CmdResult(); - - int track = getTrack(currentLocation.getM(), currentLocation.getS(), currentLocation.getF()); - int remainingM = 0; - int remainingS = 0; - if (media != null) { - if (track >= media.getFirstTrack() && track <= media.getLastTrack()) { - int endMSF = media.getTrackMSF(track == media.getLastTrack() ? 0 : track + 1); - int endM = CDUtil.fromBCD((endMSF >> 16) & 0xff); - int endS = CDUtil.fromBCD((endMSF >> 8) & 0xff); - int endF = CDUtil.fromBCD(endMSF & 0xff); - int remainingSectors = ((endM * 60) + endS) * 75 + endF - 150; - remainingSectors -= currentLocation.getSector(); - remainingSectors /= 75; - remainingS = remainingSectors % 60; - remainingM = remainingSectors / 60; - } - } - - // made up check - res.type = CmdResult.DATAREADY; - res.add(1); // ? - res.add(track); // track number - res.add(0); - toggle = !toggle; - if (toggle) { - res.add(CDUtil.toBCD(remainingM)); - res.add(CDUtil.toBCD(remainingS)); // ? - } else { - res.add(CDUtil.toBCD(currentLocation.getM())); - res.add(CDUtil.toBCD(currentLocation.getS()) | 0x80); - } - res.add(0); - res.add(0); - res.add(0); - queueResult(res); - } - } - } - break; - case STATE_READN: - // todo; end of file (or is dataend the end of the track?) - - // todo this can cause us to slow audio down, but that isn't our problem right now - if (sectorThread.sectorsReady(substate == 0)) { - substate = 1; - if (sectorThread.filterDataSector()) { - if (sectorDismissed) { - if (!checkSomeDataRead()) break; - if (rateLimit2Exceeded()) break; - if (rateLimit2) actualSectors++; - someDataRead = false; - sectorDismissed = false; - if (false || traceCD) log.trace("ah.. setting data ready"); - queueResult(newDataReadyStatusResult()); - } - } - } - break; - case STATE_READS: - // todo; end of file (or is dataend the end of the track?) - // todo, figure out what to do about sectorRequested... - if (sectorThread.sectorsReady(substate == 0)) { - substate = 1; - if (sectorThread.filterDataSector()) { - if (sectorDismissed) { - if (!checkSomeDataRead()) break; - if (rateLimit2Exceeded()) break; - if (rateLimit2) actualSectors++; - someDataRead = false; - sectorDismissed = false; - if (false || traceCD) log.trace("ah.. setting data ready"); - queueResult(newDataReadyStatusResult()); - } else { -// foobarCount++; - // if (0==(foobarCount&15)) - // log.trace("skipping sector ready for reads"); - } - } - } - break; - } - if (traceCD) log.trace("leave callback; state=" + state); - return updateCallback(currentTime); - } - - private static boolean checkSomeDataRead() { - if (waitForDataReadCounter > 0) { - waitForDataReadCounter--; - if (waitForDataReadCounter == 0) { - log.trace("DATA READ CHECK TIMEOUT!!!!!"); - } - return waitForDataReadCounter == 19; - } - return !(waitForDataRead && !someDataRead); - } - - private static void setSomeDataRead() { - if (waitForDataReadCounter > 0) { - if (SCP.EXCEPT_INTERRUPT == scp.currentExceptionType()) { - log.trace("DATA READ FROM IRQ - don't need hack"); - } else { - log.trace("DATA READ FROM non-IRQ - NEED HACK"); - waitForDataRead = true; - } - waitForDataReadCounter = 0; - } - someDataRead = true; - } - - private static void dismissSector() { - if (sectorDismissed || !sectorReady) - return; - - sectorThread.copySector(currentSector); - switch (cdMode & 0x30) { - case 0x00: - currentSectorOffset = 24; - currentSectorEnd = 24 + 2048; - break; - case 0x10: - currentSectorOffset = 12; - currentSectorEnd = 12 + 2328; - break; - case 0x20: - currentSectorOffset = 12; - currentSectorEnd = 12 + 2340; - break; - case 0x30: - currentSectorOffset = 24; - currentSectorEnd = 24 + 2328; - break; - } - sectorDismissed = true; - sectorReady = false; - } - - private static void prepareSector() { - if (currentSectorOffset == currentSectorEnd) { - dismissSector(); - } - } - - private static SectorTick sectorTick = new SectorTick(); - - private static class SectorTick implements ScheduledAction { - private int time; - - public void setTime(int t) { - time = t; - } - - public int getTime() { - return time; - } - - public long run(long currentTime) { - // long now = System.nanoTime(); - // double delta = (now-base)/1000000.0; - // log.info("CD time "+delta); - return handleSectorTick(currentTime); - } - } - - private static class SectorThread extends Thread { - private static final int SECTOR_BUFFERS = 32; - private static final int BUFFERS_BEFORE_READ = 8; - private static final int MIN_SECTOR_RUN = 8; // should always read this many sectors sequentially. - private HeadLocation[] sectorLocations = new HeadLocation[SECTOR_BUFFERS]; - private byte[][] sectorBuffers = new byte[SECTOR_BUFFERS][]; - private int sectorBufferNextRead; - private int sectorBufferNextWrite; - private HeadLocation readLocation = new HeadLocation(); - private boolean stateChanged; - private boolean locationChanged; - - public SectorThread() { - super("Sector read thread"); - for (int i = 0; i < SECTOR_BUFFERS; i++) { - sectorLocations[i] = new HeadLocation(); - sectorBuffers[i] = new byte[2352]; - } - - setPriority(NORM_PRIORITY + 2); - setDaemon(true); - start(); - } - - public void newState() { - assert Thread.holdsLock(CD.class); - stateChanged = true; - if (sectorBufferNextRead != sectorBufferNextWrite && sectorLocations[sectorBufferNextRead].getSector() == currentLocation.getSector()) { - if (traceCD) log.trace("CD: updateLocation is identical to old one, so nop"); - } else { - locationChanged = true; - readLocation.init(currentLocation); - // for now, clear buffer - sectorBufferNextRead = sectorBufferNextWrite; - } - seeking = state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP; - } - - public boolean filterDataSector() { - assert Thread.holdsLock(CD.class); - // todo filter! - assert sectorBufferNextRead != sectorBufferNextWrite; - - byte[] sector = sectorBuffers[sectorBufferNextRead]; - // xa audio submode == 0x64 -// log.trace( MiscUtil.toHex( (sector[4]>>16)&0xff, 8)); - //if (0!=(cdMode&CD_MODE_XA)) System.out.println(MiscUtil.toHex(sector[16],2)+" "+MiscUtil.toHex(sector[18],2)); - if (0x64 == sector[18]) { - if (0 != (cdMode & CD_MODE_XA)) { - if (0 == (cdMode & CD_MODE_FILTER) || (filterFile == (sector[16]) && filterChannel == (sector[17]))) { - if (!handleXASector(sector)) - return false; - } else { - // need to track that we've had a sector - if (rateLimit2) actualSectors++; - //log.trace("Skipping unfiltered sector "+(sector[4]&0xff)+" "+((sector[4]>>8)&0xff)); - } - } - currentLocation.init(sectorLocations[sectorBufferNextRead]); - //if (traceCD) log.info( "skipping XA audio sector"); - sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; - int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; - if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { - CD.class.notify(); - } - return false; - } - return true; - } - - public boolean filterDASector() { - assert Thread.holdsLock(CD.class); - // todo filter! - assert sectorBufferNextRead != sectorBufferNextWrite; - - byte[] sector = sectorBuffers[sectorBufferNextRead]; - - if (handleDASector(sector)) { - currentLocation.init(sectorLocations[sectorBufferNextRead]); - sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; - int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; - if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { - CD.class.notify(); - } - return true; - } - return false; - } - - public boolean sectorsReady(boolean seek) { - assert Thread.holdsLock(CD.class); - int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; - boolean rc = seek ? (sectors > BUFFERS_BEFORE_READ) : (sectors > 0); - if (traceCD) log.trace("sectors now: " + sectors); - seeking = !rc; - return rc; - } - - public void copySector(int[] target) { - synchronized (CD.class) { - byte[] byteBuf = sectorBuffers[sectorBufferNextRead]; - - for (int i = 0; i < 2352 / 4; i++) { - currentSector[i] = ((((int) byteBuf[i * 4 + 3]) & 0xff) << 24) | - ((((int) byteBuf[i * 4 + 2]) & 0xff) << 16) | - ((((int) byteBuf[i * 4 + 1]) & 0xff) << 8) | - ((((int) byteBuf[i * 4]) & 0xff)); - } - currentLocation.init(sectorLocations[sectorBufferNextRead]); - - if (traceCD) log.trace("COPY SECTOR " + MiscUtil.toHex(target[3], 6) + " " + currentLocation); - - // todo - this is only valid for data/xa sectors -// assert CDUtil.fromBCD( target[3] & 0xff ) == currentLocation.getM() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; -// assert CDUtil.fromBCD( (target[3] >> 8) & 0xff ) == currentLocation.getS() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; -// assert CDUtil.fromBCD( (target[3] >> 16) & 0xff ) == currentLocation.getF() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; - sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; - int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; - if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { - CD.class.notify(); - } - } - } - - public void run() { - log.info("SectorThread starts"); - try { - while (true) { - boolean read; - synchronized (CD.class) { - read = state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP; - int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; - if (read) { - if (sectors != SECTOR_BUFFERS - 2) { - sectorLocations[sectorBufferNextWrite].init(readLocation); - read = true; - } else { - read = false; - } - } - locationChanged = false; - stateChanged = false; - } - - if (read) { - if (traceCD) log.trace("reading sector " + readLocation); - try { - media.readSector(readLocation.getSector(), sectorBuffers[sectorBufferNextWrite]); - } catch (MediaException e) { - } - if (traceCD) - log.trace("read sector complete " + MiscUtil.toHex(sectorBuffers[sectorBufferNextWrite][3], 6) + " " + readLocation); - } - - synchronized (CD.class) { - // only want to update stuff if we didn't change location in the interim - if (read && !locationChanged) { - sectorBufferNextWrite = (sectorBufferNextWrite + 1) % SECTOR_BUFFERS; - readLocation.nextSequential(); - } - // sleep if we had nothing to do, and noone issued a new command in the interim - if (!read && !stateChanged) { - try { - if (traceCD) log.trace("SectorThread sleeps"); - CD.class.wait(); - if (traceCD) log.trace("SectorThread wakes"); - } catch (InterruptedException e) { - } - } - } - } - } finally { - log.info("SectorThread ends"); - } - } - } - - private static void resetAudio() { - xaDecoder.reset(); - cdFreq = 0; - rateLimitEnabled = false; - } - - private static final byte[] audioBuffer = new byte[4032 * 4]; - - private static boolean handleXASector(byte[] sectorBuffer) { - int samples = 0; - if (cdFreq == 0) { - if (cdAudioSink != null) { - cdAudioSink.newCDAudio(); - } - // need to decode to find the frequency - samples = xaDecoder.decodeXAAudioSector(sectorBuffer, audioBuffer); - if (cdFreq != xaDecoder.getFrequency()) { - cdFreq = xaDecoder.getFrequency(); - if (cdAudioSink != null) { - cdAudioSink.setCDAudioRate(cdFreq); - } - } - } - - if (rateLimit1Exceeded()) return false; - if (rateLimit2Exceeded()) return false; - - if (cdAudioSink != null && cdAudioSink.isCDAudible()) { - if (samples == 0) samples = xaDecoder.decodeXAAudioSector(sectorBuffer, audioBuffer); - actualAudioBytes += samples * 4; - //samples = Resample.resample(audioBuffer,xaDecoder.getFrequency(),samples,audioBuffer2,44100); - //cdAudioSink.cdAudioData(audioBuffer2,0,samples*4); - // todo we might want to send data anyway? - boolean started = cdAudioSink.cdAudioData(audioBuffer, 0, samples * 4); - if (rateLimit1 || rateLimit2) { - if (started) { - if (!rateLimitEnabled) { - rateLimitEnabled = true; - if (rateLimit1) actualAudioBytes = 0; - if (rateLimit2) actualSectors = 0; - rateLimitStartTime = quartz.nanoTime(); - // todo should we rate limit anyway? - rateLimitEnabled = true; - } else { - if (rateLimit2) actualSectors++; - } - } - } - } - return true; - } - - private static boolean handleDASector(byte[] sectorBuffer) { - if (cdFreq == 0) { - cdFreq = 44100; - if (cdAudioSink != null) { - cdAudioSink.newCDAudio(); - cdAudioSink.setCDAudioRate(cdFreq); - } - } - - if (rateLimit1Exceeded()) return false; - if (rateLimit2Exceeded()) return false; - - if (cdAudioSink != null && cdAudioSink.isCDAudible()) { - boolean started = cdAudioSink.cdAudioData(sectorBuffer, 0, 2352); - if (rateLimit1 || rateLimit2) { - if (started) { - if (!rateLimitEnabled) { - rateLimitEnabled = true; - if (rateLimit1) actualAudioBytes = 0; - if (rateLimit2) actualSectors = 0; - rateLimitStartTime = quartz.nanoTime(); - // todo should we rate limit anyway? - rateLimitEnabled = true; - } else { - if (rateLimit2) actualSectors++; - } - } - } - } - return true; - } - - private static boolean rateLimit1Exceeded() { - if (!(rateLimitEnabled && rateLimit1)) return false; - long time = quartz.nanoTime(); - assert false; - int expectedAudioBytes = (int) ((cdFreq * (time - rateLimitStartTime)) / 4000L); - if (log.isDebugEnabled()) { - log.debug(expectedAudioBytes + " " + actualAudioBytes); - } - - return actualAudioBytes > expectedAudioBytes; - } - - private static boolean rateLimit2Exceeded() { - if (!(rateLimitEnabled && rateLimit2)) return false; - long time = quartz.nanoTime(); - int sps = (cdMode & CD_MODE_DOUBLE_SPEED) != 0 ? 150 : 75; - - int expectedSectors = (int) ((sps * (time - rateLimitStartTime)) / Quartz.SEC); - if (log.isDebugEnabled()) { -// log.debug(expectedSectors+" "+actualSectors); - } - - return actualSectors > expectedSectors; - } - - /** - * @param m - * @param s - * @param f - * @return - */ - private static int getTrack(int m, int s, int f) { - int MSF = CDUtil.toMSF(m, s, f); - if (media != null) { - int rc = 0; - for (int i = media.getFirstTrack(); i <= media.getLastTrack(); i++) { - int trackMSF = media.getTrackMSF(i); - if (MSF < trackMSF) return rc; - rc++; - } - if (MSF < media.getTrackMSF(0)) { - return rc; - } - } - return 0; - } -} - diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java b/src/runtime/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java deleted file mode 100644 index feaccaf..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.cd; - -import org.apache.log4j.Logger; - -// todo finish this -/** - * Based on Kazzuya - Audio XA decode - */ -public class XADecoder { - Logger log = Logger.getLogger("XADecode"); - private static int[] IK0 = new int[]{0, -60, -115, -98, -122}; - private static int[] IK1 = new int[]{0, 0, 52, 55, 60}; - - //private static int[] headTable = new int[] {0,2,8,10}; - private static int[] headTable = new int[]{4, 6, 8, 10}; - - private static class ChannelContext { - public int y0; - public int y1; - - public void reset() { - y0 = y1 = 0; - } - } - - private ChannelContext leftContext = new ChannelContext(); - private ChannelContext rightContext = new ChannelContext(); - private boolean firstSector = false; - private boolean invalid; - private int freq; - private int bps; - private boolean stereo; - - private static final int BLOCK_SIZE = 28; - - public XADecoder() { - reset(); - } - - public void reset() { - leftContext.reset(); - rightContext.reset(); - firstSector = true; - } - - private void decodeBlock16(ChannelContext context, int filterRange, int[] src, byte[] dest, int destOffset, int inc) { - int filterId = (filterRange >> 4) & 0x0f; - int range = (filterRange & 0x0f) + 12; - - filterId &= 3; - - int fy0, fy1; - fy0 = context.y0; - fy1 = context.y1; - - int ik0 = IK0[filterId]; - int ik1 = IK1[filterId]; - - int s = 0; - int d = destOffset; - for (int i = BLOCK_SIZE / 4; i > 0; i--) { - int x = src[s++]; - int x0 = (x << 28) >> range; - x0 -= (ik0 * fy0 + ik1 * fy1) >> 6; - if (x0 > 524072) x0 = 524072; - else if (x0 < -525088) x0 = 525088; - dest[d] = (byte) (x0 >> 4); - dest[d + 1] = (byte) (x0 >> 12); - d += inc; - - int x1 = ((x << 24) & 0xf0000000) >> range; - x1 -= (ik0 * x0 + ik1 * fy0) >> 6; - if (x1 > 524072) x1 = 524072; - else if (x1 < -525088) x1 = 525088; - dest[d] = (byte) (x1 >> 4); - dest[d + 1] = (byte) (x1 >> 12); - d += inc; - - int x2 = ((x << 20) & 0xf0000000) >> range; - x2 -= (ik0 * x1 + ik1 * x0) >> 6; - if (x0 > 524072) x2 = 524072; - else if (x2 < -525088) x2 = 525088; - dest[d] = (byte) (x2 >> 4); - dest[d + 1] = (byte) (x2 >> 12); - d += inc; - - int x3 = ((x << 16) & 0xf0000000) >> range; - x3 -= (ik0 * x2 + ik1 * x1) >> 6; - if (x0 > 524072) x3 = 524072; - else if (x3 < -525088) x3 = 525088; - dest[d] = (byte) (x3 >> 4); - dest[d + 1] = (byte) (x3 >> 12); - d += inc; - fy1 = x2; - fy0 = x3; - } - context.y0 = fy0; - context.y1 = fy1; - } - - private int encoded[] = new int[14]; - - private int decode(byte[] src, int srcOffset, byte[] dest, int destOffset) { - int sound_groupsp; - int sound_datap; - int sound_datap2; - int nbits = bps == 4 ? 4 : 2; - int sampleCount = 0; - - if (stereo) { - for (int j = 0; j < 18; j++) { - sound_groupsp = srcOffset + j * 128; - sound_datap = sound_groupsp + 16; - - for (int i = 0; i < nbits; i++) { - int datap = 0; - sound_datap2 = sound_datap + i; - if ((bps == 8) && (freq == 37800)) { // level A - for (int k = 0; k < 14; k++, sound_datap2 += 8) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | - ((((int) src[sound_datap2 + 4]) & 0xff) << 8); - } - } else { // level B/C - for (int k = 0; k < 7; k++, sound_datap2 += 16) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xf) | - ((((int) src[sound_datap2 + 4]) & 0xf) << 4) | - ((((int) src[sound_datap2 + 8]) & 0xf) << 8) | - ((((int) src[sound_datap2 + 12]) & 0xf) << 12); - } - } - decodeBlock16(leftContext, src[sound_groupsp + headTable[i]], encoded, dest, destOffset, 4); - - datap = 0; - sound_datap2 = sound_datap + i; - if ((bps == 8) && (freq == 37800)) { // level A - for (int k = 0; k < 14; k++, sound_datap2 += 8) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | - ((((int) src[sound_datap2 + 4]) & 0xff) << 8); - } - } else { // level B/C - for (int k = 0; k < 7; k++, sound_datap2 += 16) { - encoded[datap++] = ((((int) src[sound_datap2]) & 0xf0) | - ((((int) src[sound_datap2 + 4]) & 0xf0) << 4) | - ((((int) src[sound_datap2 + 8]) & 0xf0) << 8) | - ((((int) src[sound_datap2 + 12]) & 0xf0) << 12)) >> 4; - } - } - decodeBlock16(rightContext, src[sound_groupsp + headTable[i] + 1], encoded, dest, destOffset + 2, 4); - destOffset += 28 * 4; - sampleCount += 28; - } - } - } else { // mono - for (int j = 0; j < 18; j++) { - sound_groupsp = srcOffset + j * 128; - sound_datap = sound_groupsp + 16; - - for (int i = 0; i < nbits; i++) { - int datap = 0; - sound_datap2 = sound_datap + i; - if ((bps == 8) && (freq == 37800)) { // level A - for (int k = 0; k < 14; k++, sound_datap2 += 8) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | - ((((int) src[sound_datap2 + 4]) & 0xff) << 8); - } - } else { // level B/C - for (int k = 0; k < 7; k++, sound_datap2 += 16) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xf) | - ((((int) src[sound_datap2 + 4]) & 0xf) << 4) | - ((((int) src[sound_datap2 + 8]) & 0xf) << 8) | - ((((int) src[sound_datap2 + 12]) & 0xf) << 12); - } - } - decodeBlock16(leftContext, src[sound_groupsp + headTable[i]], encoded, dest, destOffset, 4); - destOffset += 28 * 4; - sampleCount += 28; - - datap = 0; - sound_datap2 = sound_datap + i; - if ((bps == 8) && (freq == 37800)) { // level A - for (int k = 0; k < 14; k++, sound_datap2 += 8) { - encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | - ((((int) src[sound_datap2 + 4]) & 0xff) << 8); - } - } else { // level B/C - for (int k = 0; k < 7; k++, sound_datap2 += 16) { - encoded[datap++] = ((((int) src[sound_datap2]) & 0xf0) | - ((((int) src[sound_datap2 + 4]) & 0xf0) << 4) | - ((((int) src[sound_datap2 + 8]) & 0xf0) << 8) | - ((((int) src[sound_datap2 + 12]) & 0xf0) << 12)) >> 4; - } - } - decodeBlock16(leftContext, src[sound_groupsp + headTable[i] + 1], encoded, dest, destOffset, 4); - destOffset += 28 * 4; - sampleCount += 28; - } - } -/* for (j=0; j < 18; j++) { - sound_groupsp = srcp + j * 128; // sound groups header - sound_datap = sound_groupsp + 16; // sound data just after the header - - for (i=0; i < nbits; i++) { - datap = data; - sound_datap2 = sound_datap + i; - if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (U16)sound_datap2[0] | - (U16)(sound_datap2[4] << 8); - } - } else { // level B/C - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | - ((U16)(sound_datap2[ 4] & 0x0f) << 4) | - ((U16)(sound_datap2[ 8] & 0x0f) << 8) | - ((U16)(sound_datap2[12] & 0x0f) << 12); - } - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, - destp, 1 ); - - destp += 28; - - datap = data; - sound_datap2 = sound_datap + i; - if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (U16)sound_datap2[0] | - (U16)(sound_datap2[4] << 8); - } - } else { // level B/C - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (U16)(sound_datap2[ 0] >> 4) | - ((U16)(sound_datap2[ 4] >> 4) << 4) | - ((U16)(sound_datap2[ 8] >> 4) << 8) | - ((U16)(sound_datap2[12] >> 4) << 12); - } - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, - destp, 1 ); - - destp += 28; - } - } - - */ -// throw new IllegalStateException("mono"); - } - return sampleCount; - } - - public int decodeXAAudioSector(byte[] sector, byte[] samples) { - if (firstSector) { - int coding = sector[19]; - switch ((coding >> 2) & 3) { - case 0: - freq = 37800; - break; - case 1: - freq = 18900; - break; - default: - invalid = true; - break; - } - switch ((coding >> 4) & 3) { - case 0: - bps = 4; - break; - case 1: - bps = 8; - break; - default: - invalid = true; - break; - } - switch (coding & 3) { - case 0: - stereo = false; - break; - case 1: - stereo = true; - break; - default: - invalid = true; - break; - } - if (invalid) { - log.debug("INVALID XA"); - } else { - log.debug("XA " + freq + "x" + bps + " " + (stereo ? "stereo" : "mono")); - } - reset(); - firstSector = false; - } - if (invalid) { - return 0; - } - return decode(sector, 24, samples, 0); - } - - public int getFrequency() { - return freq; - } -} \ No newline at end of file diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/counters/Counters.java b/src/runtime/java/org/jpsx/runtime/components/hardware/counters/Counters.java deleted file mode 100644 index e98b1bf..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/counters/Counters.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.counters; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.ScheduledAction; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.api.components.hardware.cd.CDDrive; -import org.jpsx.api.components.hardware.cd.CDMedia; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.IRQOwnerBase; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.CDUtil; -import org.jpsx.runtime.util.MiscUtil; - -// todo pick NTSC or PAL other than by media. - -// todo IRQs for root counters -public class Counters extends SingletonJPSXComponent implements MemoryMapped { - public static final String CATEGORY = "Counters"; - public static final Logger log = Logger.getLogger(CATEGORY); - - public static final int ADDR_HARD_COUNTER0_COUNT = 0x1f801100; - public static final int ADDR_HARD_COUNTER1_COUNT = 0x1f801110; - public static final int ADDR_HARD_COUNTER2_COUNT = 0x1f801120; - public static final int ADDR_HARD_COUNTER0_MODE = 0x1f801104; - public static final int ADDR_HARD_COUNTER1_MODE = 0x1f801114; - public static final int ADDR_HARD_COUNTER2_MODE = 0x1f801124; - public static final int ADDR_HARD_COUNTER0_TARGET = 0x1f801108; - public static final int ADDR_HARD_COUNTER1_TARGET = 0x1f801118; - public static final int ADDR_HARD_COUNTER2_TARGET = 0x1f801128; - - private static final long CLOCK_FREQ = 33868800L; - - private static final int NTSC_VSYNC_FREQ = 60; - private static final int PAL_VSYNC_FREQ = 50; - private static long VSYNC_FREQ; - private static long HSYNC_FREQ; - private static long PIXEL_FREQ; - - private static long VSYNC_PERIOD; - - private static Counter[] counters; - - private static boolean bandicootUS; - private static IRQController irqController; - private static Quartz quartz; - private static Scheduler scheduler; - - public Counters() { - super("JPSX Hardware Counters"); - } - - public void init() { - super.init(); //To change body of overridden methods use File | Settings | File Templates. - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - // default to something - setNTSC(true); - bandicootUS = getBooleanProperty("bandicootUS", false); - log.info("Bandicoot = " + bandicootUS); - counters = new Counter[3]; - counters[0] = new Counter(0); - counters[1] = new Counter(1); - counters[2] = new Counter(2); - for (Counter counter : counters) { - CoreComponentConnections.IRQ_OWNERS.add(counter.getIrq()); - } - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - irqController = CoreComponentConnections.IRQ_CONTROLLER.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - scheduler = CoreComponentConnections.SCHEDULER.resolve(); - } - - public void begin() { - for (Counter counter : counters) { - counter.init(); - } - CDDrive drive = HardwareComponentConnections.CD_DRIVE.resolve(); - CDMedia media = drive == null ? null : drive.getCurrentMedia(); - - if (0 != (CDUtil.getMediaType(media) & CDUtil.MEDIA_REGION_EUROPE)) { - log.info("Picking PAL based on current media"); - setNTSC(false); - } else { - log.info("Picking NTSC based on current media"); - setNTSC(true); - } - new VSyncAction().start(); - } - - // todo, one shot? - static class Counter { - // psx - private int index; // counter num - private int mode; - private int target; - - // counting - private long freq; // incs per second - private int baseValue; - private long baseTime; - private long lastElapsed; - private int delta; - private boolean toggle; - - // irqs - private boolean irqsEnabled; - private long irqPeriod; // 1/4096 ms - - private IRQ irq; - - private class IRQ extends IRQOwnerBase { - public IRQ() { - super(4 + index, "COUNTER " + index); - } - } - - public IRQ getIrq() { - return irq; - } - - public Counter(int index) { - this.index = index; - irq = new IRQ(); - } - - public void init() { - setValue(0); - setTarget(0); - } - - public int getMode() { - return mode; - } - - public void setMode(int mode) { - if (log.isDebugEnabled()) { - log.debug("COUNTER " + index + " mode " + MiscUtil.toHex(mode, 8)); - } - this.mode = mode; - update(); - } - - public void setValue(int value) { - baseTime = quartz.nanoTime(); - lastElapsed = -1; - delta = 0; - baseValue = value; - //System.out.println("Set value "+value); - //System.out.println("COUNTER "+index+" setvalue = "+value+" pc="+MiscUtil.toHex(r3000.getPC(),8)); - } - - public int getValue() { - long elapsed = quartz.nanoTime() - baseTime; - int newValue = baseValue + (int) (elapsed * freq / Quartz.SEC); - /* - this should be irrelevent now we have nanoTime - if (elapsed == lastElapsed) { - // count up to the amount we'll reach on the next - // millisecond tick - if (toggle) { - toggle = !toggle; - } else { - if (delta < ((inc >> 12) - 1)) { - delta++; - } - newValue += delta; - } - } else { - lastElapsed = elapsed; - delta = 0; - } */ - // todo this looks wrong; since newValue may roll over. - int rc = newValue % (target + 1); - if (log.isTraceEnabled()) { - log.trace("read counter " + index + " " + rc + " " + MiscUtil.toHex(CoreComponentConnections.R3000.resolve().getPC(), 8)); - } - //System.out.println("counter "+index+" "+rc); - //System.out.println("COUNTER "+index+" getvalue = "+rc+" pc="+MiscUtil.toHex(r000.getPC(),8)); - return rc; - } - - public void setTarget(int target) { - target = target & 0xffff; - if (target == 0) { - target = 0x10000; - } - this.target = target; - update(); - } - - public int getTarget() { - return target & 0xffff; - } - - public void setTime(int previous) { - assert irqsEnabled; - //callbackTime = previous + irqPeriod; - } - - private synchronized void update() { - long newFreq = -1L; - switch (mode & 0x300) { - case 0: - newFreq = CLOCK_FREQ; - break; - case 0x100: - if (index == 0) { - // pixel - newFreq = PIXEL_FREQ; - } else if (index == 1) { - // horiz - newFreq = HSYNC_FREQ; - } - break; - case 0x200: - if (index == 2) { - // 1/8th system scheduler - newFreq = CLOCK_FREQ / 8; - } else { - newFreq = CLOCK_FREQ; - } - break; - case 0x300: - break; - } - if (newFreq == -1) { - log.warn("COUNTER " + index + " unknown clock rate; mode " + MiscUtil.toHex(mode, 4)); - newFreq = CLOCK_FREQ; - } - // note round up; for example Wipeout counts hsyncs, and does an extra - // vsync if we come in at 623 for two vsync rather than 624 - //freq = ((newFreq << 12) + 999) / 1000; - freq = newFreq + 1; - if (log.isDebugEnabled()) { - log.debug("COUNTER " + index + " frequency " + newFreq); - } - if ((mode & 0x50) == 0x50 && (index != 2 || (mode & 1) == 0)) { - long ips = newFreq / target; // Hz - log.info("REQUIRE COUNTER IRQ COUNTER " + index + " FREQ " + newFreq + " TARGET " + target + " IPS " + ips); - //irqPeriod = 4096000L/freq // microseconds - - if (!irqsEnabled) { - irqsEnabled = true; - } - //baseTime = MTScheduler.getTime(); - //setTime( baseTime); - //MTScheduler.addCallback( this); - } else { - irqsEnabled = false; - } - } - } - - public void registerAddresses(AddressSpaceRegistrar registrar) { - for (int i = 0; i <= 0x20; i += 0x10) { - registrar.registerRead32Callback(ADDR_HARD_COUNTER0_COUNT + i, Counters.class, "countRead32", true); - registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_COUNT + i, Counters.class, "countWrite32", true); - registrar.registerRead32Callback(ADDR_HARD_COUNTER0_MODE + i, Counters.class, "modeRead32", true); - registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_MODE + i, Counters.class, "modeWrite32", true); - registrar.registerRead32Callback(ADDR_HARD_COUNTER0_TARGET + i, Counters.class, "targetRead32", true); - registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_TARGET + i, Counters.class, "targetWrite32", true); - } - } - - private static Counter getCounter(int address) { - return counters[(address & 0x30) >> 4]; - } - - public static int countRead32(int address) { - return getCounter(address).getValue(); - } - - public static void countWrite32(int address, int value, int mask) { - getCounter(address).setValue(value & 0xffff); - } - - public static int modeRead32(int address) { - return getCounter(address).getMode(); - } - - public static void modeWrite32(int address, int value, int mask) { - Counter c = getCounter(address); - c.setMode((c.getMode() & ~mask) | (value & mask)); - } - - public static int targetRead32(int address) { - return getCounter(address).getTarget(); - } - - public static void targetWrite32(int address, int value, int mask) { - Counter c = getCounter(address); - mask &= 0xffff; - c.setTarget((c.getTarget() & ~mask) | (value & mask)); - } - - public static void setNTSC(boolean NTSC) { - VSYNC_FREQ = NTSC ? NTSC_VSYNC_FREQ : PAL_VSYNC_FREQ; - VSYNC_PERIOD = Quartz.SEC / VSYNC_FREQ; - int scans = NTSC ? 525 : 625; - HSYNC_FREQ = VSYNC_FREQ * scans / 2; - // todo; does this change with the video mode? - // todo is this correct - PIXEL_FREQ = 3840L * HSYNC_FREQ; - if (log.isDebugEnabled()) { - log.debug("HSYNC FREQ: " + HSYNC_FREQ); - log.debug("PIXEL FREQ: " + PIXEL_FREQ); - } - } - - private static class VSyncAction implements ScheduledAction { - private long nextTime; - - public void start() { - nextTime = quartz.nanoTime() + VSYNC_PERIOD; - scheduler.schedule(nextTime, this); - } - - public long run(long currentTime) { - irqController.raiseIRQ(IRQController.IRQ_VSYNC); - // if we missed some vsyncs, then skip them - while (currentTime >= nextTime) { - if (bandicootUS && currentTime > Quartz.SEC * 22) { - try { - // bandicoot US - AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - addressSpace.write32(0x80034520, addressSpace.read32(0x80034520) + 17); - } catch (Throwable t) { - } - } - nextTime = nextTime + VSYNC_PERIOD; - } - return nextTime; - } - } -} - diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java b/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java deleted file mode 100644 index 8ba1800..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.gpu; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.hardware.gpu.Display; -import org.jpsx.api.components.hardware.gpu.DisplayManager; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.util.Timing; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; - -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.*; - -/** - * Basic AWT Display implementation. There are other ways to do this, but this seems to work pretty at least as well - * as any other java2d method on most JDKs. - */ -public class AWTDisplay extends JPSXComponent implements Display, KeyListener { - private static final Logger log = Logger.getLogger("Display"); - - public static final String LOCATION_X_PROPERTY = "x"; - public static final String LOCATION_Y_PROPERTY = "y"; - - private Frame frame; - - private int[] ram; // video RAM - private BufferedImage bufferedImage; // image containing video RAM - private DisplayManager displayManager; - private int sourceWidth, sourceHeight; // the size of the source to be stretched to be displayed - - private boolean showBlitTime; - private boolean antiAlias; - - private boolean displayVRAM; - - private boolean funkyfudge; - - private ImageInfo[] imageInfoCache = new ImageInfo[]{ - new ImageInfo(), - new ImageInfo(), - new ImageInfo(), - new ImageInfo() - }; - - private int cacheReplaceIndex; - private VolatileImage volatileImage; - - private int MAX_X = 960; - private int MAX_Y = 512; - - private final int xres[] = new int[]{320, 640, 800, 960, 1024, 1280}; - private final int yres[] = new int[]{256, 512, 600, 768, 768, 1024}; - - private static final int BLIT_TIME_COUNT = 100; - private long blitTimeTotal; - private int blitTimeCount; - private boolean noStretch; - - int resindex = 1; - - public AWTDisplay() { - super("JPSX Default AWT Frame Display"); - } - - @Override - public void init() { - super.init(); - HardwareComponentConnections.DISPLAY.set(this); - RuntimeConnections.KEY_LISTENERS.add(this); - showBlitTime = Boolean.valueOf(getProperty("showBlitTime","true")); - antiAlias = Boolean.valueOf(getProperty("antiAlias","true")); - noStretch = Boolean.valueOf(getProperty("noStretch","false")); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - displayManager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); - } - - public void initDisplay() { - - // todo, make a new initialization state for this - frame = new Frame("JPSX") { - public void paint(Graphics g) { - stretchBlit(g); - } - }; - -// DirectColorModel model = new DirectColorModel( 24, 0x0000ff, 0x00ff00, 0xff0000); - DirectColorModel model = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); - WritableRaster raster = model.createCompatibleWritableRaster(1024, 513); - DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); - ram = db.getData(); - bufferedImage = new BufferedImage(model, raster, true, null); - int w = getIntProperty(LOCATION_X_PROPERTY, -1); - int h = getIntProperty(LOCATION_Y_PROPERTY, -1); - if (w != -1 && h != -1) frame.setLocation(w, h); - frame.show(); - frame.setResizable(false); - sizeframe(); - volatileImage = frame.createVolatileImage(MAX_X, MAX_Y); - frame.addKeyListener(RuntimeConnections.KEY_LISTENERS.resolve()); - frame.addWindowListener(new Closer()); - } - - protected class ImageInfo { - protected int x, y, w, h; - protected Image image; - - public boolean matches(int x, int y, int w, int h) { - return (this.x == x && this.y == y && this.w == w && this.h == h); - } - - public Image update(int x, int y, int w, int h) { - if (image != null) image.flush(); - image = bufferedImage.getSubimage(x, y, w, h); - this.x = x; - this.y = y; - this.w = w; - this.h = h; - return image; - } - - public Image getImage() { - return image; - } - } - -// public void setDisplayManager(DisplayManager manager) { -// displayManager = manager; -// refresh(); -// } - - public Image getImage(int x, int y, int w, int h) { - for (int i = 0; i < imageInfoCache.length; i++) { - if (imageInfoCache[i].matches(x, y, w, h)) { - return imageInfoCache[i].getImage(); - } - } - cacheReplaceIndex = (cacheReplaceIndex + 1) % imageInfoCache.length; - - // todo fix this - caused presumably by not displaying whole image! - if ((x + w) > 1024) { - w = 1024 - x; - } - if ((y + h) > 512) { - h = 512 - y; - } - if (log.isDebugEnabled()) { - log.debug("Creating new image at slot " + cacheReplaceIndex + " " + x + "," + y + " " + w + "," + h); - } - return imageInfoCache[cacheReplaceIndex].update(x, y, w, h); - } - - - protected void sizeframe() { - if (displayVRAM) - frame.setSize(new Dimension(1024 + frame.getInsets().left + frame.getInsets().right, 512 + frame.getInsets().top + frame.getInsets().bottom)); - else - frame.setSize(new Dimension(xres[resindex] + frame.getInsets().left + frame.getInsets().right, yres[resindex] + frame.getInsets().top + frame.getInsets().bottom)); - } - - protected void switchsize() { - resindex++; - if (resindex == xres.length) resindex = 0; - sizeframe(); - } - - // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU). - public int[] acquireDisplayBuffer() { - return ram; - } - - public void releaseDisplayBuffer() { - } - - protected synchronized void stretchBlit(Graphics g) { - int l = frame.getInsets().left; - int t = frame.getInsets().top; - long timeBasis = 0; - if (showBlitTime) { - timeBasis = Timing.nanos(); - } - if (displayVRAM) { - if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - g.drawImage(bufferedImage, l, t, null); - } else { - if (volatileImage != null && !volatileImage.contentsLost()) { - if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - if (noStretch) { - g.drawImage(volatileImage, l, t, l + sourceWidth, t + sourceHeight, - 0, 0, sourceWidth, sourceHeight, null); - } else { - g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], - 0, 0, sourceWidth, sourceHeight, null); - } - } - } - if (showBlitTime) { - blitTimeTotal += Timing.nanos()-timeBasis; - if (BLIT_TIME_COUNT == ++blitTimeCount) { - double blitTimeMSRounded = (blitTimeTotal/(BLIT_TIME_COUNT*100000))/10.0; - frame.setTitle("JPSX awt - " + ((blitTimeMSRounded >= 1) ? "!SLOW! blit=" : "blit=") + blitTimeMSRounded + "ms"); - blitTimeCount = 0; - blitTimeTotal = 0; - } - } - } - - public synchronized void refresh() { - boolean rgb24 = displayManager.getRGB24(); - if (funkyfudge) { - GPU.setVRAMFormat(!rgb24); - funkyfudge = false; - } - GPU.setVRAMFormat(rgb24); - // for now we use default display size - sourceWidth = displayManager.getDefaultPixelWidth(); - if (rgb24) sourceWidth = (sourceWidth * 3) / 2; - sourceHeight = displayManager.getDefaultPixelHeight(); - if (volatileImage.contentsLost()) { - volatileImage.validate(null); - } - if (displayManager.getBlanked()) { - Graphics2D g2 = volatileImage.createGraphics(); - try { - g2.setColor(Color.BLACK); - g2.fillRect(0, 0, sourceWidth, sourceHeight); - } finally { - g2.dispose(); - } - } else { - Graphics2D g2 = volatileImage.createGraphics(); - int marginLeft = displayManager.getLeftMarginPixels(); - if (rgb24) marginLeft = (marginLeft * 3) / 2; - int marginTop = displayManager.getTopMarginPixels(); - int pixelWidth = displayManager.getPixelWidth(); - if (rgb24) pixelWidth = (pixelWidth * 3) / 2; - int pixelHeight = displayManager.getPixelHeight(); - int marginRight = sourceWidth - pixelWidth - marginLeft; - int marginBottom = sourceHeight - pixelHeight - marginTop; - try { - if (pixelWidth > 0 && pixelHeight > 0) { - g2.drawImage(getImage(displayManager.getXOrigin(), displayManager.getYOrigin(), pixelWidth, pixelHeight), - marginLeft, marginTop, null); - } - g2.setColor(Color.BLACK); - if (marginLeft > 0) { - // fill left - g2.fillRect(0, 0, marginLeft, sourceHeight); - } - if (marginRight > 0) { - // fill left - g2.fillRect(sourceWidth - marginRight, 0, marginRight, sourceHeight); - } - if (marginTop > 0) { - // fill top - g2.fillRect(0, 0, sourceWidth, marginTop); - } - if (marginBottom > 0) { - // fill top - g2.fillRect(0, sourceHeight - marginBottom, sourceWidth, marginBottom); - } - } finally { - g2.dispose(); - } - } - Graphics graphics = frame.getGraphics(); - if (graphics != null) { - try { - stretchBlit(graphics); - } finally { - graphics.dispose(); - } - } - } - - public void keyTyped(KeyEvent e) { - } - - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_F12) { - switchsize(); - } - if (e.getKeyCode() == KeyEvent.VK_F11) { - refresh(); - } - if (e.getKeyCode() == KeyEvent.VK_F10) { - funkyfudge = true; - } - if (e.getKeyCode() == KeyEvent.VK_F9) { - displayVRAM = !displayVRAM; - sizeframe(); - refresh(); - } - if (e.getKeyCode() == KeyEvent.VK_F8) { - for (int i = 0; i < 1024 * 512; i++) { - ram[i] = ram[i] & 0x01ffffff; - } - } - if (e.getKeyCode() == KeyEvent.VK_F7) { - for (int i = 0; i < 1024 * 512; i++) { - ram[i] = ram[i] | 0xfe000000; - } - } - } - - public void keyReleased(KeyEvent e) { - } - - private static class Closer extends WindowAdapter { - public void windowClosing(WindowEvent e) { - RuntimeConnections.MACHINE.resolve().close(); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java b/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java deleted file mode 100644 index 9459205..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.gpu; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.hardware.gpu.Display; -import org.jpsx.api.components.hardware.gpu.DisplayManager; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; - -// todo change dirty code to only update every now and then... - -// todo this should be a component -public class DefaultDisplayManager extends JPSXComponent implements DisplayManager { - private static final Logger log = Logger.getLogger("Display"); - private long lastRefreshTime = 0; - private boolean hadDirty = false; - private static final long DIRTY_REFRESH_PERIOD = 100 * Quartz.MSEC; - private static final long AUTO_REFRESH_PERIOD = 200 * Quartz.MSEC; - - private Quartz quartz; - private Display display; - - public DefaultDisplayManager() { - super("JPSX Default GPU Display Manager"); - } - - - public void init() { - super.init(); - HardwareComponentConnections.DISPLAY_MANAGER.set(this); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - display = HardwareComponentConnections.DISPLAY.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - } - - private static boolean intersects(int x0, int y0, int w0, int h0, int x1, int y1, int w1, int h1) { - if (w0 == 0 || h0 == 0 || w1 == 0 || h1 == 0) return false; - w0 += x0; - w1 += x1; - h0 += y0; - h1 += y1; - return (w0 > x1) && (h0 > y1) && (w1 > x0) && (h1 > y0); - } - - private static class State { - public int hStart; - public int hEnd; - public int vStart; - public int vEnd; - public boolean blanked; - public boolean NTSC; - public boolean interlaced; - public boolean doubleY; - public boolean rgb24; - public int pixelDivider = 8; - - public int xOrigin; - public int yOrigin; - - public int x0Dirty; - public int y0Dirty; - public int x1Dirty; - public int y1Dirty; - - protected int getDefaultTimingLeft() { - return NTSC ? 608 : 628; - } - - protected int getDefaultTimingTop() { - return NTSC ? 16 : 40; - } - - protected int getDefaultTimingWidth() { - return 2560; - } - - protected int getDefaultTimingHeight() { - return NTSC ? 240 : 256; - } - - public int getDefaultPixelWidth() { - return getDefaultTimingWidth() / pixelDivider; - } - - public int getDefaultPixelHeight() { - int rc = getDefaultTimingHeight(); - if (doubleY) { - rc <<= 1; - } - return rc; - } - - public int getPixelWidth() { - return (hEnd - hStart) / pixelDivider; - } - - public int getPixelHeight() { - int rc = vEnd - vStart; - if (doubleY) { - rc <<= 1; - } - return rc; - } - - public int getLeftMargin() { - return hStart - getDefaultTimingLeft(); - } - - public int getLeftMarginPixels() { - return getLeftMargin() / pixelDivider; - } - - public int getRightMargin() { - return getDefaultTimingLeft() + getDefaultTimingWidth() - hEnd; - } - - public int getRightMarginPixels() { - return getRightMargin() / pixelDivider; - } - - public int getTopMargin() { - return vStart - getDefaultTimingTop(); - } - - public int getTopMarginPixels() { - int rc = getTopMargin(); - - if (doubleY) { - rc <<= 1; - } - return rc; - } - - public int getBottomMargin() { - return getDefaultTimingTop() + getDefaultTimingHeight() - vEnd; - } - - public int getBottomMarginPixels() { - int rc = getBottomMargin(); - - if (doubleY) { - rc <<= 1; - } - return rc; - } - - public boolean isDirty() { - if (x0Dirty == x1Dirty) return false; - //System.out.println("CHECKING DIRTY: disp "+xOrigin+","+yOrigin+" x "+getPixelWidth()+","+getPixelHeight()+"\n"+ - // "dirty "+x0Dirty+","+y0Dirty+" by "+(x1Dirty-x0Dirty)+","+(y1Dirty-y0Dirty)); - boolean rc = intersects(xOrigin, yOrigin, getPixelWidth(), getPixelHeight(), - x0Dirty, y0Dirty, x1Dirty - x0Dirty, y1Dirty - y0Dirty); - //if (rc) System.out.println(" INTERSECT DIRTY!"); - return rc; - } - - public void dirtyRectangle(int x, int y, int w, int h) { - int x1 = x + w; - int y1 = y + h; - if (x0Dirty == x1Dirty) { - x0Dirty = x; - y0Dirty = y; - x1Dirty = x1; - y1Dirty = y1; - } else { - if (x < x0Dirty) x0Dirty = x; - if (x1 > x1Dirty) x1Dirty = x1; - if (y < y0Dirty) y0Dirty = y; - if (y1 > y1Dirty) y1Dirty = y1; - } -// System.out.println("SET DIRTY: disp "+xOrigin+","+yOrigin+" x "+getPixelWidth()+","+getPixelHeight()+"\n"+ -// "dirty "+x0Dirty+","+y0Dirty+" by "+(x1Dirty-x0Dirty)+","+(y1Dirty-y0Dirty)); - } - - public void reset(State base) { - hStart = base.hStart; - hEnd = base.hEnd; - vStart = base.vStart; - vEnd = base.vEnd; - xOrigin = base.xOrigin; - yOrigin = base.yOrigin; - blanked = base.blanked; - NTSC = base.NTSC; - interlaced = base.interlaced; - rgb24 = base.rgb24; - pixelDivider = base.pixelDivider; - doubleY = base.doubleY; - - x0Dirty = x1Dirty; // empty dirty region - } - - public boolean matches(State other) { - return xOrigin == other.xOrigin && - yOrigin == other.yOrigin && - hStart == other.hStart && - hEnd == other.hEnd && - vStart == other.vStart && - vEnd == other.vEnd && - blanked == other.blanked && - NTSC == other.NTSC && - interlaced == other.interlaced && - doubleY == other.doubleY && - pixelDivider == other.pixelDivider && - rgb24 == other.rgb24; - } - - public String toString() { - String rc = getDefaultPixelWidth() + "x" + getDefaultPixelHeight() + "x" + (rgb24 ? "24" : "15"); - rc += " displayed: " + getPixelWidth() + "x" + getPixelHeight() + "x" + (rgb24 ? "24" : "15"); - rc += " offset: " + hStart + "," + vStart; - if (blanked) { - rc += " blanked"; - } - rc += NTSC ? " (NTSC)" : " (PAL)"; - rc += " origin " + xOrigin + "," + yOrigin; - return rc; - } - } - - protected State states[] = new State[]{new State(), new State()}; - protected int currentState = 0; - protected boolean interlaceField; - protected boolean forceUpdate; - - public void preAsync() { - updateState(); - } - - // called if a vsync has passed to make sure display is updated if necessary - // (e.g. drawing to display)... usually this does nothing, because setOrigin - // updates display if necessary - public void vsync() { - updateState(); - } - - public void setOrigin(int x, int y) { - // setting the origin takes effect immediately; we take - // any pending display changes - State s = getNextState(); - s.xOrigin = x; - s.yOrigin = y; - updateState(); - } - - protected State getState() { - return states[currentState]; - } - - protected State getNextState() { - return states[currentState ^ 1]; - } - - protected void updateState() { - currentState = currentState ^ 1; - State s = getState(); - boolean refresh = (forceUpdate || !states[0].matches(states[1])); - if (!refresh && s.isDirty()) { - hadDirty = true; - } - long time = quartz.nanoTime(); - if (!refresh && hadDirty && DIRTY_REFRESH_PERIOD < (time - lastRefreshTime)) { - if (log.isDebugEnabled()) { - log.debug("UPDATING DISPLAY BECAUSE DIRTY"); - } - refresh = true; - hadDirty = false; - } - if (!refresh && AUTO_REFRESH_PERIOD < (time - lastRefreshTime)) { - if (log.isDebugEnabled()) { - log.debug("UPDATING DISPLAY BECAUSE HAVEN'T HAD ONE"); - } - refresh = true; - } - if (refresh) { - lastRefreshTime = time; - //System.out.println("UPDATING DISPLAY: "+s.toString()); - forceUpdate = false; - display.refresh(); - } else { -// System.out.println("NOT UPDATING DISPLAY: "+s.toString()); - } - // next state should configure off as we are - getNextState().reset(s); - } - - public void toggleInterlaceField() { - interlaceField = !interlaceField; - forceUpdate = true; - } - - public boolean getInterlaceField() { - return interlaceField; - } - - // mark a display area as changed... if it intersects the next - // display region, then we will get an update at the next vsync, or - // display origin change - public void dirtyRectangle(int x, int y, int w, int h) { - // we only care about the next display state... - getNextState().dirtyRectangle(x, y, w, h); - } - - public void setPixelDivider(int divider) { - getNextState().pixelDivider = divider; - } - - public void setNTSC(boolean NTSC) { - getNextState().NTSC = NTSC; - } - - public boolean getNTSC() { - return getState().NTSC; - } - - public void setInterlaced(boolean interlaced) { - getNextState().interlaced = interlaced; - } - - public boolean getInterlaced() { - return getState().interlaced; - } - - public void setDoubleY(boolean doubleY) { - getNextState().doubleY = doubleY; - } - - public boolean getDoubleY() { - return getState().doubleY; - } - - public void setRGB24(boolean rgb24) { - getNextState().rgb24 = rgb24; - } - - public boolean getRGB24() { - return getState().rgb24; - } - - public void setBlanked(boolean blanked) { - getNextState().blanked = blanked; - } - - public boolean getBlanked() { - return getState().blanked; - } - - public void setHorizontalTiming(int hStart, int hEnd) { - State s = getNextState(); - s.hStart = hStart; - s.hEnd = hEnd; - } - - public void setVerticalTiming(int vStart, int vEnd) { - State s = getNextState(); - s.vStart = vStart; - s.vEnd = vEnd; - } - - public int getDefaultTimingWidth() { - return getState().getDefaultTimingWidth(); - } - - public int getDefaultTimingHeight() { - return getState().getDefaultTimingHeight(); - } - - public int getDefaultPixelWidth() { - return getState().getDefaultPixelWidth(); - } - - public int getDefaultPixelHeight() { - return getState().getDefaultPixelHeight(); - } - - public int getPixelWidth() { - return getState().getPixelWidth(); - } - - public int getPixelHeight() { - return getState().getPixelHeight(); - } - - public int getXOrigin() { - return getState().xOrigin; - } - - public int getYOrigin() { - return getState().yOrigin; - } - - public int getLeftMargin() { - return getState().getLeftMargin(); - } - - public int getLeftMarginPixels() { - return getState().getLeftMarginPixels(); - } - - public int getRightMargin() { - return getState().getRightMargin(); - } - - public int getRightMarginPixels() { - return getState().getRightMarginPixels(); - } - - public int getTopMargin() { - return getState().getTopMargin(); - } - - public int getTopMarginPixels() { - return getState().getTopMarginPixels(); - } - - public int getBottomMargin() { - return getState().getBottomMargin(); - } - - public int getBottomMarginPixels() { - return getState().getBottomMarginPixels(); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPU.java b/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPU.java deleted file mode 100644 index e305972..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPU.java +++ /dev/null @@ -1,9260 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.gpu; - -import org.apache.bcel.classfile.ClassParser; -import org.apache.bcel.classfile.ConstantUtf8; -import org.apache.bcel.classfile.Field; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.FieldGen; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.addressspace.Pollable; -import org.jpsx.api.components.core.cpu.PollBlockListener; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.api.components.hardware.gpu.Display; -import org.jpsx.api.components.hardware.gpu.DisplayManager; -import org.jpsx.bootstrap.classloader.ClassGenerator; -import org.jpsx.bootstrap.classloader.JPSXClassLoader; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.DMAChannelOwnerBase; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -// todo fix bit flags for 15 bit dma - -// todo convert subrange back to 16 bit. - -public class GPU extends SingletonJPSXComponent implements ClassGenerator, MemoryMapped, PollBlockListener, Pollable { - private static final boolean ignoreGPU = false; - private static final boolean dumpGPUD = false; - private static final boolean debugTransfers = false; - private static final boolean debugTexturePage = false; - private static final boolean rgb24conversion = true; - private static final boolean supportTextureWindow = true; - - private static final int ADDR_GPU_DATA = 0x1f801810; - private static final int ADDR_GPU_CTRLSTATUS = 0x1f801814; - - private static final int GPUD_CMD_NONE = 0; - private static final int GPUD_CMD_FILLING = 1; - private static final int GPUD_CMD_EXTRA = 2; - - private static final int DRAWMODE_SEMI_5P5 = 0x0000; - private static final int DRAWMODE_SEMI_10P10 = 0x0020; - private static final int DRAWMODE_SEMI_10M10 = 0x0040; - private static final int DRAWMODE_SEMI_10P25 = 0x0060; - - private static final int SEMI_NONE = 0; - private static final int SEMI_5P5 = 1; - private static final int SEMI_10P10 = 2; - private static final int SEMI_10M10 = 3; - private static final int SEMI_10P25 = 4; - - private static final int DRAWMODE_TEXTURE_4BIT = 0x0000; - private static final int DRAWMODE_TEXTURE_8BIT = 0x0080; - private static final int DRAWMODE_TEXTURE_16BIT = 0x0100; - // fake.. returned by getTextureMode() if a texture window is in effect - private static final int DRAWMODE_TEXTURE_4BITW = 0x8000; - private static final int DRAWMODE_TEXTURE_8BITW = 0x8080; - private static final int DRAWMODE_TEXTURE_16BITW = 0x8100; - - private static final int DRAWMODE_SET_MASK = 0x0800; - private static final int DRAWMODE_CHECK_MASK = 0x1000; - - private static final int TEXTURE_NONE = 0; - private static final int TEXTURE_4BIT = 1; - private static final int TEXTURE_8BIT = 2; - private static final int TEXTURE_16BIT = 3; - private static final int TEXTURE_4BITW = 4; - private static final int TEXTURE_8BITW = 5; - private static final int TEXTURE_16BITW = 6; - - //private static final int PIXEL_BREG_CLUT = 0x40000000; - private static final int PIXEL_SOLID_CLUT = 0x20000000; - private static final int PIXEL_SOLID_CLUT_CHECKED = 0x10000000; - private static final int PIXEL_RGB24 = 0x08000000; - - private static final int PIXEL_DMA_A = 0x02000000; - private static final int PIXEL_DMA_B = 0x04000000; - private static final int PIXEL_DMA_C = 0x06000000; - - - private static final int GPU_RGBXX_X_MASK = PIXEL_RGB24 | PIXEL_DMA_A | PIXEL_DMA_B | PIXEL_DMA_C; - - private static final int GPU_RGB24_A = PIXEL_RGB24 | PIXEL_DMA_A; - private static final int GPU_RGB24_B = PIXEL_RGB24 | PIXEL_DMA_B; - private static final int GPU_RGB24_C = PIXEL_RGB24 | PIXEL_DMA_C; - - private static final int GPU_RGB15_A = PIXEL_DMA_A; - private static final int GPU_RGB15_B = PIXEL_DMA_B; - private static final int GPU_RGB15_C = PIXEL_DMA_C; - - private static Display display; - - private static DisplayManager manager; - - private static final int[] dma16flags; - - private static AddressSpace addressSpace; - - public GPU() { - super("JPSX Software GPU"); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - display = HardwareComponentConnections.DISPLAY.resolve(); - manager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); - } - - - public void begin() { - display.initDisplay(); - gpusReset(0); - } - - static { - if (rgb24conversion) { - dma16flags = new int[]{GPU_RGB15_A, GPU_RGB15_B, GPU_RGB15_C, GPU_RGB15_A}; - } else { - dma16flags = new int[]{0, 0, 0, 0}; - } - } - - private static final int getTexturePage() { - return drawMode & 0x1f; - } - - private static final int getMaskModes() { - return drawMode & (DRAWMODE_SET_MASK | DRAWMODE_CHECK_MASK); - } - - /** - * accessor function for texture mode from m_drawMode - */ - private static final int getTextureMode() { - int rc = drawMode & 0x0180; - if (noTextureWindow) return rc; - return rc | 0x8000; - } - - /** - * accessor function for semi-transparency mode from m_drawMode - */ - private static final int getSemiMode() { - return drawMode & 0x0060; - } - - private static int displayMode; - private static int dmaMode; - private static int maskMode; - private static int drawMode; - - private static int cmdBufferUsed; - private static int cmdBufferTarget; - private static int m_gpudState; - - private static int m_drawOffsetX; - private static int m_drawOffsetY; - - private static int m_dmaRGB24Index; - private static int m_dmaRGB24LastPixel; - private static int m_dmaRGB24LastDWord; - private static int m_dmaX; - private static int m_dmaY; - private static int m_dmaOriginX; - private static int m_dmaOriginY; - private static int m_dmaW; - private static int m_dmaH; - private static int m_dmaDWordsRemaining; - private static int m_dmaWordsRemaining; - - private static boolean noTextureWindow = true; - - private static final int[] twuLookup = new int[32]; - private static final int[] twvLookup = new int[32]; - - private static boolean rgb24; - - private static int m_gpudCommand; - - //private static int[] m_extraCmdBuffer; - //private static int m_extraCmdOffset; - //private static int m_extraCmdSize; - - // clip - // for now non-zero -// private static int m_clipLeft=0; -// private static int m_clipRight=320; - // private static int m_clipTop=0; - // private static int m_clipBottom=512; - private static int m_clipLeft; - private static int m_clipRight; - private static int m_clipTop; - private static int m_clipBottom; - - private static final int CMD_BUFFER_SIZE = 16; - - private static final int[] m_cmdBuffer = new int[CMD_BUFFER_SIZE]; - - private static int[] videoRAM; - - private static final byte[][] _4bitTexturePages = new byte[32][]; - private static final byte[][] _8bitTexturePages = new byte[32][]; - - public void init() { - super.init(); - JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_T", this); - JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_L", this); - JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_S", this); - JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_Q", this); - JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_R", this); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - CoreComponentConnections.POLL_BLOCK_LISTENERS.add(this); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new GPUDMAChannel()); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new OTCDMAChannel()); - } - - private static int m_gpudFunctionArgumentCount[] = { - 1, // 00 - 1, // 01 - 3, // 02 - 1, // 03 - 1, // 04 - 1, // 05 - 1, // 06 - 1, // 07 - 1, // 08 - 1, // 09 - 1, // 0a - 1, // 0b - 1, // 0c - 1, // 0d - 1, // 0e - 1, // 0f - 1, // 10 - 1, // 11 - 1, // 12 - 1, // 13 - 1, // 14 - 1, // 15 - 1, // 16 - 1, // 17 - 1, // 18 - 1, // 19 - 1, // 1a - 1, // 1b - 1, // 1c - 1, // 1d - 1, // 1e - 1, // 1f - 4, // 20 - 4, // 21 - 4, // 22 - 4, // 23 - 7, // 24 - 7, // 25 - 7, // 26 - 7, // 27 - 5, // 28 - 5, // 29 - 5, // 2a - 5, // 2b - 9, // 2c - 9, // 2d - 9, // 2e - 9, // 2f - 6, // 30 - 6, // 31 - 6, // 32 - 6, // 33 - 9, // 34 - 9, // 35 - 9, // 36 - 9, // 37 - 8, // 38 - 8, // 39 - 8, // 3a - 8, // 3b - 12, // 3c - 12, // 3d - 12, // 3e - 12, // 3f - 3, // 40 - 1, // 41 - 3, // 42 - 1, // 43 - 1, // 44 - 1, // 45 - 1, // 46 - 1, // 47 - 3, // 48 - 1, // 49 - 3, // 4a - 1, // 4b - 1, // 4c - 1, // 4d - 1, // 4e - 1, // 4f - 4, // 50 - 1, - 4, - 1, - 1, // 54 - 1, // 55 - 1, // 56 - 1, // 57 - 4, // 58 - 1, - 4, - 1, - 1, // 5c - 1, // 5d - 1, // 5e - 1, // 5f - 3, // 60 - 3, - 3, - 3, - 4, // 64 - 4, - 4, - 4, - 2, - 2, - 2, - 2, - 1, // 6c - 1, // 6d - 1, // 6e - 1, // 6f - 2, // 70 - 2, - 2, - 2, - 3, // 74 - 3, - 3, - 3, - 2, // 78 - 2, - 2, - 2, - 3, // 7c - 3, - 3, - 3, - 4, // 80 - 1, // 81 - 1, // 82 - 1, // 83 - 1, // 84 - 1, // 85 - 1, // 86 - 1, // 87 - 1, // 88 - 1, // 89 - 1, // 8a - 1, // 8b - 1, // 8c - 1, // 8d - 1, // 8e - 1, // 8f - 1, // 90 - 1, // 91 - 1, // 92 - 1, // 93 - 1, // 94 - 1, // 95 - 1, // 96 - 1, // 97 - 1, // 98 - 1, // 99 - 1, // 9a - 1, // 9b - 1, // 9c - 1, // 9d - 1, // 9e - 1, // 9f - 3, // a0 - 1, // a1 - 1, // a2 - 1, // a3 - 1, // a4 - 1, // a5 - 1, // a6 - 1, // a7 - 1, // a8 - 1, // a9 - 1, // aa - 1, // ab - 1, // ac - 1, // ad - 1, // ae - 1, // af - 1, // b0 - 1, // b1 - 1, // b2 - 1, // b3 - 1, // b4 - 1, // b5 - 1, // b6 - 1, // b7 - 1, // b8 - 1, // b9 - 1, // ba - 1, // bb - 1, // bc - 1, // bd - 1, // be - 1, // bf - 3, // c0 - 1, // c1 - 1, // c2 - 1, // c3 - 1, // c4 - 1, // c5 - 1, // c6 - 1, // c7 - 1, // c8 - 1, // c9 - 1, // ca - 1, // cb - 1, // cc - 1, // cd - 1, // ce - 1, // cf - 1, // d0 - 1, // d1 - 1, // d2 - 1, // d3 - 1, // d4 - 1, // d5 - 1, // d6 - 1, // d7 - 1, // d8 - 1, // d9 - 1, // da - 1, // db - 1, // dc - 1, // dd - 1, // de - 1, // df - 1, // e0 - 1, // e1 - 1, // e2 - 1, // e3 - 1, // e4 - 1, // e5 - 1, // e6 - 1, // e7 - 1, // e8 - 1, // e9 - 1, // ea - 1, // eb - 1, // ec - 1, // ed - 1, // ee - 1, // ef - 1, // f0 - 1, // f1 - 1, // f2 - 1, // f3 - 1, // f4 - 1, // f5 - 1, // f6 - 1, // f7 - 1, // f8 - 1, // f9 - 1, // fa - 1, // fb - 1, // fc - 1, // fd - 1, // fe - 1, // ff - }; - - private static boolean m_displayEnabled; - - - public void registerAddresses(AddressSpaceRegistrar registrar) { - registrar.registerWrite32Callback(ADDR_GPU_CTRLSTATUS, GPU.class, "gpuCtrlWrite32"); - registrar.registerWrite32Callback(ADDR_GPU_DATA, GPU.class, "gpuDataWrite32"); - registrar.registerRead32Callback(ADDR_GPU_CTRLSTATUS, GPU.class, "gpuStatusRead32"); - registrar.registerRead32Callback(ADDR_GPU_DATA, GPU.class, "gpuDataRead32"); - - registrar.registerPoll32Callback(ADDR_GPU_CTRLSTATUS, this); - } - - static long baseTime = System.currentTimeMillis(); - static int counter = 0; - - private static void debuggo() { - System.out.println(counter + " " + (System.currentTimeMillis() - baseTime)); - counter++; - } - - public static void gpuCtrlWrite32(int address, int val) { - if (ignoreGPU) { - debuggo(); - return; - } -// ASSERT( SANITY_CHECK, address==ADDR_GPU_CTRLSTATUS, ""); - switch (val >> 24) { - case 0: - gpusReset(val); - break; - case 1: - gpusCmdReset(val); - break; - case 2: - gpusIRQReset(val); - break; - case 3: - gpusSetDispEnable(val); - break; - case 4: - gpusSetDataTransferMode(val); - break; - case 5: - gpusSetDisplayOrigin(val); - break; - case 6: - gpusSetMonitorLeftRight(val); - break; - case 7: - gpusSetMonitorTopBottom(val); - break; - case 8: - gpusSetDisplayMode(val); - break; - case 0x10: - gpusRequestInfo(val); - break; - } - } - - public static void gpuDataWrite32(int address, int val) { - if (ignoreGPU) { - debuggo(); - return; - } - videoRAM = display.acquireDisplayBuffer(); - try { - switch (m_gpudState) { - case GPUD_CMD_NONE: - m_gpudCommand = (val >> 24) & 0xff; - m_cmdBuffer[0] = val; - cmdBufferUsed = 1; - cmdBufferTarget = m_gpudFunctionArgumentCount[m_gpudCommand]; - m_gpudState = GPUD_CMD_FILLING; - break; - case GPUD_CMD_FILLING: - m_cmdBuffer[cmdBufferUsed++] = val; - break; - case GPUD_CMD_EXTRA: - m_cmdBuffer[0] = val; - int dwordsUsed = GPUDRouter.invoke(m_cmdBuffer, 0, 1); - assert (dwordsUsed == 1); - return; - } - assert (m_gpudState == GPUD_CMD_FILLING); - if (cmdBufferUsed == cmdBufferTarget) { - m_gpudState = GPUD_CMD_NONE; - GPUDRouter.invoke(m_cmdBuffer, 0, cmdBufferUsed); - } - } finally { - display.releaseDisplayBuffer(); - videoRAM = null; - } - } - - private static class TemplateQuadRenderer { - public static void render(PolygonRenderInfo info, Vertex v0, Vertex v1, Vertex v2, Vertex v3) { - if ((v3.x == v2.x && v0.x == v1.x && v0.y == v2.y && v1.y == v3.y) || - (v0.x == v2.x && v1.x == v3.x && v0.y == v1.y && v2.y == v3.y)) { - // this returns false if it detects non-linear gradients across the rectangle; - if (TemplateRectangleRenderer.render(info, v0, v1, v2, v3)) - return; - } - TemplateTriangleRenderer.render(info, v0, v1, v2); - TemplateTriangleRenderer.render(info, v2, v1, v3); - } - } - - private static byte[] get4BitTexturePage() { - int page = getTexturePage() & 0x1f; - byte[] rc = _4bitTexturePages[page]; - if (rc == null) { - assert !rgb24; - if (debugTexturePage) System.out.println("Generating 4 bit texture page"); - rc = new byte[0x10000]; - int offset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; - int destOffset = 0; - for (int y = 0; y < 256; y++) { - for (int x = 0; x < 64; x++) { - int val = unmakePixel(videoRAM[offset++]); - - rc[destOffset++] = (byte) (val & 0xf); - rc[destOffset++] = (byte) ((val & 0xf0) >> 4); - rc[destOffset++] = (byte) ((val & 0xf00) >> 8); - rc[destOffset++] = (byte) ((val & 0xf000) >> 12); - } - offset += 1024 - 64; - } - _4bitTexturePages[page] = rc; - } - return rc; - } - - private static byte[] get8BitTexturePage() { - int page = getTexturePage() & 0x1f; - byte[] rc = _8bitTexturePages[page]; - if (rc == null) { - assert !rgb24; - if (debugTexturePage) System.out.println("Generating 8 bit texture page"); - rc = new byte[0x10000]; - int offset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; - int destOffset = 0; - for (int y = 0; y < 256; y++) { - for (int x = 0; x < 128; x++) { - int val = unmakePixel(videoRAM[offset++]); - - rc[destOffset++] = (byte) (val & 0xff); - rc[destOffset++] = (byte) ((val & 0xff00) >> 8); - } - offset += 1024 - 128; - } - _8bitTexturePages[page] = rc; - } - return rc; - } - - public static class Vertex { - public int x, y, u, v, r, g, b; - - public final void init(Vertex vert) { - x = vert.x; - y = vert.y; - u = vert.u; - v = vert.v; - r = vert.r; - g = vert.g; - b = vert.b; - } - - public String toString() { - return "(" + x + "," + y + ")"; - } - } - - public static class Edge { - Vertex current = new Vertex(); - int dx, du, dv, dr, dg, db; - int endy; - } - - public static class LineRenderInfo { - int r0, g0, b0; - int r1, g1, b1; - int color; - } - - public static class PolygonRenderInfo { - int r, g, b; - int u, v; - int[] clut; - int clutOffset; - } - - - - private static class TemplateTriangleRenderer { - private static Vertex[] verts = new Vertex[3]; - private static Edge[] edges = new Edge[]{new Edge(), new Edge(), new Edge()}; - - // when we load the particular renderer class we make these final and - // give them a value... if we make them final at compile time, - // then the java compiler does optimizations on them... - private static int _renderSemiType; - private static int _renderTextureType; - private static boolean _renderBReg; - private static boolean _renderGouraud; - private static boolean _renderCheckMask; - private static boolean _renderSetMask; - private static boolean _renderSolid; - - public static void render(PolygonRenderInfo info, Vertex v0, Vertex v1, Vertex v2) { - // following is for spans - int color = 0; - int spanStart; // in m_ram - int count; // length - int u = 0, v = 0; - int du = 0, dv = 0; - int r = 0, g = 0, b = 0; - int dr = 0, dg = 0, db = 0; - int[] clut = null; - int clutOffset = 0; - byte[] byteTexturePage = null; - int tpOffset = 0; - - int src = 0; - - Edge e1, e2, e3; - - // TODO - loop? second for not writing to display? - // note most setup only done first time - - // want to work relative to draw origin - int clipLeft = m_clipLeft - m_drawOffsetX; - int clipRight = m_clipRight - m_drawOffsetX; - int clipTop = m_clipTop - m_drawOffsetY; - int clipBottom = m_clipBottom - m_drawOffsetY; - - boolean clippedX = false; - if (v0.x < clipLeft && v1.x < clipLeft && v2.x < clipLeft) - return; - if (v0.x >= clipRight && v1.x >= clipRight && v2.x >= clipRight) - return; - if (v0.y < clipTop && v1.y < clipTop && v2.y < clipTop) - return; - if (v0.y >= clipBottom && v1.y >= clipBottom && v2.y >= clipBottom) - return; - if (v0.x < clipLeft || v0.x >= clipRight || - v1.x < clipLeft || v1.x >= clipRight || - v2.x < clipLeft || v2.x >= clipRight) - clippedX = true; - - // y sort into vertex array - if (v0.y > v1.y) { - verts[0] = v1; - verts[1] = v0; - } else { - verts[0] = v0; - verts[1] = v1; - } - if (v2.y < verts[0].y) { - verts[2] = verts[1]; - verts[1] = verts[0]; - verts[0] = v2; - //return; - } else if (v2.y < verts[1].y) { - verts[2] = verts[1]; - verts[1] = v2; - } else { - verts[2] = v2; - } - - //ASSERT( SANITY_CHECK, verts[1].y>verts[0].y, ""); - //ASSERT( SANITY_CHECK, verts[2].y>verts[1].y, ""); - - // check for zero total height - int dy1 = verts[2].y - verts[0].y; - if (dy1 == 0) return; - - if (_renderTextureType != TEXTURE_NONE) { - // for 4 bit - if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { - byteTexturePage = get4BitTexturePage(); - } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { - byteTexturePage = get8BitTexturePage(); - } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { - int page = GPU.getTexturePage(); - tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; - } - clut = info.clut; - clutOffset = info.clutOffset; - } else { - if (!_renderGouraud) { - // need color - color = info.b | (info.g << 8) | (info.r << 16); - } - } - - e1 = edges[0]; - - // e1 is long edge from top to bottom - e1.current.init(verts[0]); - e1.dx = ((verts[2].x - verts[0].x) << 16) / dy1; - if (_renderTextureType != TEXTURE_NONE) { - e1.du = ((verts[2].u - verts[0].u) << 16) / dy1; - e1.dv = ((verts[2].v - verts[0].v) << 16) / dy1; - } - if (_renderGouraud) { - e1.dr = ((verts[2].r - verts[0].r) << 16) / dy1; - e1.dg = ((verts[2].g - verts[0].g) << 16) / dy1; - e1.db = ((verts[2].b - verts[0].b) << 16) / dy1; - } - - // e2 is short edge at top, unless flat topped - int dy2 = verts[1].y - verts[0].y; - if (dy2 != 0) { - e2 = edges[1]; - e2.current.init(verts[0]); - e2.dx = ((verts[1].x - verts[0].x) << 16) / dy2; - if (_renderTextureType != TEXTURE_NONE) { - e2.du = ((verts[1].u - verts[0].u) << 16) / dy2; - e2.dv = ((verts[1].v - verts[0].v) << 16) / dy2; - } - if (_renderGouraud) { - e2.dr = ((verts[1].r - verts[0].r) << 16) / dy2; - e2.dg = ((verts[1].g - verts[0].g) << 16) / dy2; - e2.db = ((verts[1].b - verts[0].b) << 16) / dy2; - } - e2.endy = verts[1].y; - } else { - e2 = null; - } - - // e2 is short edge at bottom, unless flat bottomed - int dy3 = verts[2].y - verts[1].y; - if (dy3 != 0) { - e3 = edges[2]; - e3.current.init(verts[1]); - e3.dx = ((verts[2].x - verts[1].x) << 16) / dy3; - e3.endy = verts[2].y; - if (_renderTextureType != TEXTURE_NONE) { - e3.du = ((verts[2].u - verts[1].u) << 16) / dy3; - e3.dv = ((verts[2].v - verts[1].v) << 16) / dy3; - } - if (_renderGouraud) { - e3.dr = ((verts[2].r - verts[1].r) << 16) / dy3; - e3.dg = ((verts[2].g - verts[1].g) << 16) / dy3; - e3.db = ((verts[2].b - verts[1].b) << 16) / dy3; - } - if (e2 == null) { - // in the case of flat-topped, we replace - // e2 with e3 - e2 = e3; - e3 = null; - } - } else { - e3 = null; - } - - int times = 2; - e1.current.x <<= 16; - e2.current.x <<= 16; - - int crossz = (verts[2].x - verts[0].x) * dy2 - (verts[1].x - verts[0].x) * dy1; - if (crossz == 0) - return; - - if (_renderTextureType != TEXTURE_NONE) { - e1.current.u <<= 16; - e1.current.v <<= 16; - e2.current.u <<= 16; - e2.current.v <<= 16; - long crosszu = (verts[2].u - verts[0].u) * (long) dy2 - (verts[1].u - verts[0].u) * dy1; - du = (int) ((crosszu << 16) / crossz); - long crosszv = (verts[2].v - verts[0].v) * (long) dy2 - (verts[1].v - verts[0].v) * dy1; - dv = (int) ((crosszv << 16) / crossz); - } - if (_renderGouraud) { - e1.current.r <<= 16; - e1.current.g <<= 16; - e1.current.b <<= 16; - e2.current.r <<= 16; - e2.current.g <<= 16; - e2.current.b <<= 16; - long crosszr = (verts[2].r - verts[0].r) * (long) dy2 - (verts[1].r - verts[0].r) * dy1; - dr = (int) ((crosszr << 16) / crossz); - long crosszg = (verts[2].g - verts[0].g) * (long) dy2 - (verts[1].g - verts[0].g) * dy1; - dg = (int) ((crosszg << 16) / crossz); - long crosszb = (verts[2].b - verts[0].b) * (long) dy2 - (verts[1].b - verts[0].b) * dy1; - db = (int) ((crosszb << 16) / crossz); - } - if (e3 != null) { - e3.current.x <<= 16; - if (_renderTextureType != TEXTURE_NONE) { - e3.current.u <<= 16; - e3.current.v <<= 16; - } - if (_renderGouraud) { - e3.current.r <<= 16; - e3.current.g <<= 16; - e3.current.b <<= 16; - } - } - - - do { - Edge el, er; - if (e1.current.x < e2.current.x) { - el = e1; - er = e2; - } else if (e1.current.x > e2.current.x) { - er = e1; - el = e2; - } else if ((e1.current.x + e1.dx) < (e2.current.x + e2.dx)) { - el = e1; - er = e2; - } else { - er = e1; - el = e2; - } - - if (e2.endy > clipBottom) { - e2.endy = clipBottom; - } - - if (e2.current.y < clipTop) { - int skipY; - if (e2.endy < clipTop) - skipY = e2.endy - e2.current.y; - else - skipY = clipTop - e2.current.y; - e1.current.x += e1.dx * skipY; - e2.current.x += e2.dx * skipY; - e2.current.y += skipY; - if (_renderTextureType != TEXTURE_NONE) { - e1.current.u += e1.du * skipY; - e1.current.v += e1.dv * skipY; - e2.current.u += e2.du * skipY; - e2.current.v += e2.dv * skipY; - } - if (_renderGouraud) { - e1.current.r += e1.dr * skipY; - e1.current.g += e1.dg * skipY; - e1.current.b += e1.db * skipY; - e2.current.r += e2.dr * skipY; - e2.current.g += e2.dg * skipY; - e2.current.b += e2.db * skipY; - } - } - int base = m_drawOffsetX + (e2.current.y + m_drawOffsetY) * 1024; - if (!clippedX) { - while (e2.current.y < e2.endy) { - int left = el.current.x >> 16; - int right = er.current.x >> 16; - - count = right - left; - if (count > 0) { - spanStart = base + left; - if (_renderTextureType != TEXTURE_NONE) { - u = el.current.u; - v = el.current.v; - } - if (_renderGouraud) { - r = el.current.r; - g = el.current.g; - b = el.current.b; - } - - // --- configure span - - //if (_renderTextureType == TEXTURE_NONE && !_renderGouraud) { - // color = color; - //} - - int target = spanStart + count; - int i = spanStart; - - for (; i < target; i++) { - // get source pixel - if (_renderTextureType == TEXTURE_NONE) { - if (!_renderGouraud) { - src = color; - } else { - src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); - } - } else if (_renderTextureType == TEXTURE_4BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BIT) { - int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); - src = videoRAM[tpOffset + offset]; - } else if (_renderTextureType == TEXTURE_4BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BITW) { - int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); - src = videoRAM[tpOffset + offset]; - } - - if (_renderBReg) { - int bb = (src & 0xff); - int gg = ((src >> 8) & 0xff); - int rr = ((src >> 16) & 0xff); - int mask = ((src & 0xffffff) == 0) ? 0 : 1; - rr = (rr * (r >> 16)) >> 7; - if (rr > 255) rr = 255; - gg = (gg * (g >> 16)) >> 7; - if (gg > 255) gg = 255; - bb = (bb * (b >> 16)) >> 7; - if (bb > 255) bb = 255; - src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; - //src = (src&0x01000000)|((b>>16)<<16)|((g>>16)<<8)|(r>>16)|mask; - } - - if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { - if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { - } else { - if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { - // semi transparency - int dest = videoRAM[i]; - int destB = dest & 0xff; - int destG = (dest >> 8) & 0xff; - int destR = (dest >> 16) & 0xff; - int srcB = src & 0xff; - int srcG = (src >> 8) & 0xff; - int srcR = (src >> 16) & 0xff; - int tmpR, tmpG, tmpB; - - if (_renderSemiType == SEMI_5P5) { - tmpR = (srcR + destR) >> 1; - tmpG = (srcG + destG) >> 1; - tmpB = (srcB + destB) >> 1; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P10) { - tmpR = srcR + destR; - tmpG = srcG + destG; - tmpB = srcB + destB; - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10M10) { - tmpR = destR - srcR; - tmpG = destG - srcG; - tmpB = destB - srcB; - if (tmpR < 0) tmpR = 0; - if (tmpG < 0) tmpG = 0; - if (tmpB < 0) tmpB = 0; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P25) { - tmpR = destR + (srcR >> 2); - tmpG = destG + (srcG >> 2); - tmpB = destB + (srcB >> 2); - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } - } - - // mask set - if (_renderSetMask) { - src |= 0x01000000; - } - videoRAM[i] = src; - } - } - if (_renderTextureType != TEXTURE_NONE) { - u += du; - v += dv; - } - if (_renderGouraud) { - r += dr; - g += dg; - b += db; - } - } - - // --- end span - } - e1.current.x += e1.dx; - e2.current.x += e2.dx; - if (_renderTextureType != TEXTURE_NONE) { - e1.current.u += e1.du; - e1.current.v += e1.dv; - e2.current.u += e2.du; - e2.current.v += e2.dv; - } - if (_renderGouraud) { - e1.current.r += e1.dr; - e1.current.g += e1.dg; - e1.current.b += e1.db; - e2.current.r += e2.dr; - e2.current.g += e2.dg; - e2.current.b += e2.db; - } - e2.current.y++; - base += 1024; - } - } else { - while (e2.current.y < e2.endy) { - int left = el.current.x >> 16; - int right = er.current.x >> 16; - - if (right > clipRight) - right = clipRight; - if (_renderTextureType != TEXTURE_NONE) { - u = el.current.u; - v = el.current.v; - } - if (_renderGouraud) { - r = el.current.r; - g = el.current.g; - b = el.current.b; - } - if (left < clipLeft) { - int skipX = clipLeft - left; - left = clipLeft; - if (_renderTextureType != TEXTURE_NONE) { - u += du * skipX; - v += dv * skipX; - } - if (_renderGouraud) { - r += dr * skipX; - g += dg * skipX; - b += db * skipX; - } - } - count = right - left; - if (count > 0) { - spanStart = base + left; - - // --- configure span - - //if (_renderTextureType == TEXTURE_NONE && !_renderGouraud) { - // color = color; - //} - - int target = spanStart + count; - int i = spanStart; - - for (; i < target; i++) { - // get source pixel - if (_renderTextureType == TEXTURE_NONE) { - if (!_renderGouraud) { - src = color; - } else { - src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); - } - } else if (_renderTextureType == TEXTURE_4BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BIT) { - int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); - src = videoRAM[tpOffset + offset]; - } else if (_renderTextureType == TEXTURE_4BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BITW) { - int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); - src = videoRAM[tpOffset + offset]; - } - - if (_renderBReg) { - int bb = (src & 0xff); - int gg = ((src >> 8) & 0xff); - int rr = ((src >> 16) & 0xff); - int mask = ((src & 0xffffff) == 0) ? 0 : 1; - rr = (rr * (r >> 16)) >> 7; - if (rr > 255) rr = 255; - gg = (gg * (g >> 16)) >> 7; - if (gg > 255) gg = 255; - bb = (bb * (b >> 16)) >> 7; - if (bb > 255) bb = 255; - src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; - } - - if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { - if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { - } else { - if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { - // semi transparency - int dest = videoRAM[i]; - int destB = dest & 0xff; - int destG = (dest >> 8) & 0xff; - int destR = (dest >> 16) & 0xff; - int srcB = src & 0xff; - int srcG = (src >> 8) & 0xff; - int srcR = (src >> 16) & 0xff; - int tmpR, tmpG, tmpB; - - if (_renderSemiType == SEMI_5P5) { - tmpR = (srcR + destR) >> 1; - tmpG = (srcG + destG) >> 1; - tmpB = (srcB + destB) >> 1; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P10) { - tmpR = srcR + destR; - tmpG = srcG + destG; - tmpB = srcB + destB; - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10M10) { - tmpR = destR - srcR; - tmpG = destG - srcG; - tmpB = destB - srcB; - if (tmpR < 0) tmpR = 0; - if (tmpG < 0) tmpG = 0; - if (tmpB < 0) tmpB = 0; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P25) { - tmpR = destR + (srcR >> 2); - tmpG = destG + (srcG >> 2); - tmpB = destB + (srcB >> 2); - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } - } - - // mask set - if (_renderSetMask) { - src |= 0x01000000; - } - videoRAM[i] = src; - } - } - if (_renderTextureType != TEXTURE_NONE) { - u += du; - v += dv; - } - if (_renderGouraud) { - r += dr; - g += dg; - b += db; - } - } - - // --- end span - - } - e1.current.x += e1.dx; - e2.current.x += e2.dx; - if (_renderTextureType != TEXTURE_NONE) { - e1.current.u += e1.du; - e1.current.v += e1.dv; - e2.current.u += e2.du; - e2.current.v += e2.dv; - } - if (_renderGouraud) { - e1.current.r += e1.dr; - e1.current.g += e1.dg; - e1.current.b += e1.db; - e2.current.r += e2.dr; - e2.current.g += e2.dg; - e2.current.b += e2.db; - } - e2.current.y++; - base += 1024; - } - ; - } - - e2 = e3; - times--; - } while (times != 0 && e2 != null); - } - } - - private static class TemplateRectangleRenderer { - private static Vertex[] verts = new Vertex[4]; - - // when we load the particular renderer class we make these final and - // give them a value... if we make them final at compile time, - // then the java compiler does optimizations on them... - private static int _renderSemiType; - private static int _renderTextureType; - private static boolean _renderBReg; - private static boolean _renderGouraud; - private static boolean _renderCheckMask; - private static boolean _renderSetMask; - private static boolean _renderSolid; - - public static boolean render(PolygonRenderInfo info, Vertex ve0, Vertex ve1, Vertex ve2, Vertex ve3) { - // following is for spans - int color = 0; - int spanStart; // in m_ram - int count; // length - - int u = 0, v = 0; - int u0 = 0, v0 = 0; - int du = 0, dv = 0; - int du0 = 0, dv0 = 0; - - int r = 0, g = 0, b = 0; - int r0 = 0, g0 = 0, b0 = 0; - int dr = 0, dg = 0, db = 0; - int dr0 = 0, dg0 = 0, db0 = 0; - - int[] clut = null; - int clutOffset = 0; - byte[] byteTexturePage = null; - int tpOffset = 0; - - int src = 0; - - verts[0] = ve0; - verts[1] = ve1; - verts[2] = ve2; - verts[3] = ve3; - - Vertex tmp; - - // sort to 0 - 1 - // | | - // 2 - 3 - if (verts[0].x == verts[1].x) { - tmp = verts[1]; - verts[1] = verts[2]; - verts[2] = tmp; - } - if (verts[0].x > verts[1].x) { - tmp = verts[1]; - verts[1] = verts[0]; - verts[0] = tmp; - } - if (verts[2].x > verts[3].x) { - tmp = verts[2]; - verts[2] = verts[3]; - verts[3] = tmp; - } - if (verts[0].y > verts[2].y) { - tmp = verts[0]; - verts[0] = verts[2]; - verts[2] = tmp; - } - if (verts[1].y > verts[3].y) { - tmp = verts[1]; - verts[1] = verts[3]; - verts[3] = tmp; - } - - int x = verts[0].x; - int y = verts[0].y; - int ww = verts[1].x - x; - int hh = verts[2].y - y; - - if (ww <= 0 || hh <= 0) - return true; - - int w = ww; - int h = hh; - - // TODO - loop? second for not writing to display? - // note most setup only done first time - - // want to work relative to draw origin - int clipLeft = m_clipLeft - m_drawOffsetX; - int clipRight = m_clipRight - m_drawOffsetX; - int clipTop = m_clipTop - m_drawOffsetY; - int clipBottom = m_clipBottom - m_drawOffsetY; - - if ((x + w) >= clipRight) - w = clipRight - x; - if ((y + h) >= clipBottom) - h = clipBottom - y; - - int skipX = 0; - int skipY = 0; - - if (x < clipLeft) { - skipX = clipLeft - x; - x = clipLeft; - w -= skipX; - } - if (y < clipTop) { - skipY = clipTop - y; - y = clipTop; - h -= skipY; - } - - if (w <= 0 || h <= 0) - return true; - - if (_renderTextureType != TEXTURE_NONE) { - // check for non-linear - if ((verts[1].u - verts[0].u) != (verts[3].u - verts[2].u) || - (verts[1].v - verts[0].v) != (verts[3].v - verts[2].v) || - (verts[2].u - verts[0].u) != (verts[3].u - verts[1].u) || - (verts[2].v - verts[0].v) != (verts[3].v - verts[1].v)) { - //System.out.println("non-linear quad texture!"); - return false; - } - u0 = verts[0].u << 16; - v0 = verts[0].v << 16; - du = ((verts[1].u << 16) - u0) / ww; - dv = ((verts[1].v << 16) - v0) / ww; - du0 = ((verts[2].u << 16) - u0) / hh; - dv0 = ((verts[2].v << 16) - v0) / hh; - - if (skipX != 0) { - u0 += skipX * du; - v0 += skipX + dv; - } - if (skipY != 0) { - u0 += skipY * du0; - v0 += skipY * dv0; - } - - // for 4 bit - if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { - byteTexturePage = get4BitTexturePage(); - } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { - byteTexturePage = get8BitTexturePage(); - } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { - int page = GPU.getTexturePage(); - tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; - } - clut = info.clut; - clutOffset = info.clutOffset; - if (_renderBReg) { - r = info.r; - g = info.g; - b = info.b; - } - } else { - color = info.b | (info.g << 8) | (info.r << 16); - } - - if (_renderGouraud) { - // check for non-linear - if ((verts[1].r - verts[0].r) != (verts[3].r - verts[2].r) || - (verts[1].g - verts[0].g) != (verts[3].g - verts[2].g) || - (verts[1].b - verts[0].b) != (verts[3].b - verts[2].b) || - (verts[2].r - verts[0].r) != (verts[3].r - verts[1].r) || - (verts[2].g - verts[0].g) != (verts[3].g - verts[1].g) || - (verts[2].b - verts[0].b) != (verts[3].b - verts[1].b)) { - //System.out.println("non-linear quad gouraud!"); - return false; - } - r0 = verts[0].r << 16; - g0 = verts[0].g << 16; - b0 = verts[0].b << 16; - - dr = ((verts[1].r << 16) - r0) / ww; - dg = ((verts[1].g << 16) - g0) / ww; - db = ((verts[1].b << 16) - b0) / ww; - dr0 = ((verts[2].r << 16) - r0) / hh; - dg0 = ((verts[2].g << 16) - g0) / hh; - db0 = ((verts[2].b << 16) - b0) / hh; - - if (skipX != 0) { - r0 += skipX * dr; - g0 += skipX + dg; - b0 += skipX + db; - } - if (skipY != 0) { - r0 += skipY * dr0; - g0 += skipY * dg0; - b0 += skipY * db0; - } - } - - int base = m_drawOffsetX + x + (y + m_drawOffsetY) * 1024; - outertmp: - for (; h > 0; h--) { - if (_renderTextureType != TEXTURE_NONE) { - u = u0; - v = v0; - } - if (_renderGouraud) { - r = r0; - g = g0; - b = b0; - } - for (int i = base; i < (base + w); i++) { - // get source pixel - if (_renderTextureType == TEXTURE_NONE) { - if (!_renderGouraud) { - src = color; - } else { - src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); - } - } else if (_renderTextureType == TEXTURE_4BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BIT) { - int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BIT) { - int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); - src = videoRAM[tpOffset + offset]; - } else if (_renderTextureType == TEXTURE_4BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BITW) { - int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BITW) { - int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); - src = videoRAM[tpOffset + offset]; - } - - if (_renderBReg) { - int bb = (src & 0xff); - int gg = ((src >> 8) & 0xff); - int rr = ((src >> 16) & 0xff); - int mask = ((src & 0xffffff) == 0) ? 0 : 1; - rr = (rr * (r >> 16)) >> 7; - if (rr > 255) rr = 255; - gg = (gg * (g >> 16)) >> 7; - if (gg > 255) gg = 255; - bb = (bb * (b >> 16)) >> 7; - if (bb > 255) bb = 255; - src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; - } - - if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { - if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { - } else { - if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { - // semi transparency - int dest = videoRAM[i]; - int destB = dest & 0xff; - int destG = (dest >> 8) & 0xff; - int destR = (dest >> 16) & 0xff; - int srcB = src & 0xff; - int srcG = (src >> 8) & 0xff; - int srcR = (src >> 16) & 0xff; - int tmpR, tmpG, tmpB; - - if (_renderSemiType == SEMI_5P5) { - tmpR = (srcR + destR) >> 1; - tmpG = (srcG + destG) >> 1; - tmpB = (srcB + destB) >> 1; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P10) { - tmpR = srcR + destR; - tmpG = srcG + destG; - tmpB = srcB + destB; - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10M10) { - tmpR = destR - srcR; - tmpG = destG - srcG; - tmpB = destB - srcB; - if (tmpR < 0) tmpR = 0; - if (tmpG < 0) tmpG = 0; - if (tmpB < 0) tmpB = 0; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P25) { - tmpR = destR + (srcR >> 2); - tmpG = destG + (srcG >> 2); - tmpB = destB + (srcB >> 2); - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } - } - - // mask set - if (_renderSetMask) { - src |= 0x01000000; - } - videoRAM[i] = src; - } - } - if (_renderTextureType != TEXTURE_NONE) { - u += du; - v += dv; - } - if (_renderGouraud) { - r += dr; - g += dg; - b += db; - } - } - base += 1024; - if (_renderTextureType != TEXTURE_NONE) { - u0 += du0; - v0 += dv0; - } - if (_renderGouraud) { - r0 += dr0; - g0 += dg0; - b0 += db0; - } - } - return true; - } - } - - private static class TemplateSpriteRenderer { - // when we load the particular renderer class we make these final and - // give them a value... if we make them final at compile time, - // then the java compiler does optimizations on them... - private static int _renderSemiType; - private static int _renderTextureType; - private static boolean _renderBReg; - private static boolean _renderGouraud; - private static boolean _renderCheckMask; - private static boolean _renderSetMask; - private static boolean _renderSolid; - - - public static void render(PolygonRenderInfo info, int x, int y, int w, int h) { -// System.out.println("Sprite renderer "+x+","+y+" "+w+","+h); - // following is for spans - int color = 0; - int u0 = 0, v = 0; - int r = 0, g = 0, b = 0; - int[] clut = null; - int clutOffset = 0; - byte[] byteTexturePage = null; - int tpOffset = 0; - - int src = 0; - - // TODO - loop? second for not writing to display? - // note most setup only done first time - - // want to work relative to draw origin - int clipLeft = m_clipLeft - m_drawOffsetX; - int clipRight = m_clipRight - m_drawOffsetX; - int clipTop = m_clipTop - m_drawOffsetY; - int clipBottom = m_clipBottom - m_drawOffsetY; - - if ((x + w) >= clipRight) - w = clipRight - x; - if ((y + h) >= clipBottom) - h = clipBottom - y; - - int skipX = 0; - int skipY = 0; - - if (x < clipLeft) { - skipX = clipLeft - x; - x = clipLeft; - w -= skipX; - } - if (y < clipTop) { - skipY = clipTop - y; - y = clipTop; - h -= skipY; - } - - if (w <= 0 || h <= 0) - return; - - if (_renderTextureType != TEXTURE_NONE) { - // shifted to avoid shifts in loop - u0 = info.u + skipX; - v = (info.v + skipY) << 8; - // for 4 bit - if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { - byteTexturePage = get4BitTexturePage(); - } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { - byteTexturePage = get8BitTexturePage(); - } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { - int page = GPU.getTexturePage(); - tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; - } - clut = info.clut; - clutOffset = info.clutOffset; - if (_renderBReg) { - r = info.r; - g = info.g; - b = info.b; - } - } else { - color = info.b | (info.g << 8) | (info.r << 16); - } - - int base = m_drawOffsetX + x + (y + m_drawOffsetY) * 1024; - for (; h > 0; h--) { - int u = u0; - for (int i = base; i < (base + w); i++) { - //System.out.println(MiscUtil.toHex(u,4)+" "+MiscUtil.toHex(v,4)); - // get source pixel - if (_renderTextureType == TEXTURE_NONE) { - src = color; - } else if (_renderTextureType == TEXTURE_4BIT) { - int offset = (u & 0xff) | (v & 0xff00); - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BIT) { - int offset = (u & 0xff) | (v & 0xff00); - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BIT) { - int offset = (u & 0xff) | ((v & 0xff00) << 2); - src = videoRAM[tpOffset + offset]; - } else if (_renderTextureType == TEXTURE_4BITW) { - int offset = (u & 0x07) | (v & 0x0700) | twuLookup[(u >> 3) & 0x1f] | twvLookup[(v >> 11) & 0x1f]; - src = clut[clutOffset + byteTexturePage[offset]]; - } else if (_renderTextureType == TEXTURE_8BITW) { - int offset = (u & 0x07) | (v & 0x0700) | twuLookup[(u >> 3) & 0x1f] | twvLookup[(v >> 11) & 0x1f]; - src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; - } else if (_renderTextureType == TEXTURE_16BITW) { - int offset = (u & 0x07) | twuLookup[(u >> 3) & 0x1f] | (((v & 0x0700) | twvLookup[(v >> 11) & 0x1f]) << 2); - src = videoRAM[tpOffset + offset]; - } - - if (_renderBReg) { - int bb = (src & 0xff); - int gg = ((src >> 8) & 0xff); - int rr = ((src >> 16) & 0xff); - int mask = ((src & 0xffffff) == 0) ? 0 : 1; - rr = (rr * (r >> 16)) >> 7; - if (rr > 255) rr = 255; - gg = (gg * (g >> 16)) >> 7; - if (gg > 255) gg = 255; - bb = (bb * (b >> 16)) >> 7; - if (bb > 255) bb = 255; - src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; - //src = (src&0x01000000)|((b>>16)<<16)|((g>>16)<<8)|(r>>16)|mask; - } - if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { - if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { - } else { - if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { - // semi transparency - int dest = videoRAM[i]; - int destB = dest & 0xff; - int destG = (dest >> 8) & 0xff; - int destR = (dest >> 16) & 0xff; - int srcB = src & 0xff; - int srcG = (src >> 8) & 0xff; - int srcR = (src >> 16) & 0xff; - int tmpR, tmpG, tmpB; - - if (_renderSemiType == SEMI_5P5) { - tmpR = (srcR + destR) >> 1; - tmpG = (srcG + destG) >> 1; - tmpB = (srcB + destB) >> 1; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P10) { - tmpR = srcR + destR; - tmpG = srcG + destG; - tmpB = srcB + destB; - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10M10) { - tmpR = destR - srcR; - tmpG = destG - srcG; - tmpB = destB - srcB; - if (tmpR < 0) tmpR = 0; - if (tmpG < 0) tmpG = 0; - if (tmpB < 0) tmpB = 0; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P25) { - tmpR = destR + (srcR >> 2); - tmpG = destG + (srcG >> 2); - tmpB = destB + (srcB >> 2); - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } - } - - // mask set - if (_renderSetMask) { - src |= 0x01000000; - } - videoRAM[i] = src; - } - } - if (_renderTextureType != TEXTURE_NONE) { - u++; - } - } - base += 1024; - if (_renderTextureType != TEXTURE_NONE) { - v += 256; - } - } - } - } - - private static class TemplateLineRenderer { - // when we load the particular renderer class we make these final and - // give them a value... if we make them final at compile time, - // then the java compiler does optimizations on them... - private static int _renderSemiType; - private static int _renderTextureType; - private static boolean _renderBReg; - private static boolean _renderGouraud; - private static boolean _renderCheckMask; - private static boolean _renderSetMask; - private static boolean _renderSolid; - - public static void render(LineRenderInfo info, Vertex v0, Vertex v1) { - int clipLeft = m_clipLeft - m_drawOffsetX; - int clipRight = m_clipRight - m_drawOffsetX; - int clipTop = m_clipTop - m_drawOffsetY; - int clipBottom = m_clipBottom - m_drawOffsetY; - - int p0codes = 0; - int p1codes = 0; - - if (v0.x < clipLeft) p0codes |= 1; - if (v0.x >= clipRight) p0codes |= 2; - if (v0.y < clipTop) p0codes |= 4; - if (v0.y >= clipBottom) p0codes |= 8; - - if (v1.x < clipLeft) p1codes |= 1; - if (v1.x >= clipRight) p1codes |= 2; - if (v1.y < clipTop) p1codes |= 4; - if (v1.y >= clipBottom) p1codes |= 8; - - // trivial reject - if (0 != (p0codes & p1codes)) - return; - - // @@@ TMP - if (0 != (p0codes | p1codes)) - return; - - // TODO other code checks - - int color = 0; - int r = 0; - int g = 0; - int b = 0; - - if (!_renderGouraud) { - color = info.color; - } else { - r = info.r0 << 16; - g = info.g0 << 16; - b = info.b0 << 16; - } - - // todo clip - int dx = v1.x - v0.x; - int adx = dx > 0 ? dx : -dx; - int dy = v1.y - v0.y; - int ady = dy > 0 ? dy : -dy; - - if (adx == 0 && ady == 0) - return; - - int count; - int minor; - int dpMajor; - int dpMinor; - int dr = 0; - int dg = 0; - int db = 0; - if (adx > ady) { - // x is major - count = adx;//+1; // check the +1 - minor = ady; - dpMajor = dx > 0 ? 1 : -1; - dpMinor = dy > 0 ? 1024 : -1024; - if (_renderGouraud) { - dr = ((info.r1 - info.r0) << 16) / adx; - dg = ((info.g1 - info.g0) << 16) / adx; - db = ((info.b1 - info.b0) << 16) / adx; - } - } else { - // y is major - count = ady;//+1; // check the +1 - minor = adx; - dpMajor = dy > 0 ? 1024 : -1024; - dpMinor = dx > 0 ? 1 : -1; - if (_renderGouraud) { - dr = ((info.r1 - info.r0) << 16) / ady; - dg = ((info.g1 - info.g0) << 16) / ady; - db = ((info.b1 - info.b0) << 16) / ady; - } - } - - // --- configure span - - int i = m_drawOffsetX + v0.x + (v0.y + m_drawOffsetY) * 1024; - int src = color; - int line = count / 2; - int j = count; - - for (; j > 0; j--) { - if (_renderGouraud) { - src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); - } - if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { - } else { - if (_renderSemiType != SEMI_NONE) { - // semi transparency - int dest = videoRAM[i]; - int destB = dest & 0xff; - int destG = (dest >> 8) & 0xff; - int destR = (dest >> 16) & 0xff; - int srcB = src & 0xff; - int srcG = (src >> 8) & 0xff; - int srcR = (src >> 16) & 0xff; - int tmpR, tmpG, tmpB; - - if (_renderSemiType == SEMI_5P5) { - tmpR = (srcR + destR) >> 1; - tmpG = (srcG + destG) >> 1; - tmpB = (srcB + destB) >> 1; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P10) { - tmpR = srcR + destR; - tmpG = srcG + destG; - tmpB = srcB + destB; - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10M10) { - tmpR = destR - srcR; - tmpG = destG - srcG; - tmpB = destB - srcB; - if (tmpR < 0) tmpR = 0; - if (tmpG < 0) tmpG = 0; - if (tmpB < 0) tmpB = 0; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } else if (_renderSemiType == SEMI_10P25) { - tmpR = destR + (srcR >> 2); - tmpG = destG + (srcG >> 2); - tmpB = destB + (srcB >> 2); - if (tmpR > 255) tmpR = 255; - if (tmpG > 255) tmpG = 255; - if (tmpB > 255) tmpB = 255; - src = (tmpR << 16) | (tmpG << 8) | tmpB; - } - } - - // mask set - if (_renderSetMask) { - src |= 0x01000000; - } - videoRAM[i] = src; - } - i += dpMajor; - line -= minor; - if (line < 0) { - line += count; - i += dpMinor; - } - - if (_renderGouraud) { - r += dr; - g += dg; - b += db; - } - - } - - // --- end span - - } - } - - private static class GPUDRouter { - public static int invoke(int[] data, int offset, int size) { - if (dumpGPUD) { - //System.out.println("GPUD Invoke "+MiscUtil.toHex(m_gpudCommand,8)); - } - - if (m_gpudCommand > 2 && m_gpudCommand < 0x80) { - // todo; dirty based on clip rect - } - - switch (m_gpudCommand & 0xe0) { - case 0x20: - // texture or semi; we should make sure were 16bit - if (0 != (m_gpudCommand & 6)) setVRAMFormat(false); - switch (m_gpudCommand) { - case 0x20: - return gpud3PointFlat(data, offset, size); - case 0x21: - return gpud3PointFlat(data, offset, size); - case 0x22: - return gpud3PointFlatSemi(data, offset, size); - case 0x23: - return gpud3PointFlatSemi(data, offset, size); - - case 0x24: - return gpud3PointTexture(data, offset, size); - case 0x25: - return gpud3PointTexture(data, offset, size); - case 0x26: - return gpud3PointTextureSemi(data, offset, size); - case 0x27: - return gpud3PointTextureSemi(data, offset, size); - - case 0x28: - return gpud4PointFlat(data, offset, size); - case 0x29: - return gpud4PointFlat(data, offset, size); - case 0x2a: - return gpud4PointFlatSemi(data, offset, size); - case 0x2b: - return gpud4PointFlatSemi(data, offset, size); - - case 0x2c: - return gpud4PointTexture(data, offset, size); - case 0x2d: - return gpud4PointTexture(data, offset, size); - case 0x2e: - return gpud4PointTextureSemi(data, offset, size); - case 0x2f: - return gpud4PointTextureSemi(data, offset, size); - - case 0x30: - return gpud3PointGouraud(data, offset, size); - case 0x31: - return gpud3PointGouraud(data, offset, size); - case 0x32: - return gpud3PointGouraudSemi(data, offset, size); - case 0x33: - return gpud3PointGouraudSemi(data, offset, size); - - case 0x34: - return gpud3PointTextureGouraud(data, offset, size); - case 0x35: - return gpud3PointTextureGouraud(data, offset, size); - case 0x36: - return gpud3PointTextureGouraudSemi(data, offset, size); - case 0x37: - return gpud3PointTextureGouraudSemi(data, offset, size); - - case 0x38: - return gpud4PointGouraud(data, offset, size); - case 0x39: - return gpud4PointGouraud(data, offset, size); - case 0x3a: - return gpud4PointGouraudSemi(data, offset, size); - case 0x3b: - return gpud4PointGouraudSemi(data, offset, size); - - case 0x3c: - return gpud4PointTextureGouraud(data, offset, size); - case 0x3d: - return gpud4PointTextureGouraud(data, offset, size); - case 0x3e: - return gpud4PointTextureGouraudSemi(data, offset, size); - case 0x3f: - return gpud4PointTextureGouraudSemi(data, offset, size); - } - break; - case 0x40: - if (0 == (m_gpudCommand & 2)) { - // nom-semi - if (0 == (m_gpudCommand & 8)) { - // non-poly - if (0 == (m_gpudCommand & 0x10)) { - // non-gouraud - return gpudLine(data, offset, size); - } else { - // gouraud - return gpudLineGouraud(data, offset, size); - } - } else { - // poly - if (0 == (m_gpudCommand & 0x10)) { - // non-gouraud - return gpudPolyLine(data, offset, size); - } else { - // gouraud - return gpudPolyLineGouraud(data, offset, size); - } - } - } else { - // semi - setVRAMFormat(false); - if (0 == (m_gpudCommand & 8)) { - // non-poly - if (0 == (m_gpudCommand & 0x10)) { - // non-gouraud - return gpudLineSemi(data, offset, size); - } else { - // gouraud - return gpudLineGouraudSemi(data, offset, size); - } - } else { - // poly - if (0 == (m_gpudCommand & 0x10)) { - // non-gouraud - return gpudPolyLineSemi(data, offset, size); - } else { - // gouraud - return gpudPolyLineGouraudSemi(data, offset, size); - } - } - } - case 0x60: - // texture or semi; we should make sure were 16bit - if (0 != (m_gpudCommand & 6)) setVRAMFormat(false); - switch (m_gpudCommand) { - case 0x60: - return gpudRectangle(data, offset, size); - case 0x61: - return gpudRectangle(data, offset, size); - case 0x62: - return gpudRectangleSemi(data, offset, size); - case 0x63: - return gpudRectangleSemi(data, offset, size); - - case 0x64: - return gpudSprite(data, offset, size); - case 0x65: - return gpudSprite(data, offset, size); - case 0x66: - return gpudSpriteSemi(data, offset, size); - case 0x67: - return gpudSpriteSemi(data, offset, size); - - case 0x68: - return gpudRectangle1x1(data, offset, size); - case 0x69: - return gpudRectangle1x1(data, offset, size); - case 0x6a: - return gpudRectangle1x1Semi(data, offset, size); - case 0x6b: - return gpudRectangle1x1Semi(data, offset, size); - - case 0x6c: - return gpudSprite1x1(data, offset, size); - case 0x6d: - return gpudSprite1x1(data, offset, size); - case 0x6e: - return gpudSprite1x1Semi(data, offset, size); - case 0x6f: - return gpudSprite1x1Semi(data, offset, size); - - case 0x70: - return gpudRectangle8x8(data, offset, size); - case 0x71: - return gpudRectangle8x8(data, offset, size); - case 0x72: - return gpudRectangle8x8Semi(data, offset, size); - case 0x73: - return gpudRectangle8x8Semi(data, offset, size); - - case 0x74: - return gpudSprite8x8(data, offset, size); - case 0x75: - return gpudSprite8x8(data, offset, size); - case 0x76: - return gpudSprite8x8Semi(data, offset, size); - case 0x77: - return gpudSprite8x8Semi(data, offset, size); - - case 0x78: - return gpudRectangle16x16(data, offset, size); - case 0x79: - return gpudRectangle16x16(data, offset, size); - case 0x7a: - return gpudRectangle16x16Semi(data, offset, size); - case 0x7b: - return gpudRectangle16x16Semi(data, offset, size); - - case 0x7c: - return gpudSprite16x16(data, offset, size); - case 0x7d: - return gpudSprite16x16(data, offset, size); - case 0x7e: - return gpudSprite16x16Semi(data, offset, size); - case 0x7f: - return gpudSprite16x16Semi(data, offset, size); - } - break; - default: - switch (m_gpudCommand) { - case 0x01: - return gpudCacheFlush(data, offset, size); - case 0x02: - return gpudClear(data, offset, size); - case 0x80: - return gpudVRAMtoVRAM(data, offset, size); - case 0xa0: - return gpudMemToVRAM(data, offset, size); - case 0xc0: - setVRAMFormat(false); - return gpudVRAMToMem(data, offset, size); - case 0xe1: - return gpudSetDrawMode(data, offset, size); - case 0xe2: - return gpudSetTextureWindow(data, offset, size); - case 0xe3: - return gpudSetClipTopLeft(data, offset, size); - case 0xe4: - return gpudSetClipBottomRight(data, offset, size); - case 0xe5: - return gpudSetDrawingOffset(data, offset, size); - case 0xe6: - return gpudSetMaskMode(data, offset, size); - } - break; - } - return 1; - } - } - - public static int gpudCacheFlush(int[] data, int offset, int size) { - //System.out.println("GPUD CacheFlush"); - return 0; - } - - public static int gpudClear(int[] data, int offset, int size) { - - int x = (data[offset + 1] << 20) >> 20; - int y = (data[offset + 1] << 4) >> 20; - int w = data[offset + 2] & 0xffff; - int h = data[offset + 2] >> 16; - int r = data[offset] & 0xff; - int g = (data[offset] >> 8) & 0xff; - int b = (data[offset] >> 16) & 0xff; - - //LOG7P( GPU_COMMAND, "gpudClear (%d,%d,%u,%u), color (%02x,%02x,%02x)\n",x, y, w, h, r, g, b); - if (dumpGPUD) System.out.println("GPUD clear " + x + "," + y + " " + w + "," + h + " " + colorString(r, g, b)); - - if (x < 0) { - w += x; - x = 0; - } - if (y < 0) { - h += y; - y = 0; - } - if ((x + w) > 1024) { - w = 1024 - x; - } - if ((y + h) > 512) { - h = 512 - y; - } - - int base = x + y * 1024; - int color = b | (g << 8) | (r << 16); - for (; h > 0; h--) { - for (int i = base; i < base + w; i++) { - videoRAM[i] = color; - } - base += 1024; - } - return 0; - } - - public static int gpud3PointFlat(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - - v2.x = (data[offset + 3] << 20) >> 20; - v2.y = (data[offset + 3] << 4) >> 20; - - m_polygonInfo.r = data[offset] & 0xff; - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointFlat"); - } - - switch (getMaskModes()) { - case 0: - GPUGenerated._T000000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T000100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T000010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T000110.render(m_polygonInfo, v0, v1, v2); - break; - } - return 0; - } - - public static int gpud3PointFlatSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - - v2.x = (data[offset + 3] << 20) >> 20; - v2.y = (data[offset + 3] << 4) >> 20; - - m_polygonInfo.r = data[offset] & 0xff; - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointFlatSemi"); - } - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T001000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T002000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T003000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T004000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T001100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T002100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T003100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T004100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T001010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T002010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T003010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T004010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T001110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T002110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T003110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T004110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - return 0; - } - - private static Vertex m_v0 = new Vertex(); - private static Vertex m_v1 = new Vertex(); - private static Vertex m_v2 = new Vertex(); - private static Vertex m_v3 = new Vertex(); - - private static void drawModePacket(int packet) { - drawMode = (drawMode & ~0x1ff) | ((packet >> 16) & 0x1ff); - } - - private static PolygonRenderInfo m_polygonInfo = new PolygonRenderInfo(); - private static LineRenderInfo m_lineInfo = new LineRenderInfo(); - - public static int gpud3PointTexture(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - v1.u = data[offset + 4] & 0xff; - v1.v = (data[offset + 4] >> 8) & 0xff; - - drawModePacket(data[offset + 4]); - - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - v2.u = data[offset + 6] & 0xff; - v2.v = (data[offset + 6] >> 8) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointTexture"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T400001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T400101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T400011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T400111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T400000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T400100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T400010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T400110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T800001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T800101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T800011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T800111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T800000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T800100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T800010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T800110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud3PointTexture"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._T600000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T600100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T600010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T600110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T500001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T500101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T500011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T500111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T500000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T500100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T500010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T500110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T900001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T900101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T900011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T900111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T900000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T900100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T900010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T900110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud3PointTexture"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._T700000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T700100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T700010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T700110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - } - return 0; - } - - static int[] m_TempPalette = new int[256]; - - // todo check for cached palette - public static boolean getPalette4(int val) { - int[] src = m_polygonInfo.clut; - int srcIndex = m_polygonInfo.clutOffset; - int first = src[srcIndex]; - - // no breg required - if ((val & 0x01000000) != 0 || (val & 0xffffff) == 0x808080) { - if (0 != (first & PIXEL_SOLID_CLUT_CHECKED)) { - return (first & PIXEL_SOLID_CLUT) != 0; - } - boolean solid = true; - for (int i = 0; i < 16; i++) { - int current = src[srcIndex + i]; - if (0 == (current & 0x1ffffff)) { - solid = false; - break; - } - } -// System.out.println("checking solid 16 for "+MiscUtil.toHex( srcIndex, 5)+" "+solid); - if (solid) { - src[srcIndex] |= PIXEL_SOLID_CLUT | PIXEL_SOLID_CLUT_CHECKED; - } else { - src[srcIndex] = (src[srcIndex] & ~PIXEL_SOLID_CLUT) | PIXEL_SOLID_CLUT_CHECKED; - } - return solid; - } - //if (0==(first&PIXEL_BREG_CLUT)) { - // System.out.println("BREG CLUT 16 "+MiscUtil.toHex( srcIndex, 5)); - // src[srcIndex]|=PIXEL_BREG_CLUT; - //} - - int rmul = (val & 0xff); - int gmul = ((val >> 8) & 0xff); - int bmul = ((val >> 16) & 0xff); - int[] dest = m_TempPalette; - boolean solid = true; - for (int i = 0; i < 16; i++) { - int current = src[srcIndex + i]; - int b = (current & 0xff); - int g = ((current >> 8) & 0xff); - int r = ((current >> 16) & 0xff); - // we mustn't change pixel to a zero unless it was zero to configure with - int mask = ((current & 0xffffff) == 0) ? 0 : 1; - r = (r * rmul) >> 7; - if (r > 255) r = 255; - g = (g * gmul) >> 7; - if (g > 255) g = 255; - b = (b * bmul) >> 7; - if (b > 255) b = 255; - dest[i] = (current & 0x01000000) | (r << 16) | (g << 8) | b | mask; - if (dest[i] == 0) { - solid = false; - } - } - m_polygonInfo.clut = dest; - m_polygonInfo.clutOffset = 0; - return solid; - } - - // todo check for cached palette - public static boolean getPalette8(int val) { - int[] src = m_polygonInfo.clut; - int srcIndex = m_polygonInfo.clutOffset; - int first = src[srcIndex]; - // no breg required - if ((val & 0x01000000) != 0 || (val & 0xffffff) == 0x808080) { - if (0 != (first & PIXEL_SOLID_CLUT_CHECKED)) { - return (first & PIXEL_SOLID_CLUT) != 0; - } - boolean solid = true; - for (int i = 0; i < 256; i++) { - int current = src[srcIndex + i]; - if (0 == (current & 0x1ffffff)) { - solid = false; - break; - } - } -// System.out.println("checking solid 256 for "+MiscUtil.toHex( srcIndex, 5)+" "+solid); - if (solid) { - src[srcIndex] |= PIXEL_SOLID_CLUT | PIXEL_SOLID_CLUT_CHECKED; - } else { - src[srcIndex] = (src[srcIndex] & ~PIXEL_SOLID_CLUT) | PIXEL_SOLID_CLUT_CHECKED; - } - return solid; - } - //if (0==(first&PIXEL_BREG_CLUT)) { - // System.out.println("BREG CLUT 256 "+MiscUtil.toHex( srcIndex, 5)); - // src[srcIndex]|=PIXEL_BREG_CLUT; - //} - - // todo caching here! - boolean solid = true; - int rmul = (val & 0xff); - int gmul = ((val >> 8) & 0xff); - int bmul = ((val >> 16) & 0xff); - int[] dest = m_TempPalette; - for (int i = 0; i < 256; i++) { - int current = src[srcIndex + i]; - int b = (current & 0xff); - int g = ((current >> 8) & 0xff); - int r = ((current >> 16) & 0xff); - // we mustn't change pixel to a zero unless it was zero to start with - int mask = ((current & 0xffffff) == 0) ? 0 : 1; - r = (r * rmul) >> 7; - if (r > 255) r = 255; - g = (g * gmul) >> 7; - if (g > 255) g = 255; - b = (b * bmul) >> 7; - if (b > 255) b = 255; - dest[i] = (current & 0x01000000) | (r << 16) | (g << 8) | b | mask; - if (dest[i] == 0) { - solid = false; - } - } - m_polygonInfo.clut = dest; - m_polygonInfo.clutOffset = 0; - return solid; - } - - public static int gpud3PointTextureSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - v1.u = data[offset + 4] & 0xff; - v1.v = (data[offset + 4] >> 8) & 0xff; - - drawModePacket(data[offset + 4]); - - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - v2.u = data[offset + 6] & 0xff; - v2.v = (data[offset + 6] >> 8) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointTextureSemi"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T401110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T402110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T403110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T404110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T801110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T802110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T803110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T804110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud3PointTextureSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T601000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T602000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T603000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T604000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T601100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T602100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T603100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T604100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T601010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T602010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T603010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T604010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T601110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T602110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T603110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T604110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T501110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T502110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T503110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T504110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T901110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T902110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T903110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T904110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud3PointTextureSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T701000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T702000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T703000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T704000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T701100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T702100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T703100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T704100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T701010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T702010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T703010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T704010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T701110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T702110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T703110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T704110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - } - return 0; - } - - private static String colorString(int r, int g, int b) { - return "(" + MiscUtil.toHex(r, 2) + "," + MiscUtil.toHex(g, 2) + "," + MiscUtil.toHex(b, 2) + ")"; - } - - public static int gpud4PointFlat(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - - v2.x = (data[offset + 3] << 20) >> 20; - v2.y = (data[offset + 3] << 4) >> 20; - - v3.x = (data[offset + 4] << 20) >> 20; - v3.y = (data[offset + 4] << 4) >> 20; - - m_polygonInfo.r = data[offset] & 0xff; - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointFlat " + v0.x + "," + v0.y + " " + v1.x + "," + v1.y + " " + v2.x + "," + v2.y + " " + v3.x + "," + v3.y + " " + - colorString(m_polygonInfo.r, m_polygonInfo.g, m_polygonInfo.b)); - } - - switch (getMaskModes()) { - case 0: - GPUGenerated._Q000000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q000100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q000010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q000110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - return 0; - } - - public static int gpud4PointFlatSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - - v2.x = (data[offset + 3] << 20) >> 20; - v2.y = (data[offset + 3] << 4) >> 20; - - v3.x = (data[offset + 4] << 20) >> 20; - v3.y = (data[offset + 4] << 4) >> 20; - - m_polygonInfo.r = data[offset] & 0xff; - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointFlatSemi"); - } - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q001000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q002000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q003000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q004000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q001100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q002100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q003100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q004100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q001010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q002010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q003010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q004010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q001110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q002110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q003110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q004110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - return 0; - } - - public static int gpud4PointTexture(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - v1.u = data[offset + 4] & 0xff; - v1.v = (data[offset + 4] >> 8) & 0xff; - - drawModePacket(data[offset + 4]); - - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - v2.u = data[offset + 6] & 0xff; - v2.v = (data[offset + 6] >> 8) & 0xff; - - v3.x = (data[offset + 7] << 20) >> 20; - v3.y = (data[offset + 7] << 4) >> 20; - v3.u = data[offset + 8] & 0xff; - v3.v = (data[offset + 8] >> 8) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointTexture " + v0.x + "," + v0.y + " " + v1.x + "," + v1.y + " " + v2.x + "," + v2.y + " " + v3.x + "," + v3.y + " clut " + clx + "," + cly); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q400001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q400101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q400011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q400111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q400000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q400100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q400010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q400110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q800001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q800101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q800011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q800111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q800000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q800100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q800010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q800110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud4PointTexture"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._Q600000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q600100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q600010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q600110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q500001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q500101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q500011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q500111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q500000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q500100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q500010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q500110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q900001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q900101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q900011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q900111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q900000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q900100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q900010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q900110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud4PointTexture"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._Q700000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q700100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q700010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q700110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - } - return 0; - } - - public static int gpud4PointTextureSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - v1.u = data[offset + 4] & 0xff; - v1.v = (data[offset + 4] >> 8) & 0xff; - - drawModePacket(data[offset + 4]); - - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - v2.u = data[offset + 6] & 0xff; - v2.v = (data[offset + 6] >> 8) & 0xff; - - v3.x = (data[offset + 7] << 20) >> 20; - v3.y = (data[offset + 7] << 4) >> 20; - v3.u = data[offset + 8] & 0xff; - v3.v = (data[offset + 8] >> 8) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointTextureSemi"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q401110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q402110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q403110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q404110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q801110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q802110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q803110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q804110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud4PointTextureSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q601000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q602000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q603000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q604000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q601100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q602100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q603100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q604100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q601010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q602010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q603010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q604010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q601110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q602110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q603110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q604110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q501110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q502110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q503110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q504110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q901110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q902110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q903110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q904110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpud4PointTextureSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q701000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q702000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q703000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q704000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q701100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q702100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q703100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q704100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q701010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q702010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q703010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q704010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q701110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q702110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q703110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q704110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - } - return 0; - } - - public static int gpud3PointGouraud(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - - v1.r = data[offset + 2] & 0xff; - v1.g = (data[offset + 2] >> 8) & 0xff; - v1.b = (data[offset + 2] >> 16) & 0xff; - - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - - v2.r = data[offset + 4] & 0xff; - v2.g = (data[offset + 4] >> 8) & 0xff; - v2.b = (data[offset + 4] >> 16) & 0xff; - - //System.out.println("("+v0.r+","+v0.g+","+v0.b+") ("+v1.r+","+v1.g+","+v1.b+") ("+v2.r+","+v2.g+","+v2.b+")"); - if (dumpGPUD) { - System.out.println("gpud3PointGouraud"); - } - switch (getMaskModes()) { - case 0: - GPUGenerated._T010001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T010101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T010011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T010111.render(m_polygonInfo, v0, v1, v2); - break; - } - return 0; - } - - public static int gpud3PointGouraudSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.r = data[offset + 2] & 0xff; - v1.g = (data[offset + 2] >> 8) & 0xff; - v1.b = (data[offset + 2] >> 16) & 0xff; - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - - v2.r = data[offset + 4] & 0xff; - v2.g = (data[offset + 4] >> 8) & 0xff; - v2.b = (data[offset + 4] >> 16) & 0xff; - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - - if (dumpGPUD) { - System.out.println("gpud3PointGouraudSemi"); - } - // todo lots - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T011000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T012000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T013000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T014000.render(m_polygonInfo, v0, v1, v2); - break; - } - return 0; - } - - public static int gpud3PointTextureGouraud(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 4] << 20) >> 20; - v1.y = (data[offset + 4] << 4) >> 20; - v1.u = data[offset + 5] & 0xff; - v1.v = (data[offset + 5] >> 8) & 0xff; - v1.r = data[offset + 3] & 0xff; - v1.g = (data[offset + 3] >> 8) & 0xff; - v1.b = (data[offset + 3] >> 16) & 0xff; - - drawModePacket(data[offset + 5]); - - v2.x = (data[offset + 7] << 20) >> 20; - v2.y = (data[offset + 7] << 4) >> 20; - v2.u = data[offset + 8] & 0xff; - v2.v = (data[offset + 8] >> 8) & 0xff; - v2.r = data[offset + 6] & 0xff; - v2.g = (data[offset + 6] >> 8) & 0xff; - v2.b = (data[offset + 6] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointTextureGouraud"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T410001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T410101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T410011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T410111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T410000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T410100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T410010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T410110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T810001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T810101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T810011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T810111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T810000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T810100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T810010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T810110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: - switch (getMaskModes()) { - case 0: - GPUGenerated._T610000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T610100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T610010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T610110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T510001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T510101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T510011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T510111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T510000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T510100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T510010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T510110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._T910001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T910101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T910011.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T910111.render(m_polygonInfo, v0, v1, v2); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._T910000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T910100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T910010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T910110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: - switch (getMaskModes()) { - case 0: - GPUGenerated._T710000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._T710100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._T710010.render(m_polygonInfo, v0, v1, v2); - break; - default: - GPUGenerated._T710110.render(m_polygonInfo, v0, v1, v2); - break; - } - } - return 0; - } - - public static int gpud3PointTextureGouraudSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 4] << 20) >> 20; - v1.y = (data[offset + 4] << 4) >> 20; - v1.u = data[offset + 5] & 0xff; - v1.v = (data[offset + 5] >> 8) & 0xff; - v1.r = data[offset + 3] & 0xff; - v1.g = (data[offset + 3] >> 8) & 0xff; - v1.b = (data[offset + 3] >> 16) & 0xff; - - drawModePacket(data[offset + 5]); - - v2.x = (data[offset + 7] << 20) >> 20; - v2.y = (data[offset + 7] << 4) >> 20; - v2.u = data[offset + 8] & 0xff; - v2.v = (data[offset + 8] >> 8) & 0xff; - v2.r = data[offset + 6] & 0xff; - v2.g = (data[offset + 6] >> 8) & 0xff; - v2.b = (data[offset + 6] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud3PointTextureGouraudSemi"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T411110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T412110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T413110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T414110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T811110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T812110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T813110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T814110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T611000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T612000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T613000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T614000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T611100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T612100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T613100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T614100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T611010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T612010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T613010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T614010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T611110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T612110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T613110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T614110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - break; - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T511110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T512110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T513110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T514110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913001.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914001.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913101.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914101.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913011.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914011.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913111.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914111.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T911110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T912110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T913110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T914110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T711000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T712000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T713000.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T714000.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T711100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T712100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T713100.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T714100.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T711010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T712010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T713010.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T714010.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._T711110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._T712110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._T713110.render(m_polygonInfo, v0, v1, v2); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._T714110.render(m_polygonInfo, v0, v1, v2); - break; - } - break; - } - } - return 0; - } - - public static int gpud4PointGouraud(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.r = data[offset + 2] & 0xff; - v1.g = (data[offset + 2] >> 8) & 0xff; - v1.b = (data[offset + 2] >> 16) & 0xff; - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - - v2.r = data[offset + 4] & 0xff; - v2.g = (data[offset + 4] >> 8) & 0xff; - v2.b = (data[offset + 4] >> 16) & 0xff; - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - - v3.r = data[offset + 6] & 0xff; - v3.g = (data[offset + 6] >> 8) & 0xff; - v3.b = (data[offset + 6] >> 16) & 0xff; - v3.x = (data[offset + 7] << 20) >> 20; - v3.y = (data[offset + 7] << 4) >> 20; - - if (dumpGPUD) { - System.out.println("gpud4PointGouraud"); - } - GPUGenerated._Q010000.render(m_polygonInfo, v0, v1, v2, v3); - return 0; - } - - public static int gpud4PointGouraudSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - - v1.r = data[offset + 2] & 0xff; - v1.g = (data[offset + 2] >> 8) & 0xff; - v1.b = (data[offset + 2] >> 16) & 0xff; - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - - v2.r = data[offset + 4] & 0xff; - v2.g = (data[offset + 4] >> 8) & 0xff; - v2.b = (data[offset + 4] >> 16) & 0xff; - v2.x = (data[offset + 5] << 20) >> 20; - v2.y = (data[offset + 5] << 4) >> 20; - - v3.r = data[offset + 6] & 0xff; - v3.g = (data[offset + 6] >> 8) & 0xff; - v3.b = (data[offset + 6] >> 16) & 0xff; - v3.x = (data[offset + 7] << 20) >> 20; - v3.y = (data[offset + 7] << 4) >> 20; - - if (dumpGPUD) { - System.out.println("gpud4PointGouraudSemi"); - } - // todo lots - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q011000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q012000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q013000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q014000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - return 0; - } - - public static int gpud4PointTextureGouraud(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 4] << 20) >> 20; - v1.y = (data[offset + 4] << 4) >> 20; - v1.u = data[offset + 5] & 0xff; - v1.v = (data[offset + 5] >> 8) & 0xff; - v1.r = data[offset + 3] & 0xff; - v1.g = (data[offset + 3] >> 8) & 0xff; - v1.b = (data[offset + 3] >> 16) & 0xff; - - drawModePacket(data[offset + 5]); - - v2.x = (data[offset + 7] << 20) >> 20; - v2.y = (data[offset + 7] << 4) >> 20; - v2.u = data[offset + 8] & 0xff; - v2.v = (data[offset + 8] >> 8) & 0xff; - v2.r = data[offset + 6] & 0xff; - v2.g = (data[offset + 6] >> 8) & 0xff; - v2.b = (data[offset + 6] >> 16) & 0xff; - - v3.x = (data[offset + 10] << 20) >> 20; - v3.y = (data[offset + 10] << 4) >> 20; - v3.u = data[offset + 11] & 0xff; - v3.v = (data[offset + 11] >> 8) & 0xff; - v3.r = data[offset + 9] & 0xff; - v3.g = (data[offset + 9] >> 8) & 0xff; - v3.b = (data[offset + 9] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointTextureGouraud"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q410001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q410101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q410011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q410111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q410000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q410100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q410010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q410110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q810001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q810101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q810011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q810111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q810000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q810100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q810010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q810110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: - switch (getMaskModes()) { - case 0: - GPUGenerated._Q610000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q610100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q610010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q610110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q510001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q510101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q510011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q510111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q510000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q510100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q510010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q510110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q910001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q910101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q910011.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q910111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._Q910000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q910100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q910010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q910110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: - switch (getMaskModes()) { - case 0: - GPUGenerated._Q710000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._Q710100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._Q710010.render(m_polygonInfo, v0, v1, v2, v3); - break; - default: - GPUGenerated._Q710110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - } - return 0; - } - - public static int gpud4PointTextureGouraudSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - Vertex v2 = m_v2; - Vertex v3 = m_v3; - - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v0.u = data[offset + 2] & 0xff; - v0.v = (data[offset + 2] >> 8) & 0xff; - v0.r = data[offset] & 0xff; - v0.g = (data[offset] >> 8) & 0xff; - v0.b = (data[offset] >> 16) & 0xff; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - v1.x = (data[offset + 4] << 20) >> 20; - v1.y = (data[offset + 4] << 4) >> 20; - v1.u = data[offset + 5] & 0xff; - v1.v = (data[offset + 5] >> 8) & 0xff; - v1.r = data[offset + 3] & 0xff; - v1.g = (data[offset + 3] >> 8) & 0xff; - v1.b = (data[offset + 3] >> 16) & 0xff; - - drawModePacket(data[offset + 5]); - - v2.x = (data[offset + 7] << 20) >> 20; - v2.y = (data[offset + 7] << 4) >> 20; - v2.u = data[offset + 8] & 0xff; - v2.v = (data[offset + 8] >> 8) & 0xff; - v2.r = data[offset + 6] & 0xff; - v2.g = (data[offset + 6] >> 8) & 0xff; - v2.b = (data[offset + 6] >> 16) & 0xff; - - v3.x = (data[offset + 10] << 20) >> 20; - v3.y = (data[offset + 10] << 4) >> 20; - v3.u = data[offset + 11] & 0xff; - v3.v = (data[offset + 11] >> 8) & 0xff; - v3.r = data[offset + 9] & 0xff; - v3.g = (data[offset + 9] >> 8) & 0xff; - v3.b = (data[offset + 9] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpud4PointTextureGouraudSemi"); - } - // TODO texturepage - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q411110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q412110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q413110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q414110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q811110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q812110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q813110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q814110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q611000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q612000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q613000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q614000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q611100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q612100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q613100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q614100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q611010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q612010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q613010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q614010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q611110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q612110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q613110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q614110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - break; - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q511110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q512110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q513110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q514110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset] | 0x01000000)) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913001.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914001.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913101.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914101.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913011.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914011.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913111.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914111.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q911110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q912110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q913110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q914110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q711000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q712000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q713000.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q714000.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q711100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q712100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q713100.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q714100.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q711010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q712010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q713010.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q714010.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._Q711110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._Q712110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._Q713110.render(m_polygonInfo, v0, v1, v2, v3); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._Q714110.render(m_polygonInfo, v0, v1, v2, v3); - break; - } - break; - } - } - return 0; - } - - public static int gpudLine(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - m_lineInfo.color = makePixel(data[offset] & 0xff, (data[offset] >> 8) & 0xff, (data[offset] >> 16) & 0xff, 0); - - if (dumpGPUD) { - System.out.println("gpudLine (" + v0.x + "," + v0.y + ") -> (" + v1.x + "," + v1.y + ")"); - } - switch (getMaskModes()) { - case 0: - GPUGenerated._L000000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._L000100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._L000010.render(m_lineInfo, v0, v1); - break; - default: - GPUGenerated._L000110.render(m_lineInfo, v0, v1); - break; - } - return 0; - } - - public static int gpudLineSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v1.x = (data[offset + 2] << 20) >> 20; - v1.y = (data[offset + 2] << 4) >> 20; - m_lineInfo.color = makePixel(data[offset] & 0xff, (data[offset] >> 8) & 0xff, (data[offset] >> 16) & 0xff, 0); - - if (dumpGPUD) { - System.out.println("gpudLineSemi"); - } - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L001000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L002000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L003000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L004000.render(m_lineInfo, v0, v1); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L001100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L002100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L003100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L004100.render(m_lineInfo, v0, v1); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L001010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L002010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L003010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L004010.render(m_lineInfo, v0, v1); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L001110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L002110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L003110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L004110.render(m_lineInfo, v0, v1); - break; - } - break; - } - return 0; - } - - public static int gpudPolyLine(int[] data, int offset, int size) { - if (m_gpudState != GPUD_CMD_EXTRA) { - // Draw the first line segment. - gpudLine(data, offset, 3); - polyLineCmdBuffer[0] = data[offset]; // Color for whole polyline. - polyLineCmdBuffer[1] = data[offset + 2]; // v1 for next line segment. - m_gpudState = GPUD_CMD_EXTRA; - return 0; - } else { - // todo; do this more efficiently! - // NOTE: While most games use 0x55555555, Wild Arms uses 0x50005000. - // http://problemkaputt.de/psx-spx.htm#gpurenderlinecommands - if ((data[offset] & 0xf000f000 ) == 0x50005000) { - // End of the polyline! - m_gpudState = GPUD_CMD_NONE; - } else { - // Draw the next line segment. - polyLineCmdBuffer[2] = data[offset]; - gpudLine(polyLineCmdBuffer, 0, 3); - // Buffer entry 0 [color data] doesn't need to be rewritten. - polyLineCmdBuffer[1] = data[offset]; // v1 for next line segment. - } - return 1; - } - } - - public static int gpudPolyLineSemi(int[] data, int offset, int size) { - System.out.println("GPUD PolyLineSemi"); - if (true) throw new IllegalStateException(); - return 0; - } - - public static int gpudLineGouraudSemi(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - m_lineInfo.r0 = data[offset] & 0xff; - m_lineInfo.g0 = (data[offset] >> 8) & 0xff; - m_lineInfo.b0 = (data[offset] >> 16) & 0xff; - m_lineInfo.r1 = data[offset + 2] & 0xff; - m_lineInfo.g1 = (data[offset + 2] >> 8) & 0xff; - m_lineInfo.b1 = (data[offset + 2] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpudLineGouraudSemi"); - } - - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L011000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L012000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L013000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L014000.render(m_lineInfo, v0, v1); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L011100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L012100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L013100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L014100.render(m_lineInfo, v0, v1); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L011010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L012010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L013010.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L014010.render(m_lineInfo, v0, v1); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._L011110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._L012110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._L013110.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._L014110.render(m_lineInfo, v0, v1); - break; - } - break; - } - return 0; - } - - public static int gpudLineGouraud(int[] data, int offset, int size) { - Vertex v0 = m_v0; - Vertex v1 = m_v1; - v0.x = (data[offset + 1] << 20) >> 20; - v0.y = (data[offset + 1] << 4) >> 20; - v1.x = (data[offset + 3] << 20) >> 20; - v1.y = (data[offset + 3] << 4) >> 20; - m_lineInfo.r0 = data[offset] & 0xff; - m_lineInfo.g0 = (data[offset] >> 8) & 0xff; - m_lineInfo.b0 = (data[offset] >> 16) & 0xff; - m_lineInfo.r1 = data[offset + 2] & 0xff; - m_lineInfo.g1 = (data[offset + 2] >> 8) & 0xff; - m_lineInfo.b1 = (data[offset + 2] >> 16) & 0xff; - - if (dumpGPUD) { - System.out.println("gpudLineGouraud"); - } - switch (getMaskModes()) { - case 0: - GPUGenerated._L010000.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._L010100.render(m_lineInfo, v0, v1); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._L010010.render(m_lineInfo, v0, v1); - break; - default: - GPUGenerated._L010110.render(m_lineInfo, v0, v1); - break; - } - return 0; - } - - public static int gpudPolyLineGouraud(int[] data, int offset, int size) { - System.out.println("GPUD PolyLineGouraud"); - if (true) throw new IllegalStateException(); - return 0; - } - - private static int[] polyLineCmdBuffer = new int[4]; - - public static int gpudPolyLineGouraudSemi(int[] data, int offset, int size) { - if (m_gpudState != GPUD_CMD_EXTRA) { - gpudLineGouraudSemi(data, offset, 4); - polyLineCmdBuffer[0] = data[offset + 2]; // color1 - polyLineCmdBuffer[1] = data[offset + 3]; // v1 - polyLineCmdBuffer[2] = 0x55555555; - m_gpudState = GPUD_CMD_EXTRA; - return 0; - } else { - // todo; do this more efficiently! - // NOTE: While most games use 0x55555555, Wild Arms uses 0x50005000. - // http://problemkaputt.de/psx-spx.htm#gpurenderlinecommands - if ((data[offset] & 0xf000f000 ) == 0x50005000) { - m_gpudState = GPUD_CMD_NONE; - return 1; - } - if (polyLineCmdBuffer[2] == 0x55555555) { - polyLineCmdBuffer[2] = data[offset]; - } else { - polyLineCmdBuffer[3] = data[offset + 1]; - gpudLineGouraudSemi(polyLineCmdBuffer, 0, 4); - polyLineCmdBuffer[0] = polyLineCmdBuffer[2]; - polyLineCmdBuffer[1] = polyLineCmdBuffer[3]; - polyLineCmdBuffer[2] = 0x55555555; - } - return 1; - } - } - - public static int gpudRectangle(int[] data, int offset, int size) { - - m_polygonInfo.r = (data[offset] & 0xff); - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - int x = (data[offset + 1] << 20) >> 20; - int y = (data[offset + 1] << 4) >> 20; - - int w = data[offset + 2] & 0xffff; - int h = data[offset + 2] >> 16; - - if (dumpGPUD) { - System.out.println("gpudRectangle " + x + "," + y + " " + w + "," + h); - } - switch (getMaskModes()) { - case 0: - GPUGenerated._S000000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S000100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S000010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S000110.render(m_polygonInfo, x, y, w, h); - break; - } - return 0; - } - - public static int gpudRectangleSemi(int[] data, int offset, int size) { - - m_polygonInfo.r = (data[offset] & 0xff); - m_polygonInfo.g = (data[offset] >> 8) & 0xff; - m_polygonInfo.b = (data[offset] >> 16) & 0xff; - - int x = (data[offset + 1] << 20) >> 20; - int y = (data[offset + 1] << 4) >> 20; - - int w = data[offset + 2] & 0xffff; - int h = data[offset + 2] >> 16; - - if (dumpGPUD) { - System.out.println("gpudRectangleSemi " + x + "," + y + " " + w + "," + h); - } - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S001000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S002000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S003000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S004000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S001100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S002100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S003100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S004100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S001010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S002010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S003010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S004010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S001110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S002110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S003110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S004110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - return 0; - } - - public static int gpudSprite(int[] data, int offset, int size) { - - - int x = (data[offset + 1] << 20) >> 20; - int y = (data[offset + 1] << 4) >> 20; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.u = data[offset + 2] & 0xff; - m_polygonInfo.v = (data[offset + 2] >> 8) & 0xff; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - int w = data[offset + 3] & 0x1ff; - int h = data[offset + 3] >> 16; - - if (dumpGPUD) { - System.out.println("gpudSprite " + x + "," + y + " " + w + "," + h + " tm " + getTextureMode() + " mm " + getMaskModes()); - } - if (false && x == -48 && y == 96 && w == 16 && h == 16) { - try { - java.io.FileOutputStream fos = new java.io.FileOutputStream("vram.dat"); - for (int i = 0; i < 1024 * 512; i++) { - int b = videoRAM[i]; - fos.write(b & 0xff); - fos.write((b >> 8) & 0xff); - fos.write((b >> 16) & 0xff); - fos.write((b >> 24) & 0x01); - } - } catch (Throwable t) { - - } - System.exit(0); - } - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._S400001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S400101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S400011.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S400111.render(m_polygonInfo, x, y, w, h); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._S400000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S400100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S400010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S400110.render(m_polygonInfo, x, y, w, h); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._S800001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S800101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S800011.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S800111.render(m_polygonInfo, x, y, w, h); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._S800000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S800100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S800010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S800110.render(m_polygonInfo, x, y, w, h); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpudSprite"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._S600000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S600100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S600010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S600110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._S500001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S500101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S500011.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S500111.render(m_polygonInfo, x, y, w, h); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._S500000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S500100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S500010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S500110.render(m_polygonInfo, x, y, w, h); - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - GPUGenerated._S900001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S900101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S900011.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S900111.render(m_polygonInfo, x, y, w, h); - break; - } - } else { - switch (getMaskModes()) { - case 0: - GPUGenerated._S900000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S900100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S900010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S900110.render(m_polygonInfo, x, y, w, h); - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpudSprite"); - } - // todo breg - switch (getMaskModes()) { - case 0: - GPUGenerated._S700000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SET_MASK: - GPUGenerated._S700100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_CHECK_MASK: - GPUGenerated._S700010.render(m_polygonInfo, x, y, w, h); - break; - default: - GPUGenerated._S700110.render(m_polygonInfo, x, y, w, h); - break; - } - } - } - return 0; - - - } - - public static int gpudSpriteSemi(int[] data, int offset, int size) { - - int x = (data[offset + 1] << 20) >> 20; - int y = (data[offset + 1] << 4) >> 20; - - int cly = (data[offset + 2] >> 22) & 0x1ff; - int clx = (data[offset + 2] & 0x3f0000) >> 12; - m_polygonInfo.u = data[offset + 2] & 0xff; - m_polygonInfo.v = (data[offset + 2] >> 8) & 0xff; - m_polygonInfo.clut = videoRAM; - m_polygonInfo.clutOffset = cly * 1024 + clx; - - int w = data[offset + 3] & 0x1ff; - int h = data[offset + 3] >> 16; - - if (dumpGPUD) { - System.out.println("gpudSpriteSemi " + x + "," + y + " " + w + "," + h); - } - switch (getTextureMode()) { - case DRAWMODE_TEXTURE_4BIT: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404001.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404101.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404011.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404111.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S401110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S402110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S403110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S404110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BIT: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804001.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804101.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804011.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804111.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S801110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S802110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S803110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S804110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BIT: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpudSpriteSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S601000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S602000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S603000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S604000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S601100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S602100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S603100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S604100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S601010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S602010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S603010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S604010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S601110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S602110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S603110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S604110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - break; - } - case DRAWMODE_TEXTURE_4BITW: - if (getPalette4(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504001.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504101.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504011.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504111.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S501110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S502110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S503110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S504110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_8BITW: - if (getPalette8(data[offset])) { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903001.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904001.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903101.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904101.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903011.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904011.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903111.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904111.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } else { - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S901110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S902110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S903110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S904110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } - break; - case DRAWMODE_TEXTURE_16BITW: { - boolean nobreg = false; - if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { - nobreg = true; - } else { - missing("16 bit breg gpudSpriteSemi"); - } - // todo breg - switch (getMaskModes()) { - case 0: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S701000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S702000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S703000.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S704000.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_SET_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S701100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S702100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S703100.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S704100.render(m_polygonInfo, x, y, w, h); - break; - } - break; - case DRAWMODE_CHECK_MASK: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S701010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S702010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S703010.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S704010.render(m_polygonInfo, x, y, w, h); - break; - } - break; - default: - switch (getSemiMode()) { - case DRAWMODE_SEMI_5P5: - GPUGenerated._S701110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P10: - GPUGenerated._S702110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10M10: - GPUGenerated._S703110.render(m_polygonInfo, x, y, w, h); - break; - case DRAWMODE_SEMI_10P25: - GPUGenerated._S704110.render(m_polygonInfo, x, y, w, h); - break; - } - break; - } - } - } - return 0; - } - - public static int gpudRectangle1x1(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00010001; - int rc = gpudRectangle(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudRectangle1x1Semi(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00010001; - int rc = gpudRectangleSemi(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudSprite1x1(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00010001; - int rc = gpudSprite(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudSprite1x1Semi(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00010001; - int rc = gpudSpriteSemi(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudRectangle8x8(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00080008; - int rc = gpudRectangle(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudRectangle8x8Semi(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00080008; - int rc = gpudRectangleSemi(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudSprite8x8(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00080008; - int rc = gpudSprite(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudSprite8x8Semi(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00080008; - int rc = gpudSpriteSemi(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudRectangle16x16(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00100010; - int rc = gpudRectangle(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudRectangle16x16Semi(int[] data, int offset, int size) { - int tmp = data[offset + 2]; - data[offset + 2] = 0x00100010; - int rc = gpudRectangleSemi(data, offset, size); - data[offset + 2] = tmp; - return rc; - } - - public static int gpudSprite16x16(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00100010; - int rc = gpudSprite(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudSprite16x16Semi(int[] data, int offset, int size) { - int tmp = data[offset + 3]; - data[offset + 3] = 0x00100010; - int rc = gpudSpriteSemi(data, offset, size); - data[offset + 3] = tmp; - return rc; - } - - public static int gpudVRAMtoVRAM(int[] data, int offset, int size) { - // todo check sizes - int sx = data[offset + 1] & 0x3ff; - int sy = (data[offset + 1] >> 16) & 0x1ff; - int dx = data[offset + 2] & 0x3ff; - int dy = (data[offset + 2] >> 16) & 0x1ff; - - if (sx == dx && sy == dy) { - if (false) - System.out.println("??? " + MiscUtil.toHex(data[offset], 8) + " " + - MiscUtil.toHex(data[offset + 1], 8) + " " + - MiscUtil.toHex(data[offset + 2], 8) + " " + - MiscUtil.toHex(data[offset + 3], 8)); - return 0; - } - int w = data[offset + 3] & 0x3ff; - int h = (data[offset + 3] >> 16) & 0x1ff; - // todo is this slow? - if (dumpGPUD) - System.out.println("GPUD VRAMToVRAM " + sx + "," + sy + " " + w + "," + h + " -> " + dx + "," + dy); - - if (w > 0) { - int src = sx + sy * 1024; - int dest = dx + dy * 1024; - // system.arraycopy? - if (dest < src) { - for (; h > 0; h--) { - for (int x = 0; x < w; x++) { - videoRAM[dest + x] = videoRAM[src + x]; - } - src += 1024; - dest += 1024; - } - } else { - src += (h - 1) * 1024; - dest += (h - 1) * 1024; - for (; h > 0; h--) { - for (int x = w - 1; x >= 0; x--) { - videoRAM[dest + x] = videoRAM[src + x]; - } - src -= 1024; - dest -= 1024; - } - } - } - manager.dirtyRectangle(dx, dy, w, h); - return 0; - } - - public static int gpudMemToVRAM(int[] data, int offset, int size) { - if (m_gpudState != GPUD_CMD_EXTRA) { - int x = data[offset + 1] & 0x3ff; - int y = (data[offset + 1] >> 16) & 0x1ff; - int w = data[offset + 2] & 0x7ff; - int h = (data[offset + 2] >> 16) & 0x3ff; - int dwordSize = (w * h + 1) >> 1; - - m_dmaRGB24Index = 0; - m_dmaX = x; - m_dmaY = y; - m_dmaOriginX = x; - m_dmaOriginY = y; - m_dmaW = w; - m_dmaH = h; - if (dumpGPUD) System.out.println("GPUD MemToVRAM " + x + "," + y + " " + w + "," + h); - if (dwordSize > 0) { - m_gpudState = GPUD_CMD_EXTRA; - m_dmaDWordsRemaining = dwordSize; - } - return 0; - } else { - //System.out.println("Avail: "+count); - //System.out.println("MemToVRAM remaining: "+m_dmaDWordsRemaining); - if (size > m_dmaDWordsRemaining) { - size = m_dmaDWordsRemaining; - } - int rc = size; - m_dmaDWordsRemaining -= size; - - size *= 2; - - int[] ram; - - try { - ram = display.acquireDisplayBuffer(); - - // TODO this is woefully inefficient :-) - if (rgb24conversion && rgb24 && (m_dmaW % 6) == 0) { - // todo graham 12/21/14 - I realized while debugging the intro screen of spyro - // that I actually thought the B and the R were the other way around on the PSX - // curiously that works for other things. Frankly at this point I don't think - // the work of doing the conversion to a separate 24 bit display buffer at display time - // is that bad and will gain us some simplification - probably worth a fork of the GPU/Display though - - // we convert dwords from: - // B1R0G0B0 G2B2R1G1 R3G3B3R2 - // to - // A_R0G0B0 B_R0G0B1 C_R1G1B1 A_R2G2B2 B_R2G2B3 C_R3G3B3 - - // consider words, we pick the internal representation, such that - // we can convert a single pixel without knowing where it came from - // i.e. A_ pixels do one thing, B_ another, and C_ a third. - - // G0B0 B1R0 R1G1 G2B2 B3R2 R3G3 - // to: - // A_R0G0B0 B_R0G0B1 C_R1G1B1 A_R2G2B2 B_R2G2B3 C_R3G3B3 - // to: - // G0B0 B1R0 R1G1 G2B2 B3R2 R3G3 - - while (size > 0) { - int dword = data[offset++]; - switch (m_dmaRGB24Index) { - case 0: - m_dmaRGB24LastPixel = (dword & 0xffffff); - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_A | m_dmaRGB24LastPixel; - m_dmaRGB24LastDWord = dword; - m_dmaX++; - m_dmaRGB24Index = 1; - break; - case 1: - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_B | (m_dmaRGB24LastPixel & 0xffff00) | (m_dmaRGB24LastDWord >>> 24); - m_dmaX++; - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_C | (m_dmaRGB24LastDWord >>> 24) | ((dword << 8) & 0xffff00); - m_dmaRGB24LastDWord = dword; - m_dmaX++; - m_dmaRGB24Index = 2; - break; - case 2: - m_dmaRGB24LastPixel = (m_dmaRGB24LastDWord >>> 16) | ((dword & 0xff) << 16); - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_A | m_dmaRGB24LastPixel; - m_dmaX++; - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_B | (m_dmaRGB24LastPixel & 0xffff00) | ((dword >> 8) & 0xff); - m_dmaX++; - ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_C | ((dword >> 8) & 0xffffff); - m_dmaX++; - m_dmaRGB24Index = 0; - break; - } - if (m_dmaX == (m_dmaOriginX + m_dmaW)) { - m_dmaX = m_dmaOriginX; - m_dmaY++; - m_dmaRGB24Index = 0; - if (m_dmaY == (m_dmaOriginY + m_dmaH)) { - break; - } - } - size -= 2; - } - } else { - // 16 bit - while (size > 0) { - int dword = data[offset++]; - int val = dword >>> 16; - ram[m_dmaX + m_dmaY * 1024] = dma16flags[m_dmaRGB24Index] | makePixel((dword & 0x1f) << 3, (dword & 0x3e0) >> 2, (dword & 0x7c00) >> 7, (dword & 0x8000) >> 15); - m_dmaX++; - m_dmaRGB24Index++; - if (m_dmaX == (m_dmaOriginX + m_dmaW)) { - m_dmaX = m_dmaOriginX; - m_dmaY++; - if (m_dmaY == (m_dmaOriginY + m_dmaH)) { - break; - } - m_dmaRGB24Index = 0; - } - size--; - - ram[m_dmaX + m_dmaY * 1024] = dma16flags[m_dmaRGB24Index] | makePixel((val & 0x1f) << 3, (val & 0x3e0) >> 2, (val & 0x7c00) >> 7, (val & 0x8000) >> 15); - m_dmaX++; - m_dmaRGB24Index++; - if (m_dmaX == (m_dmaOriginX + m_dmaW)) { - m_dmaX = m_dmaOriginX; - m_dmaY++; - if (m_dmaY == (m_dmaOriginY + m_dmaH)) { - break; - } - m_dmaRGB24Index = 0; - } - size--; - if (m_dmaRGB24Index >= 3) m_dmaRGB24Index -= 3; - } - } - } finally { - display.releaseDisplayBuffer(); - } - - if (m_dmaDWordsRemaining == 0) { - int x = m_dmaOriginX; - int y = m_dmaOriginY; - int w = m_dmaW; - int h = m_dmaH; - // todo clear the cache better - for (int page = 0; page < 0x20; page++) { - int px = (page & 0x0f) * 64; - int py = (page & 0x10) * 16; - if (intersects(x, y, w, h, px, py, 64, 256)) { - if (dumpGPUD) { - if (_4bitTexturePages[page] != null) - System.out.println("Zapping 4bit tpage " + page); - } - _4bitTexturePages[page] = null; - } - if (intersects(x, y, w, h, px, py, 128, 256)) { - if (dumpGPUD) { - if (_8bitTexturePages[page] != null) - System.out.println("Zapping 8bit tpage " + page); - } - _8bitTexturePages[page] = null; - } - } - manager.dirtyRectangle(x, y, w, h); - m_gpudState = GPUD_CMD_NONE; - } - return rc; - } - } - - private static boolean intersects(int x0, int y0, int w0, int h0, int x1, int y1, int w1, int h1) { - if (w0 == 0 || h0 == 0 || w1 == 0 || h1 == 0) return false; - w0 += x0; - w1 += x1; - h0 += y0; - h1 += y1; - return (w0 > x1) && (h0 > y1) && (w1 > x0) && (h1 > y0); - } - -/* private static boolean intersectsDisplay( int x, int y, int w, int h) - { - int dx = m_displayX; - int dy = m_displayY; - int dw = m_displayWidth; - int dh = m_displayHeight; - - // todo display configure/end - - if (0!=(m_displayMode&0x0040) && h==1) { - if ((!interlace && 0!=((dy+y)&1)) || - (interlace && 0==((dy+y)&1))) { - //System.out.println("Detected non-intersect in interlaced mode"); - return false; - } - } - return intersects( x, y, w, h, dx, dy, dw, dh); - }*/ - - public static int gpudVRAMToMem(int[] data, int offset, int size) { - int x = data[offset + 1] & 0x3ff; - int y = (data[offset + 1] >> 16) & 0x1ff; - int w = data[offset + 2] & 0x7ff; - int h = (data[offset + 2] >> 16) & 0x3ff; - - m_dmaX = x; - m_dmaY = y; - m_dmaOriginX = x; - m_dmaOriginY = y; - m_dmaW = w; - m_dmaH = h; - m_dmaWordsRemaining = w * h; - if (dumpGPUD) System.out.println("GPUD VRAMtoMem " + x + "," + y + " " + w + "," + h); - assert !rgb24; - return 0; - } - - private static int readPixel() { - if (m_dmaWordsRemaining > 0) { - m_dmaWordsRemaining--; - int rc = unmakePixel(videoRAM[m_dmaX + m_dmaY * 1024]); - m_dmaX++; - if (m_dmaX == m_dmaOriginX + m_dmaW) { - m_dmaX = m_dmaOriginX; - m_dmaY++; - } - return rc; - } - return 0; - } - - public static int gpudSetDrawMode(int[] data, int offset, int size) { - drawMode = data[offset] & 0x7ff; - return 0; - } - - public static int gpudSetTextureWindow(int[] data, int offset, int size) { - if (!supportTextureWindow) { - noTextureWindow = true; - return 0; - } - noTextureWindow = 0 == (data[offset] & 0xfffff); - if (!noTextureWindow) { - int twy = (data[offset] >> 15) & 0x1f; - int twx = (data[offset] >> 10) & 0x1f; - int twh = 32 - ((data[offset] >> 5) & 0x1f); - int tww = 32 - ((data[offset]) & 0x1f); - - // todo cache recent? - int val = twx << 3; - int w = 0; - for (int i = twx; i < 32 + twx; i++) { - twuLookup[i & 0x1f] = val; - val += 1 << 3; - w++; - if (w == tww) { - w = 0; - val = twx << 3; - } - } - - val = twy << 11; - int h = 0; - for (int i = twy; i < 32 + twy; i++) { - twvLookup[i & 0x1f] = val; - val += 1 << 11; - h++; - if (h == twh) { - h = 0; - val = twy << 11; - } - } - - if (dumpGPUD) { - System.out.println("GPUD SetTextureWindow " + (twx * 8) + "," + (twy * 8) + " " + (tww * 8) + "," + (twh * 8)); - } - } - return 0; - } - - public static int gpudSetClipTopLeft(int[] data, int offset, int size) { - m_clipLeft = data[offset] & 0x3ff; - m_clipTop = (data[offset] >> 10) & 0x3ff; - // System.out.println("GPUD SetClipTopLeft "+m_clipLeft+","+m_clipTop); - return 0; - } - - public static int gpudSetClipBottomRight(int[] data, int offset, int size) { - // note addition of (1,1) to co-ords, since we do non-inclusive bottom-right, - // but PSX doesn't. - m_clipRight = (data[offset] & 0x3ff) + 1; - m_clipBottom = ((data[offset] >> 10) & 0x3ff) + 1; - // System.out.println("GPUD SetClipBottomRight "+m_clipRight+","+m_clipBottom); - return 0; - } - - public static int gpudSetDrawingOffset(int[] data, int offset, int size) { - m_drawOffsetX = ((data[offset] & 0x7ff) << 21) >> 21; - m_drawOffsetY = ((data[offset] & 0x3ff800) << 10) >> 21; - // System.out.println("GPUD SetDrawingOfffset "+m_drawOffsetX+","+m_drawOffsetY); - return 0; - } - - public static int gpudSetMaskMode(int[] data, int offset, int size) { - // store the mask settings where they go - - // TODO ? more efficient to keep in low bits because of switch - drawMode = (drawMode & ~(DRAWMODE_SET_MASK | DRAWMODE_CHECK_MASK)) | ((data[offset] & 0x1800) >> 11); - return 0; - } - - public static int gpuStatusRead32(int address) { -// ASSERT( SANITY_CHECK, address==ADDR_GPU_CTRLSTATUS, ""); - int rc = 0; - - // ----------------------------------------------------------------------------- - // |1f |1e 1d|1c |1b |1a |19 18|17 |16 |15 |14 |13 |12 11 |10 | - // |lcf|dma |com|img|busy| ? ?|den|isinter|isrgb24|Video|Height|Width0|Width1| - // ----------------------------------------------------------------------------- - - // ---------------------------------------------------- - // |0f 0e 0d|0c|0b|0a |09 |08 07|06 05|04|03 02 01 00| - // | ? ? ?|me|md|dfe |dtd|tp |abr |ty|tx | - // ---------------------------------------------------- - - // 0000 0000 0000 0000 0000 0111 1111 1111 -// rc |= getRenderer()->getDrawMode(); - rc |= drawMode; - - // TODO don't need this since it is part of draw mode ??? - // 0000 0000 0000 0000 0001 1000 0000 0000 - //rc |= m_maskMode<<11; - - // 0000 0000 0000 0000 1110 0000 0000 0000 - // 0000 0000 0111 1111 0000 0000 0000 0000 - rc |= displayMode << 16; - - // 0000 0000 1000 0000 0000 0000 0000 0000 - if (!m_displayEnabled) - rc |= 0x00800000; - - // 0000 0011 0000 0000 0000 0000 0000 0000 - // 0000 0100 0000 0000 0000 0000 0000 0000 - rc |= 0x04000000; // gpu idle - - // TODO turn this off at some point - // 0000 1000 0000 0000 0000 0000 0000 0000 - rc |= 0x08000000; // ready to receive img - - // 0001 0000 0000 0000 0000 0000 0000 0000 - rc |= 0x10000000; // ready to receive cmds - - // 0110 0000 0000 0000 0000 0000 0000 0000 - rc |= dmaMode << 29; - - // 1000 0000 0000 0000 0000 0000 0000 0000 - - if (manager.getInterlaceField()) - rc |= 0x80000000; //for interlace - - // The poll detection code does not always work, so as a temporary workaround, add another backstop here to catch - // vsync timeouts that never end - if (0 != (displayMode & 0x0040)) { - if (++pollHackStatusReadCount >= 1000) { - _poll(ADDR_GPU_CTRLSTATUS,4); - } - } else { - if (++pollHackStatusReadCount >= 1000000) { - // TonyHawk is still rarely (possibly race) waiting for this to change even in non interlace mode. - // If something is waiting forever, this will at least wake it up - manager.toggleInterlaceField(); - pollHackStatusReadCount = 0; - } - } - - return rc; - } - - static int pollHackStatusReadCount; - - public void aboutToBlock() { - manager.preAsync(); - } - - public void poll(int address, int size) { - _poll(address, size); - } - - protected static void _poll(int address, int size) { - pollHackStatusReadCount = 0; - assert address == ADDR_GPU_CTRLSTATUS; - if (0 != (displayMode & 0x0040)) { - //System.out.println("flicking interlace because of 1814 poll in interlaced mode"); - manager.toggleInterlaceField(); - } - // note, this may not actually update anything... it will update anything if the mode has - // changed, or someone has dirtied the visible display - manager.vsync(); - } - - public static int gpuDataRead32(int address) { - videoRAM = display.acquireDisplayBuffer(); - try { - // used if we're doing vram to mem... these will - // return 0 if we're not currently doing a vram to mem - return readPixel() + (readPixel() << 16); -// return (readPixel()<<16)+readPixel(); - } finally { - display.releaseDisplayBuffer(); - videoRAM = null; - } - } - - private static class GPUDMAChannel extends DMAChannelOwnerBase { - public final int getDMAChannel() { - return DMAController.DMA_GPU; - } - - public final String getName() { - return "GPU"; - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if ((ctrl & 0x200) != 0) { - int size = blocks * blockSize; // in dwords - if (debugTransfers) System.out.println("*** LINEAR GPU DMA FROM VRAM *** size=" + (size * 4)); - try { - addressSpace.resolve(base, size * 4, true, m_resolveResult); - if (m_resolveResult.mem != null) { - videoRAM = display.acquireDisplayBuffer(); - try { - // todo, do this more efficiently - int end = m_resolveResult.offset + size; - for (int i = m_resolveResult.offset; i < end; i++) { - //m_resolveResult.mem[i] = (readPixel()<<16)+readPixel(); - m_resolveResult.mem[i] = readPixel() + (readPixel() << 16); - } - } finally { - display.releaseDisplayBuffer(); - videoRAM = null; - } - } - } finally { - signalTransferComplete(); - } - } else { - throw new IllegalStateException("not implemented"); - } - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - try { - if (ignoreGPU) { - debuggo(); - return; - } - if ((ctrl & 0x200) != 0) { - if (debugTransfers) System.out.println("*** LINEAR GPU DMA ***"); - // linear DMA - //LOG3P( GPU_COMMAND, "Linear DMA %08x %04x * %04x\n", base, blocks, blockSize); - //uint32 size = blocks*blockSize; - //uint32 *addr = (uint32 *)m_gpu->getAddressSpace()->resolve( base, size*4); - // TODO check alignment - //if (addr) { - // m_gpu->handleGPUData( addr, size); - //} - int size = blocks * blockSize; - addressSpace.resolve(base, size, false, m_resolveResult); - if (m_resolveResult.mem != null) { - videoRAM = display.acquireDisplayBuffer(); - try { - handleGPUData(m_resolveResult.mem, m_resolveResult.offset, size); - } finally { - display.releaseDisplayBuffer(); - videoRAM = null; - } - } - } else if ((ctrl & 0x400) != 0) { - if (debugTransfers) System.out.println("*** LINKED LIST GPU DMA ***"); - // linked list DMA - // TODO check alignment - //int timeBefore = MTScheduler.getTime(); - videoRAM = display.acquireDisplayBuffer(); - try { - handleGPUDataChain(base); - } finally { - display.releaseDisplayBuffer(); - videoRAM = null; - } - //System.out.println("chain time "+((MTScheduler.getTime()-timeBefore)>>4)); - } - // TODO for now only - } finally { - signalTransferComplete(); - } - } - } - - private static class OTCDMAChannel extends DMAChannelOwnerBase { - public final int getDMAChannel() { - return DMAController.DMA_GPU_OTC; - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if (ctrl == 0x11000002) { - int count = blockSize; - - // we know that linked list must be in main RAM, - // since addresses are only 24 bits. - - // todo clamp this to ram size? - base &= 0xffffff; - int end = base >> 2; - int addr = end - count + 1; - int[] mainRAM = addressSpace.getMainRAM(); - mainRAM[addr] = 0x00ffffff; - while (addr < end) { - int tmp = addr; - mainRAM[++addr] = (tmp << 2); - } - - } - signalTransferComplete(); - } - - - public final String getName() { - return "GPU OTClear"; - } - } - - public static void gpusReset(int val) { - //System.out.println("GPUS RESET"); - gpusSetDispEnable(1); - gpusSetDisplayMode(0); - gpusSetDisplayOrigin(0); - maskMode = 0; - m_gpudState = GPUD_CMD_NONE; - // todo, check this sets status to 14802000 - } - - private static void gpusCmdReset(int val) { - //System.out.println("GPUS CMD RESET"); - m_gpudState = GPUD_CMD_NONE; - } - - private static void gpusIRQReset(int val) { - //System.out.println("GPUS IRQ RESET"); - } - - private static void gpusSetDispEnable(int val) { - m_displayEnabled = ((val & 1) == 0) ? true : false; - manager.setBlanked(!m_displayEnabled); - //System.out.println("GPUS SET DISP ENABLE "+m_displayEnabled); - } - - private static void gpusSetDataTransferMode(int val) { - dmaMode = val & 3; - //System.out.println("GPUS SET DATA TRANSFER MODE "+m_dmaMode); - } - - private static void gpusSetDisplayOrigin(int val) { - int originX = val & 0x3ff; - int originY = (val >> 10) & 0x1ff; - manager.setOrigin(originX, originY); - } - - private static void gpusSetMonitorLeftRight(int val) { - int l = val & 0xfff; - int r = (val >> 12) & 0xfff; - manager.setHorizontalTiming(l, r); - } - - private static void gpusSetMonitorTopBottom(int val) { - int t = val & 0x3ff; - int b = (val >> 10) & 0x3ff; - manager.setVerticalTiming(t, b); - } - - private static void gpusSetDisplayMode(int val) { - displayMode = ((val & 0x3f) << 1) | ((val & 0x40 >> 6)); - - boolean doubleY = 0 != (val & 0x4); - boolean pal = 0 != (val & 8); - boolean rgb24 = 0 != (val & 0x10); - boolean interlace = 0 != (val & 0x20); - int divider = 8; - - // int isMystery = !!(data&0x80); - switch (val & 0x43) { - case 0: - divider = 10; - break; - case 1: - divider = 8; - break; - case 2: - divider = 5; - break; - case 3: - divider = 4; - break; - case 0x40: - divider = 7; - break; - } - if (dumpGPUD) { - System.out.println("begin set display mode: div="+divider+" depth="+((rgb24)?24:16)+" intl="+interlace+" dbly="+doubleY+" pal="+pal); - } - manager.setPixelDivider(divider); - manager.setRGB24(rgb24); - manager.setInterlaced(interlace); - manager.setDoubleY(doubleY); - manager.setNTSC(!pal); - if (dumpGPUD) { - System.out.println("end set display mode"); - } - } - - private static void gpusRequestInfo(int val) { - val &= 0xffffffL; - switch (val) { - case 3: - //LOG( GPU_COMMAND, "gpusRequestInfo - 3 old top left\n"); - //_gpu_data = 0; - break; - case 4: - //LOG( GPU_COMMAND, "gpusRequestInfo - 4 old bottom right\n"); - //_gpu_data = 0xffffffff; - break; - case 5: - //LOG( GPU_COMMAND, "gpusRequestInfo - 5 draw offset\n"); - //_gpu_data = 0x0; - break; - case 7: - //System.out.println( "GET CPU VERSION" ); - addressSpace.internalWrite32(ADDR_GPU_DATA, 2); - break; - default: - //LOG1P( GPU_COMMAND, "gpusRequestInfo - %d (unknown)\n", data); - break; - } - } - -/* - private static void handleGPUData( int[] mem, int offset, int size) - { - while (size>0) { - if (m_gpudState == GPUD_EXTRA_COMMAND_DATA) { -// ASSERT( SANITY_CHECK, m_currentGPUDFunction!=0, ""); - int dwordsUsed = handleGPUDFunction( mem, offset, size); -// ASSERT( SANITY_CHECK, dwordsUsed<=size, ""); - offset+=dwordsUsed; - size-=dwordsUsed; - } else { - // TODO do better than this later - gpuDataWrite32Internal( ADDR_GPU_DATA, mem[offset]); - offset++; - size--; - } - } - } - */ - - private static void handleGPUData(int[] mem, int offset, int size) { - int origOffset = offset; - if (debugTransfers) System.out.println("HandleGPUData " + size + " dwords"); - while (size > 0) { - switch (m_gpudState) { - case GPUD_CMD_NONE: - m_gpudCommand = (mem[offset] >> 24) & 0xff; - if (debugTransfers) - System.out.println("New command at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); - int count = m_gpudFunctionArgumentCount[m_gpudCommand]; - if (size >= count) { - GPUDRouter.invoke(mem, offset, count); - offset += count; - size -= count; - } else { - // use cmdBuffer for filling - for (int i = 0; i < size; i++) { - m_cmdBuffer[i++] = mem[offset++]; - } - cmdBufferUsed = size; - cmdBufferTarget = count; - m_gpudState = GPUD_CMD_EXTRA; - size = 0; - } - break; - case GPUD_CMD_FILLING: - if (debugTransfers) - System.out.println("Next byte main command data at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); - m_cmdBuffer[cmdBufferUsed++] = mem[offset++]; - size--; - if (cmdBufferUsed == cmdBufferTarget) { - m_gpudState = GPUD_CMD_NONE; - GPUDRouter.invoke(m_cmdBuffer, 0, cmdBufferUsed); - } - break; - case GPUD_CMD_EXTRA: - if (debugTransfers) - System.out.println("extra command data at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); - int dwordsUsed = GPUDRouter.invoke(mem, offset, size); - assert (dwordsUsed <= size); - if (debugTransfers) System.out.println("consumed " + dwordsUsed); - size -= dwordsUsed; - offset += dwordsUsed; - break; - } - } - } - - private static AddressSpace.ResolveResult m_resolveResult = new AddressSpace.ResolveResult(); - - private static void handleGPUDataChain(int address) { - address &= 0xffffff; - int[] mainRAM = addressSpace.getMainRAM(); - while (address < AddressSpace.RAM_SIZE) { - int head = mainRAM[address >> 2]; - //System.out.println("HEAD "+MiscUtil.toHex( head, 8)); - int count = (head >> 24) & 0xff; - if (count > 0) { - handleGPUData(mainRAM, (address >> 2) + 1, count); - } - address = head & 0xffffff; - // TODO: maybe a temp thing - if ((address & 0xffffff) == 0) - break; - } - } - - public static final int makePixel(int val) { - // todo inline this - return makePixel((val & 0x1f) << 3, (val & 0x3e0) >> 2, (val & 0x7c00) >> 7, (val & 0x8000) >> 15); - } - - public static final int makePixel(int r, int g, int b, int mask) { - return (r << 16) | (g << 8) | b | (mask << 24); - } - - public static final int unmakePixel(int pixel) { - return ((pixel & 0xf8) << 7) | ((pixel & 0xf800) >> 6) | ((pixel & 0xf80000) >> 19) | ((pixel & 0x1000000) >> 9); - } - - private static JavaClass m_TemplateTClass; - private static JavaClass m_TemplateLClass; - private static JavaClass m_TemplateSClass; - private static JavaClass m_TemplateQClass; - private static JavaClass m_TemplateRClass; - - private JavaClass getTemplateTClass() { - if (m_TemplateTClass == null) { - String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer.class"; - final URL url = getClass().getClassLoader().getResource(filename); - try { - InputStream stream = url.openStream(); - try { - m_TemplateTClass = (new ClassParser(stream, filename)).parse(); - } finally { - stream.close(); - } - } catch (IOException e) { - } - } - return m_TemplateTClass.copy(); - } - - private JavaClass getTemplateSClass() { - if (m_TemplateSClass == null) { - String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateSpriteRenderer.class"; - final URL url = getClass().getClassLoader().getResource(filename); - try { - InputStream stream = url.openStream(); - try { - m_TemplateSClass = (new ClassParser(stream, filename)).parse(); - } finally { - stream.close(); - } - } catch (IOException e) { - } - } - return m_TemplateSClass.copy(); - } - - private JavaClass getTemplateQClass() { - if (m_TemplateQClass == null) { - String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateQuadRenderer.class"; - final URL url = getClass().getClassLoader().getResource(filename); - try { - InputStream stream = url.openStream(); - try { - m_TemplateQClass = (new ClassParser(stream, filename)).parse(); - } finally { - stream.close(); - } - } catch (IOException e) { - } - } - return m_TemplateQClass.copy(); - } - - private JavaClass getTemplateRClass() { - if (m_TemplateRClass == null) { - String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateRectangleRenderer.class"; - final URL url = getClass().getClassLoader().getResource(filename); - try { - InputStream stream = url.openStream(); - try { - m_TemplateRClass = (new ClassParser(stream, filename)).parse(); - } finally { - stream.close(); - } - } catch (IOException e) { - } - } - return m_TemplateRClass.copy(); - } - - private JavaClass getTemplateLClass() { - if (m_TemplateLClass == null) { - String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateLineRenderer.class"; - final URL url = getClass().getClassLoader().getResource(filename); - try { - InputStream stream = url.openStream(); - try { - m_TemplateLClass = (new ClassParser(stream, filename)).parse(); - } finally { - stream.close(); - } - } catch (IOException e) { - } - } - return m_TemplateLClass.copy(); - } - - // _T - // 0 no tex - // 4 4bit tex - // 8 8bit tex - // 6 16bit tex - // 0 non gouraud - // 1 gouraud - // 0 non-semi - // 1 5 plus 5 - // 2 10 plus 10 - // 3 10 minus 10 - // 4 10 plus 25 - // 0 no mask set - // 1 mask set - // 0 no mask check - // 1 mask check - // 0 non solid - // 1 solid - // TODO replace other occurences of field with their value - public ClassGen generateClass(String classname) { - ClassGen cgen; - String suffix = classname.substring(classname.indexOf("$_") + 2); - if (suffix.charAt(0) == 'T' || suffix.charAt(0) == 'L' || suffix.charAt(0) == 'S' || suffix.charAt(0) == 'Q' || suffix.charAt(0) == 'R') { - int targetTextureType; - switch (suffix.charAt(1)) { - case'0': - targetTextureType = TEXTURE_NONE; - break; - case'4': - targetTextureType = TEXTURE_4BIT; - break; - case'8': - targetTextureType = TEXTURE_8BIT; - break; - case'6': - targetTextureType = TEXTURE_16BIT; - break; - case'5': - targetTextureType = TEXTURE_4BITW; - break; - case'9': - targetTextureType = TEXTURE_8BITW; - break; - case'7': - targetTextureType = TEXTURE_16BITW; - break; - default: - throw new IllegalStateException("Unknown texture type " + suffix.charAt(1)); - } - boolean targetGouraud; - switch (suffix.charAt(2)) { - case'0': - targetGouraud = false; - break; - case'1': - targetGouraud = true; - break; - default: - throw new IllegalStateException("Unknown gouraud flag " + suffix.charAt(2)); - } - int targetSemi; - switch (suffix.charAt(3)) { - case'0': - targetSemi = SEMI_NONE; - break; - case'1': - targetSemi = SEMI_5P5; - break; - case'2': - targetSemi = SEMI_10P10; - break; - case'3': - targetSemi = SEMI_10M10; - break; - case'4': - targetSemi = SEMI_10P25; - break; - default: - throw new IllegalStateException("Unknown semi flag " + suffix.charAt(3)); - } - boolean targetMaskSet; - switch (suffix.charAt(4)) { - case'0': - targetMaskSet = false; - break; - case'1': - targetMaskSet = true; - break; - default: - throw new IllegalStateException("Unknown mask set flag " + suffix.charAt(4)); - } - boolean targetMaskCheck; - switch (suffix.charAt(5)) { - case'0': - targetMaskCheck = false; - break; - case'1': - targetMaskCheck = true; - break; - default: - throw new IllegalStateException("Unknown mask check flag " + suffix.charAt(5)); - } - boolean targetSolid; - switch (suffix.charAt(6)) { - case'0': - targetSolid = false; - break; - case'1': - targetSolid = true; - break; - default: - throw new IllegalStateException("Unknown solid flag " + suffix.charAt(6)); - } - - JavaClass jclass; - if (suffix.charAt(0) == 'T') { - jclass = getTemplateTClass(); - } else if (suffix.charAt(0) == 'L') { - jclass = getTemplateLClass(); - } else if (suffix.charAt(0) == 'S') { - jclass = getTemplateSClass(); - } else if (suffix.charAt(0) == 'R') { - jclass = getTemplateRClass(); - } else { - jclass = getTemplateQClass(); - } - String origClassName = jclass.getClassName(); - jclass.setFileName(JPSXClassLoader.getClassFilename(classname)); - cgen = new ClassGen(jclass); - ConstantPoolGen cp = cgen.getConstantPool(); - - // note for some reason this messes up jad - cgen.setClassName(classname); - if (suffix.charAt(0) == 'Q') { - int utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer"); - cp.setConstant(utfIndex, new ConstantUtf8(classname.replace('Q', 'T').replace('.', '/'))); - utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateRectangleRenderer"); - cp.setConstant(utfIndex, new ConstantUtf8(classname.replace('Q', 'R').replace('.', '/'))); - } else { - // replace the string constant itself - //int utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer"); - //cp.setConstant( utfIndex, new ConstantUtf8( classname.replace('.','/'))); - - - Field field = cgen.containsField("_renderTextureType"); - FieldGen fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetTextureType); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderSemiType"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetSemi); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderBReg"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetGouraud && (targetTextureType != TEXTURE_NONE)); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderGouraud"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetGouraud); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderCheckMask"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetMaskCheck); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderSetMask"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetMaskSet); - cgen.replaceField(field, fg.getField()); - - field = cgen.containsField("_renderSolid"); - fg = new FieldGen(field, cp); - fg.isFinal(true); - fg.cancelInitValue(); - fg.setInitValue(targetSolid); - cgen.replaceField(field, fg.getField()); - } - - // replace the class constant for the original class with our one, since it is used - // in GETSTATIC methods - cp.setConstant(cp.lookupClass(origClassName), cp.getConstant(cp.lookupClass(classname))); - return cgen; - } - throw new IllegalStateException("Unknown inner class to generate " + classname); - } - - // 0000 tiim rrrr rrrr gggg gggg bbbb bbbb - - public static void setVRAMFormat(boolean rgb24) { - if (!rgb24conversion) return; - if (rgb24 != GPU.rgb24) { - //System.out.println( "Convert VRAM to " + ((rgb24) ? "24 bit" : "15 bit") ); - GPU.rgb24 = rgb24; - int[] ram = display.acquireDisplayBuffer(); - if (rgb24) { - // G0B0 B1R0 R1G1 - // to: - // A_R0G0B0 B_R0G0B1 C_R1G1B1 - int last = 0; - for (int i = 0; i < 1024 * 512; i++) { - int pixel = ram[i]; - switch (pixel & GPU_RGBXX_X_MASK) { - case GPU_RGB15_A: { - int decoded = unmakePixel(pixel); - int decoded2 = unmakePixel(ram[i + 1]); - ram[i] = GPU_RGB24_A | decoded | ((decoded2 & 0xff) << 16); - last = decoded; - break; - } - case GPU_RGB15_B: { - int decoded = unmakePixel(pixel); - int pp = last | ((decoded & 0xff) << 16); - ram[i] = GPU_RGB24_B | (pp & 0xffff00) | ((decoded >> 8) & 0xff); - last = decoded; - break; - } - case GPU_RGB15_C: { - int decoded = unmakePixel(pixel); - ram[i] = GPU_RGB24_C | (decoded << 8) | ((last >> 8) & 0xff); - break; - } - } - } - } else { - // A_R0G0B0 B_R0G0B1 C_R1G1B1 - // to: - // G0B0 B1R0 R1G1 - for (int i = 0; i < 1024 * 512; i++) { - int pixel = ram[i]; - switch (pixel & GPU_RGBXX_X_MASK) { - case GPU_RGB24_A: { - ram[i] = GPU_RGB15_A | makePixel((pixel & 0xffff)); - break; - } - case GPU_RGB24_B: { - ram[i] = GPU_RGB15_B | makePixel(((pixel & 0xff) << 8) | ((pixel >> 16) & 0xff)); - break; - } - case GPU_RGB24_C: { - ram[i] = GPU_RGB15_C | makePixel(((pixel >> 8) & 0xffff)); - break; - } - } - } - } - display.releaseDisplayBuffer(); - } - } - - // Temporary hack to show stuff that is missing - we shoud do this with a system wide log4j channel - static int maxMissing = 10; - private static void missing(String s) { - if (maxMissing > 0) { - maxMissing --; - System.out.println("Missing "+s); - } - } -} - - diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java b/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java deleted file mode 100644 index 78a14e2..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java +++ /dev/null @@ -1,5599 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */package org.jpsx.runtime.components.hardware.gpu; - -/** - * Placeholder class enclosing rendering classes that are dynamically generated as needed at runtime. - * - * Each class represents a (quad/triangle/line/sprite) representer with one set of rendering options (e.g. - * palette size, semi-transparency, gouraud-ness, masking etc.) - * - * To save space the compiled class files are actually deleted by the build - */ -public class GPUGenerated { - - public static class _Q400000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q400111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q401111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q402111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q403111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q404111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q500111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q501111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q502111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q503111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q504111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q800111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q801111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q802111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q803111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q804111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q900111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q901111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q902111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q903111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q904111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q600000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q600010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q600100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q600110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q601000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q601010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q601100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q601110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q602000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q602010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q602100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q602110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q603000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q603010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q603100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q603110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q604000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q604010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q604100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q604110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q700000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q700010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q700100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q700110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q701000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q701010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q701100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q701110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q702000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q702010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q702100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q702110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q703000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q703010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q703100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q703110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q704000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q704010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q704100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q704110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q410111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q411111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q412111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q413111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q414111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q510111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q511111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q512111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q513111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q514111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q810111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q811111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q812111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q813111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q814111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q910111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q911111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q912111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q913111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q914111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q610000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q610010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q610100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q610110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q611000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q611010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q611100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q611110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q612000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q612010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q612100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q612110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q613000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q613010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q613100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q613110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q614000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q614010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q614100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q614110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q710000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q710010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q710100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q710110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q711000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q711010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q711100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q711110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q712000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q712010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q712100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q712110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q713000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q713010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q713100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q713110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q714000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q714010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q714100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q714110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q000000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q000010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q000100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q000110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q001000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q001010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q001100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q001110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q002000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q002010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q002100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q002110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q003000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q003010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q003100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q003110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q004000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q004010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q004100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q004110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q010000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q011000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q012000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q013000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _Q014000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { - } - } - - public static class _T010001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T010011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T010101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T010111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T400111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T401111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T402111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T403111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T404111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T410111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T411111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T412111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T413111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T414111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T500111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T501111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T502111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T503111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T504111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T510111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T511111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T512111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T513111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T514111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T000000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T000010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T000100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T000110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T001000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T001010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T001100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T001110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T002000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T002010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T002100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T002110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T003000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T003010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T003100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T003110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T004000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T004010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T004100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T004110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T010000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T011000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T012000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T013000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T014000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T800111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T801111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T802111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T803111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T804111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T810111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T811111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T812111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T813111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T814111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T900111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T901111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T902111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T903111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T904111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T910111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T911111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T912111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T913111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914001 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914011 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914101 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T914111 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T600000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T600010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T600100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T600110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T601000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T601010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T601100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T601110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T602000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T602010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T602100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T602110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T603000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T603010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T603100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T603110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T604000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T604010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T604100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T604110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T610000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T610010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T610100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T610110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T611000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T611010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T611100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T611110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T612000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T612010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T612100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T612110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T613000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T613010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T613100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T613110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T614000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T614010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T614100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T614110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T700000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T700010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T700100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T700110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T701000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T701010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T701100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T701110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T702000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T702010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T702100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T702110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T703000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T703010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T703100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T703110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T704000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T704010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T704100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T704110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T710000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T710010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T710100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T710110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T711000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T711010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T711100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T711110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T712000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T712010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T712100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T712110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T713000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T713010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T713100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T713110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T714000 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T714010 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T714100 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _T714110 { - public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { - } - } - - public static class _S000000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S000010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S000100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S000110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S001000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S001010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S001100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S001110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S002000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S002010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S002100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S002110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S003000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S003010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S003100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S003110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S004000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S004010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S004100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S004110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S400111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S401111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S402111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S403111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S404111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S500111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S501111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S502111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S503111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S504111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S800111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S801111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S802111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S803111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S804111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S900111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S901111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S902111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S903111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904001 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904011 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904101 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S904111 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S600000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S600010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S600100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S600110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S601000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S601010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S601100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S601110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S602000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S602010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S602100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S602110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S603000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S603010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S603100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S603110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S604000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S604010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S604100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S604110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S700000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S700010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S700100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S700110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S701000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S701010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S701100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S701110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S702000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S702010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S702100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S702110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S703000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S703010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S703100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S703110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S704000 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S704010 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S704100 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _S704110 { - public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { - } - } - - public static class _L010000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L010010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L010100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L010110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L000000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L000010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L000100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L000110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L001000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L001010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L001100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L001110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L002000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L002010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L002100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L002110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L003000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L003010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L003100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L003110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L004000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L004010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L004100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L004110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L011000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L011010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L011100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L011110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L012000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L012010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L012100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L012110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L013000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L013010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L013100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L013110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L014000 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L014010 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L014100 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } - - public static class _L014110 { - public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/gte/GTE.java b/src/runtime/java/org/jpsx/runtime/components/hardware/gte/GTE.java deleted file mode 100644 index 5cb7d56..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/gte/GTE.java +++ /dev/null @@ -1,3585 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.gte; - -import org.apache.bcel.generic.*; -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.*; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.util.ClassUtil; -import org.jpsx.runtime.util.MiscUtil; - -// TODO should vz be 16 bits only when read? - -public final class GTE extends JPSXComponent implements InstructionProvider { - private static final boolean debugLimit = false; - private static final boolean debugLimitB = false; - private static final boolean debugLimitG = false; - private static final boolean debugLimitD = false; - private static final Logger log = Logger.getLogger("GTE"); - private static final String CLASS = GTE.class.getName(); - private static final String VECTOR_CLASS = Vector.class.getName(); - private static final String VECTOR_SIGNATURE = ClassUtil.signatureOfClass(VECTOR_CLASS); - private static final String MATRIX_CLASS = Matrix.class.getName(); - private static final String MATRIX_SIGNATURE = ClassUtil.signatureOfClass(MATRIX_CLASS); - - private static final int R_VXY0 = 0; - private static final int R_VZ0 = 1; - private static final int R_VXY1 = 2; - private static final int R_VZ1 = 3; - private static final int R_VXY2 = 4; - private static final int R_VZ2 = 5; - private static final int R_RGB = 6; - private static final int R_OTZ = 7; - private static final int R_IR0 = 8; - private static final int R_IR1 = 9; - private static final int R_IR2 = 10; - private static final int R_IR3 = 11; - private static final int R_SXY0 = 12; - private static final int R_SXY1 = 13; - private static final int R_SXY2 = 14; - private static final int R_SXYP = 15; - private static final int R_SZX = 16; - private static final int R_SZ0 = 17; - private static final int R_SZ1 = 18; - private static final int R_SZ2 = 19; - private static final int R_RGB0 = 20; - private static final int R_RGB1 = 21; - private static final int R_RGB2 = 22; - private static final int R_RES1 = 23; - private static final int R_MAC0 = 24; - private static final int R_MAC1 = 25; - private static final int R_MAC2 = 26; - private static final int R_MAC3 = 27; - private static final int R_IRGB = 28; - private static final int R_ORGB = 29; - private static final int R_LZCS = 30; - private static final int R_LZCR = 31; - private static final int R_R11R12 = 32; - private static final int R_R13R21 = 33; - private static final int R_R22R23 = 34; - private static final int R_R31R32 = 35; - private static final int R_R33 = 36; - private static final int R_TRX = 37; - private static final int R_TRY = 38; - private static final int R_TRZ = 39; - private static final int R_L11L12 = 40; - private static final int R_L13L21 = 41; - private static final int R_L22L23 = 42; - private static final int R_L31L32 = 43; - private static final int R_L33 = 44; - private static final int R_RBK = 45; - private static final int R_GBK = 46; - private static final int R_BBK = 47; - private static final int R_LR1LR2 = 48; - private static final int R_LR3LG1 = 49; - private static final int R_LG2LG3 = 50; - private static final int R_LB1LB2 = 51; - private static final int R_LB3 = 52; - private static final int R_RFC = 53; - private static final int R_GFC = 54; - private static final int R_BFC = 55; - private static final int R_OFX = 56; - private static final int R_OFY = 57; - private static final int R_H = 58; - private static final int R_DQA = 59; - private static final int R_DQB = 60; - private static final int R_ZSF3 = 61; - private static final int R_ZSF4 = 62; - private static final int R_FLAG = 63; - - private static final int GTE_SF_MASK = 0x80000; - - private static final int GTE_MX_MASK = 0x60000; - private static final int GTE_MX_ROTATION = 0x00000; - private static final int GTE_MX_LIGHT = 0x20000; - private static final int GTE_MX_COLOR = 0x40000; - - private static final int GTE_V_MASK = 0x18000; - private static final int GTE_V_V0 = 0x00000; - private static final int GTE_V_V1 = 0x08000; - private static final int GTE_V_V2 = 0x10000; - private static final int GTE_V_IR = 0x18000; - - private static final int GTE_CV_MASK = 0x06000; - private static final int GTE_CV_TR = 0x00000; - private static final int GTE_CV_BK = 0x02000; - private static final int GTE_CV_FC = 0x04000; - private static final int GTE_CV_NONE = 0x06000; - - private static final int GTE_LM_MASK = 0x00400; - - private static final int GTE_ALL_MASKS = (GTE_SF_MASK | GTE_MX_MASK | GTE_V_MASK | GTE_CV_MASK | GTE_LM_MASK); - -// public static void setFlag( int bits) -// { -// reg_flag |= bits; -// -// // TODO check these flags! -// // CHK is set if any flag in 0x7FC7E000 is set -// // (A1-A3 B1-B3 D E FP FN G1 G2) -// -// if (0!=(bits & 0x7fc7e000)) { -// reg_flag|=FLAG_CHK; -// } -// } - -// removed above, and rolled FLAG_CHK into them automatically - - private static final int FLAG_CHK = 0x80000000; - private static final int FLAG_A1P = 0x40000000 | FLAG_CHK; - private static final int FLAG_A2P = 0x20000000 | FLAG_CHK; - private static final int FLAG_A3P = 0x10000000 | FLAG_CHK; - private static final int FLAG_A1N = 0x08000000 | FLAG_CHK; - private static final int FLAG_A2N = 0x04000000 | FLAG_CHK; - private static final int FLAG_A3N = 0x02000000 | FLAG_CHK; - private static final int FLAG_B1 = 0x01000000 | FLAG_CHK; - private static final int FLAG_B2 = 0x00800000 | FLAG_CHK; - private static final int FLAG_B3 = 0x00400000; - private static final int FLAG_C1 = 0x00200000; - private static final int FLAG_C2 = 0x00100000; - private static final int FLAG_C3 = 0x00080000; - private static final int FLAG_D = 0x00040000 | FLAG_CHK; - private static final int FLAG_E = 0x00020000 | FLAG_CHK; - private static final int FLAG_FP = 0x00010000 | FLAG_CHK; - private static final int FLAG_FN = 0x00008000 | FLAG_CHK; - private static final int FLAG_G1 = 0x00004000 | FLAG_CHK; - private static final int FLAG_G2 = 0x00002000 | FLAG_CHK; - private static final int FLAG_H = 0x00001000; - - private static final long BIT43 = 0x80000000000L; - private static final long BIT31 = 0x80000000L; - private static final long BIT47 = 0x800000000000L; - - public static class Vector { - public int x, y, z; - } - - public static class Matrix { - public int m11, m12, m13, m21, m22, m23, m31, m32, m33; - } - - /** - * Note with respect to internal registers that aren't signed 32 bit values on the playstation: - * - * All internal registers here are kept as signed 32 bit values. If the actual register on PSX is say a 16 bit signed value - * it is sign extended to 32 bits as part of the register write. If it is a 16 bit unsigned value, it is zero extended to 32 bits as - * part of the register write. - * - * Equally the reverse is done when reading GTE regs (i.e. a signed 32 bit internal value may only have 16 bits exposed) - */ - - public static Vector reg_v0 = new Vector(); - public static Vector reg_v1 = new Vector(); - public static Vector reg_v2 = new Vector(); - - public static int reg_rgb; - public static int reg_otz; - - public static int reg_ir0; - public static int reg_ir1; - public static int reg_ir2; - public static int reg_ir3; - - public static int reg_sx0; // checked - public static int reg_sy0; // checked - public static int reg_sx1; // checked - public static int reg_sy1; // checked - public static int reg_sx2; // checked - public static int reg_sy2; // checked - public static int reg_sxp; // checked - public static int reg_syp; // checked - - public static int reg_szx; // checked - public static int reg_sz0; // checked - public static int reg_sz1; // checked - public static int reg_sz2; // checked - public static int reg_rgb0; - public static int reg_rgb1; - public static int reg_rgb2; - public static int reg_res1; - public static int reg_mac0; - public static int reg_mac1; - public static int reg_mac2; - public static int reg_mac3; -// public static int reg_irgb; // checked -// public static int reg_orgb; // checked - public static int reg_lzcr; // checked - public static int reg_lzcs; // checked - - public static Matrix reg_rot = new Matrix(); - - public static int reg_trx; - public static int reg_try; - public static int reg_trz; - - public static Matrix reg_ls = new Matrix(); - public static int reg_rbk; - public static int reg_gbk; - public static int reg_bbk; - - public static Matrix reg_lc = new Matrix(); - public static int reg_rfc; - public static int reg_gfc; - public static int reg_bfc; - - public static int reg_ofx; - public static int reg_ofy; - public static int reg_h; - public static int reg_dqa; - public static int reg_dqb; - - public static int reg_zsf3; - public static int reg_zsf4; - public static int reg_flag; - - public GTE() { - super("JPSX Geometry Transform Engine"); - } - - private static AddressSpace addressSpace; - private static R3000 r3000; - private static int[] r3000regs; - - private static void emitReadReg(InstructionList il, CompilationContext context, int reg) { - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (reg < 32) { - switch (reg) { - case R_VXY0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_VZ0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_VXY1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_VZ1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_VXY2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_VZ2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_RGB: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb", "I"))); - break; - case R_OTZ: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_otz", "I"))); - break; - case R_IR0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir0", "I"))); - break; - case R_IR1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir1", "I"))); - break; - case R_IR2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir2", "I"))); - break; - case R_IR3: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir3", "I"))); - break; - case R_SXY0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx0", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy0", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_SXY1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx1", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy1", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_SXY2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx2", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy2", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_SXYP: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sxp", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_syp", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_SZX: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_szx", "I"))); - break; - case R_SZ0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz0", "I"))); - break; - case R_SZ1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz1", "I"))); - break; - case R_SZ2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz2", "I"))); - break; - case R_RGB0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb0", "I"))); - break; - case R_RGB1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb1", "I"))); - break; - case R_RGB2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb2", "I"))); - break; - case R_RES1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_res1", "I"))); - break; - case R_MAC0: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac0", "I"))); - break; - case R_MAC1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac1", "I"))); - break; - case R_MAC2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac2", "I"))); - break; - case R_MAC3: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac3", "I"))); - break; - case R_IRGB: - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "readIORGB", "()V"))); - break; - case R_ORGB: - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "readIORGB", "()V"))); - break; - case R_LZCS: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lzcs", "I"))); - break; - case R_LZCR: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lzcr", "I"))); - break; - } - } else { - switch (reg) { - case R_R11R12: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_R13R21: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_R22R23: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_R31R32: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_R33: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - break; - case R_TRX: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trx", "I"))); - break; - case R_TRY: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_try", "I"))); - break; - case R_TRZ: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trz", "I"))); - break; - case R_L11L12: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_L13L21: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_L22L23: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_L31L32: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_L33: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - break; - case R_RBK: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rbk", "I"))); - break; - case R_GBK: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gbk", "I"))); - break; - case R_BBK: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bbk", "I"))); - break; - case R_LR1LR2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_LR3LG1: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_LG2LG3: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_LB1LB2: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new IOR()); - break; - case R_LB3: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - break; - case R_RFC: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rfc", "I"))); - break; - case R_GFC: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gfc", "I"))); - break; - case R_BFC: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bfc", "I"))); - break; - case R_OFX: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofx", "I"))); - break; - case R_OFY: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofy", "I"))); - break; - case R_H: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_h", "I"))); - // this is according to docs that it is accidentally sign extended - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - break; - case R_DQA: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqa", "I"))); - break; - case R_DQB: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqb", "I"))); - break; - case R_ZSF3: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf3", "I"))); - break; - case R_ZSF4: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf4", "I"))); - break; - case R_FLAG: - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_flag", "I"))); - break; - } - } - } - - private static void emitWriteReg(InstructionList il, CompilationContext context, int reg) { - ConstantPoolGen cp = context.getConstantPoolGen(); - int temp = context.getTempLocal(0); - - if (reg < 32) { - switch (reg) { - case R_VXY0: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - break; - case R_VZ0: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_VXY1: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - break; - case R_VZ1: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_VXY2: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); - break; - case R_VZ2: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); - break; - case R_RGB: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb", "I"))); - break; - case R_OTZ: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_otz", "I"))); - break; - case R_IR0: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir0", "I"))); - break; - case R_IR1: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir1", "I"))); - break; - case R_IR2: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir2", "I"))); - break; - case R_IR3: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir3", "I"))); - break; - case R_SXY0: - il.append(new ISTORE(temp)); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx0", "I"))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy0", "I"))); - break; - case R_SXY1: - il.append(new ISTORE(temp)); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx1", "I"))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy1", "I"))); - break; - case R_SXY2: - il.append(new ISTORE(temp)); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx2", "I"))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy2", "I"))); - break; - case R_SZX: - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_szx", "I"))); - break; - case R_SZ0: - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz0", "I"))); - break; - case R_SZ1: - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz1", "I"))); - break; - case R_SZ2: - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz2", "I"))); - break; - case R_RGB0: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb0", "I"))); - break; - case R_RGB1: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb1", "I"))); - break; - case R_RGB2: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb2", "I"))); - break; - case R_RES1: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_res1", "I"))); - break; - case R_MAC0: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac0", "I"))); - break; - case R_MAC1: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac1", "I"))); - break; - case R_MAC2: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac2", "I"))); - break; - case R_MAC3: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac3", "I"))); - break; - case R_IRGB: - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeIRGB", "(I)V"))); - break; - case R_ORGB: - il.append(new POP()); // read only - break; - case R_LZCR: - il.append(new POP()); // read only - break; -// case R_LZCS: -// fall thru for writeRegister -// case R_SXYP: -// fall thru for writeRegister - default: - il.append(new ISTORE(temp)); - il.append(new PUSH(cp, reg)); - il.append(new ILOAD(temp)); -// il.append(new PUSH(cp, reg)); -// il.append(new SWAP()); - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeRegister", "(II)V"))); - break; - } - } else { - switch (reg) { - case R_R11R12: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - break; - case R_R13R21: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - break; - case R_R22R23: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - break; - case R_R31R32: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - break; - case R_R33: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); - break; - case R_TRX: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trx", "I"))); - break; - case R_TRY: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_try", "I"))); - break; - case R_TRZ: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trz", "I"))); - break; - case R_L11L12: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - break; - case R_L13L21: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - break; - case R_L22L23: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - break; - case R_L31L32: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - break; - case R_L33: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); - break; - case R_RBK: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rbk", "I"))); - break; - case R_GBK: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gbk", "I"))); - break; - case R_BBK: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bbk", "I"))); - break; - case R_LR1LR2: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); - break; - case R_LR3LG1: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); - break; - case R_LG2LG3: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); - break; - case R_LB1LB2: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); - break; - case R_LB3: - il.append(new ISTORE(temp)); - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); - il.append(new ILOAD(temp)); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); - break; - case R_RFC: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rfc", "I"))); - break; - case R_GFC: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gfc", "I"))); - break; - case R_BFC: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bfc", "I"))); - break; - case R_OFX: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofx", "I"))); - break; - case R_OFY: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofy", "I"))); - break; - case R_H: - il.append(new PUSH(cp, 0xffff)); - il.append(new IAND()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_h", "I"))); - break; - case R_DQA: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqa", "I"))); - break; - case R_DQB: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqb", "I"))); - break; - case R_ZSF3: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf3", "I"))); - break; - case R_ZSF4: - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf4", "I"))); - break; - case R_FLAG: - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_flag", "I"))); - break; - default: - il.append(new ISTORE(temp)); - il.append(new PUSH(cp, reg)); - il.append(new ILOAD(temp)); - il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeRegister", "(II)V"))); - break; - } - } - } - - public void init() { - super.init(); - CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - r3000 = CoreComponentConnections.R3000.resolve(); - r3000regs = r3000.getInterpreterRegs(); - } - - public void addInstructions(InstructionRegistrar registrar) { - log.info("Adding COP2 instructions..."); - i_mfc2 = new CPUInstruction("mfc2", GTE.class, 0, CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = R3000.Util.bits_rd(ci); - int rt = R3000.Util.bits_rt(ci); - - if (rt != 0) { - emitReadReg(il, context, rd); - context.emitSetReg(il, rt); - } - } - }; - i_cfc2 = new CPUInstruction("cfc2", GTE.class, 0, CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = R3000.Util.bits_rd(ci); - int rt = R3000.Util.bits_rt(ci); - - if (rt != 0) { - emitReadReg(il, context, rd + 32); - context.emitSetReg(il, rt); - } - } - }; - - i_mtc2 = new CPUInstruction("mtc2", GTE.class, 0, CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - emitWriteReg(il, context, rd); - } - }; - - i_ctc2 = new CPUInstruction("ctc2", GTE.class, 0, CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - emitWriteReg(il, context, rd + 32); - } - }; - i_lwc2 = new CPUInstruction("lwc2", GTE.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = R3000.Util.bits_rs(ci); - int rt = R3000.Util.bits_rt(ci); - int offset = R3000.Util.sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem32(il, context.getRegValue(base) + offset, false); - } else { - context.emitReadMem32(il, base, offset, false); - } - emitWriteReg(il, context, rt); - } - }; - i_swc2 = new CPUInstruction("swc2", GTE.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = R3000.Util.bits_rs(ci); - int rt = R3000.Util.bits_rt(ci); - int offset = R3000.Util.sign_extend(ci); - - InstructionList il2 = new InstructionList(); - emitReadReg(il2, context, rt); - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitWriteMem32(il, context.getRegValue(base) + offset, il2, false); - } else { - context.emitWriteMem32(il, base, offset, il2, false); - } - il2.dispose(); - } - }; - i_rtpt = new CPUInstruction("rtpt", GTE.class, 0, 0); - i_rtps = new CPUInstruction("rtps", GTE.class, 0, 0); - i_mvmva = new CPUInstruction("mvmva", GTE.class, 0, 0); - i_op = new CPUInstruction("op", GTE.class, 0, 0); - i_avsz3 = new CPUInstruction("avsz3", GTE.class, 0, 0); - i_avsz4 = new CPUInstruction("avsz4", GTE.class, 0, 0); - i_nclip = new CPUInstruction("nclip", GTE.class, 0, 0); - i_ncct = new CPUInstruction("ncct", GTE.class, 0, 0); - i_gpf = new CPUInstruction("gpf", GTE.class, 0, 0); - i_dcpl = new CPUInstruction("dcpl", GTE.class, 0, 0); - i_dpcs = new CPUInstruction("dpcs", GTE.class, 0, 0); - i_intpl = new CPUInstruction("intpl", GTE.class, 0, 0); - i_sqr = new CPUInstruction("sqr", GTE.class, 0, 0); - i_ncs = new CPUInstruction("ncs", GTE.class, 0, 0); - i_nct = new CPUInstruction("nct", GTE.class, 0, 0); - i_ncds = new CPUInstruction("ncds", GTE.class, 0, 0); - i_ncdt = new CPUInstruction("ncdt", GTE.class, 0, 0); - i_dpct = new CPUInstruction("dpct", GTE.class, 0, 0); - i_nccs = new CPUInstruction("nccs", GTE.class, 0, 0); - i_cdp = new CPUInstruction("cdp", GTE.class, 0, 0); - i_cc = new CPUInstruction("cc", GTE.class, 0, 0); - i_gpl = new CPUInstruction("gpl", GTE.class, 0, 0); - CPUInstruction i_cop2 = new CPUInstruction("cop2", GTE.class, 0, 0) { - public CPUInstruction subDecode(int ci) { - switch (R3000.Util.bits_rs(ci)) { - case 0: - return i_mfc2; - case 2: - return i_cfc2; - case 4: - return i_mtc2; - case 6: - return i_ctc2; - case 1: - case 3: - case 5: - case 7: - return r3000.getInvalidInstruction(); - } - switch (ci & 0x3f) { - case 0x01: - return i_rtps; - case 0x06: - return i_nclip; - case 0x0c: - return i_op; - case 0x10: - return i_dpcs; - case 0x11: - return i_intpl; - case 0x12: - return i_mvmva; - case 0x13: - return i_ncds; - case 0x14: - return i_cdp; - case 0x16: - return i_ncdt; - case 0x1b: - return i_nccs; - case 0x1c: - return i_cc; - case 0x1e: - return i_ncs; - case 0x20: - return i_nct; - case 0x28: - return i_sqr; - case 0x29: - return i_dcpl; - case 0x2a: - return i_dpct; - case 0x2d: - return i_avsz3; - case 0x2e: - return i_avsz4; - case 0x30: - return i_rtpt; - case 0x3d: - return i_gpf; - case 0x3e: - return i_gpl; - case 0x3f: - return i_ncct; - } - return r3000.getInvalidInstruction(); - } - }; - - registrar.setInstruction(18, i_cop2); - registrar.setInstruction(50, i_lwc2); - registrar.setInstruction(58, i_swc2); - } - - private static CPUInstruction i_mfc2; - private static CPUInstruction i_cfc2; - private static CPUInstruction i_mtc2; - private static CPUInstruction i_ctc2; - private static CPUInstruction i_lwc2; - private static CPUInstruction i_swc2; - private static CPUInstruction i_rtpt; - private static CPUInstruction i_rtps; - private static CPUInstruction i_mvmva; - private static CPUInstruction i_op; - private static CPUInstruction i_avsz3; - private static CPUInstruction i_avsz4; - private static CPUInstruction i_nclip; - private static CPUInstruction i_ncct; - private static CPUInstruction i_gpf; - private static CPUInstruction i_dcpl; - private static CPUInstruction i_dpcs; - private static CPUInstruction i_intpl; - private static CPUInstruction i_sqr; - private static CPUInstruction i_ncs; - private static CPUInstruction i_nct; - private static CPUInstruction i_ncds; - private static CPUInstruction i_ncdt; - private static CPUInstruction i_dpct; - private static CPUInstruction i_nccs; - private static CPUInstruction i_cdp; - private static CPUInstruction i_cc; - private static CPUInstruction i_gpl; - - public static void interpret_mfc2(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int value = readRegister(rd); - if (rt != 0) - r3000regs[rt] = value; - } - - public static int readRegister(final int reg) { - int value; - switch (reg) { - case R_VXY0: - value = (reg_v0.x & 0xffff) | ((reg_v0.y << 16) & 0xffff0000); - break; - case R_VZ0: - value = reg_v0.z; - break; - case R_VXY1: - value = (reg_v1.x & 0xffff) | ((reg_v1.y << 16) & 0xffff0000); - break; - case R_VZ1: - value = reg_v1.z; - break; - case R_VXY2: - value = (reg_v2.x & 0xffff) | ((reg_v2.y << 16) & 0xffff0000); - break; - case R_VZ2: - value = reg_v2.z; - break; - case R_RGB: - value = reg_rgb; - break; - case R_OTZ: - value = reg_otz; - break; - case R_IR0: - value = reg_ir0; - break; - case R_IR1: - value = reg_ir1; - break; - case R_IR2: - value = reg_ir2; - break; - case R_IR3: - value = reg_ir3; - break; - case R_SXY0: - value = (reg_sx0 & 0xffff) | ((reg_sy0 << 16) & 0xffff0000); - break; - case R_SXY1: - value = (reg_sx1 & 0xffff) | ((reg_sy1 << 16) & 0xffff0000); - break; - case R_SXY2: - value = (reg_sx2 & 0xffff) | ((reg_sy2 << 16) & 0xffff0000); - break; - case R_SXYP: - value = (reg_sxp & 0xffff) | ((reg_syp << 16) & 0xffff0000); - break; - case R_SZX: - value = reg_szx; - break; - case R_SZ0: - value = reg_sz0; - break; - case R_SZ1: - value = reg_sz1; - break; - case R_SZ2: - value = reg_sz2; - break; - case R_RGB0: - value = reg_rgb0; - break; - case R_RGB1: - value = reg_rgb1; - break; - case R_RGB2: - value = reg_rgb2; - break; - case R_RES1: - value = reg_res1; - break; - case R_MAC0: - value = reg_mac0; - break; - case R_MAC1: - value = reg_mac1; - break; - case R_MAC2: - value = reg_mac2; - break; - case R_MAC3: - value = reg_mac3; - break; - case R_IRGB: - value = readIORGB(); - break; - case R_ORGB: - value = readIORGB(); - break; - case R_LZCS: - value = reg_lzcs; - break; - case R_LZCR: - value = reg_lzcr; - break; - case R_R11R12: - value = (reg_rot.m11 & 0xffff) | ((reg_rot.m12 << 16) & 0xffff0000); - break; - case R_R13R21: - value = (reg_rot.m13 & 0xffff) | ((reg_rot.m21 << 16) & 0xffff0000); - break; - case R_R22R23: - value = (reg_rot.m22 & 0xffff) | ((reg_rot.m23 << 16) & 0xffff0000); - break; - case R_R31R32: - value = (reg_rot.m31 & 0xffff) | ((reg_rot.m32 << 16) & 0xffff0000); - break; - case R_R33: - value = (reg_rot.m33 & 0xffff); - break; - case R_TRX: - value = reg_trx; - break; - case R_TRY: - value = reg_try; - break; - case R_TRZ: - value = reg_trz; - break; - case R_L11L12: - value = (reg_ls.m11 & 0xffff) | ((reg_ls.m12 << 16) & 0xffff0000); - break; - case R_L13L21: - value = (reg_ls.m13 & 0xffff) | ((reg_ls.m21 << 16) & 0xffff0000); - break; - case R_L22L23: - value = (reg_ls.m21 & 0xffff) | ((reg_ls.m23 << 16) & 0xffff0000); - break; - case R_L31L32: - value = (reg_ls.m31 & 0xffff) | ((reg_ls.m32 << 16) & 0xffff0000); - break; - case R_L33: - value = (reg_ls.m33 & 0xffff); - break; - case R_RBK: - value = reg_rbk; - break; - case R_GBK: - value = reg_gbk; - break; - case R_BBK: - value = reg_bbk; - break; - case R_LR1LR2: - value = (reg_lc.m11 & 0xffff) | ((reg_lc.m12 << 16) & 0xffff0000); - break; - case R_LR3LG1: - value = (reg_lc.m13 & 0xffff) | ((reg_lc.m21 << 16) & 0xffff0000); - break; - case R_LG2LG3: - value = (reg_lc.m22 & 0xffff) | ((reg_lc.m23 << 16) & 0xffff0000); - break; - case R_LB1LB2: - value = (reg_lc.m31 & 0xffff) | ((reg_lc.m32 << 16) & 0xffff0000); - break; - case R_LB3: - value = (reg_lc.m33 & 0xffff); - break; - case R_RFC: - value = reg_rfc; - break; - case R_GFC: - value = reg_gfc; - break; - case R_BFC: - value = reg_bfc; - break; - case R_OFX: - value = reg_ofx; - break; - case R_OFY: - value = reg_ofy; - break; - case R_H: - // this is according to docs that it is accidentally sign extended - value = (reg_h << 16) >> 16; - break; - case R_DQA: - value = reg_dqa; - break; - case R_DQB: - value = reg_dqb; - break; - case R_ZSF3: - value = reg_zsf3; - break; - case R_ZSF4: - value = reg_zsf4; - break; - case R_FLAG: - value = reg_flag; - break; - default: - value = 0; - } - return value; - } - - public static void interpret_cfc2(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int value = readRegister(rd + 32); - if (rt != 0) - r3000regs[rt] = value; - } - - public static void writeIRGB(int value) { - reg_ir1 = (value&0x1f)<<7; - reg_ir2 = ((value>>5)&0x1f)<<7; - reg_ir3 = ((value>>10)&0x1f)<<7; - } - - public static int clampIR(int value) { - if (value < 0) { - value = 0; - } else { - value = value >> 7; - if (value > 0x1f) { - value = 0x1f; - } - } - return value; - } - - public static int readIORGB() { - return clampIR(reg_ir1)|(clampIR(reg_ir2)<<5)|(clampIR(reg_ir3)<<10); - } - - public static void writeRegister(int reg, int value) { - switch (reg) { - case R_VXY0: - reg_v0.x = (value << 16) >> 16; - reg_v0.y = value >> 16; - break; - case R_VZ0: - reg_v0.z = (value << 16) >> 16; - break; - case R_VXY1: - reg_v1.x = (value << 16) >> 16; - reg_v1.y = value >> 16; - break; - case R_VZ1: - reg_v1.z = (value << 16) >> 16; - break; - case R_VXY2: - reg_v2.x = (value << 16) >> 16; - reg_v2.y = value >> 16; - break; - case R_VZ2: - reg_v2.z = (value << 16) >> 16; - break; - case R_RGB: - reg_rgb = value; - break; - case R_OTZ: - reg_otz = value & 0xffff; // checked - break; - case R_IR0: - reg_ir0 = (value << 16) >> 16; // checked - break; - case R_IR1: - reg_ir1 = (value << 16) >> 16; // checked - break; - case R_IR2: - reg_ir2 = (value << 16) >> 16; // checked - break; - case R_IR3: - reg_ir3 = (value << 16) >> 16; // checked - break; - case R_SXY0: - reg_sx0 = (value << 16) >> 16; - reg_sy0 = value >> 16; - break; - case R_SXY1: - reg_sx1 = (value << 16) >> 16; - reg_sy1 = value >> 16; - break; - case R_SXY2: - reg_sx2 = (value << 16) >> 16; - reg_sy2 = value >> 16; - break; - case R_SXYP: - reg_sx0 = reg_sx1; - reg_sx1 = reg_sx2; - reg_sx2 = (value << 16) >> 16; - reg_sy0 = reg_sy1; - reg_sy1 = reg_sy2; - reg_sy2 = value >> 16; - break; - case R_SZX: - reg_szx = value & 0xffff; - break; - case R_SZ0: - reg_sz0 = value & 0xffff; - break; - case R_SZ1: - reg_sz1 = value & 0xffff; - break; - case R_SZ2: - reg_sz2 = value & 0xffff; - break; - case R_RGB0: - reg_rgb0 = value; - break; - case R_RGB1: - reg_rgb1 = value; - break; - case R_RGB2: - reg_rgb2 = value; - break; - case R_RES1: - reg_res1 = value; - break; - case R_MAC0: - reg_mac0 = value; - break; - case R_MAC1: - reg_mac1 = value; - break; - case R_MAC2: - reg_mac2 = value; - break; - case R_MAC3: - reg_mac3 = value; - break; - case R_IRGB: - writeIRGB(value); - break; - case R_ORGB: - // no op - break; - case R_LZCS: { - reg_lzcs = value; - /* - // old code for pre JDK5 - int mask = 0x80000000; - int comp = value & 0x80000000; - int bits; - - for (bits = 0; bits < 32; bits++) { - if ((value & mask) != comp) - break; - mask >>= 1; - comp >>= 1; - } - reg_lzcr = bits; - */ - reg_lzcr = Integer.numberOfLeadingZeros(value >= 0 ? value : ~value); - break; - } - case R_LZCR: - // lzcr is read only - // no op - break; - case R_R11R12: - reg_rot.m11 = (value << 16) >> 16; - reg_rot.m12 = value >> 16; - break; - case R_R13R21: - reg_rot.m13 = (value << 16) >> 16; - reg_rot.m21 = value >> 16; - break; - case R_R22R23: - reg_rot.m22 = (value << 16) >> 16; - reg_rot.m23 = value >> 16; - break; - case R_R31R32: - reg_rot.m31 = (value << 16) >> 16; - reg_rot.m32 = value >> 16; - break; - case R_R33: - reg_rot.m33 = (value << 16) >> 16; - break; - case R_TRX: - reg_trx = value; - break; - case R_TRY: - reg_try = value; - break; - case R_TRZ: - reg_trz = value; - break; - case R_L11L12: - reg_ls.m11 = (value << 16) >> 16; - reg_ls.m12 = value >> 16; - break; - case R_L13L21: - reg_ls.m13 = (value << 16) >> 16; - reg_ls.m21 = value >> 16; - break; - case R_L22L23: - reg_ls.m22 = (value << 16) >> 16; - reg_ls.m23 = value >> 16; - break; - case R_L31L32: - reg_ls.m31 = (value << 16) >> 16; - reg_ls.m32 = value >> 16; - break; - case R_L33: - reg_ls.m33 = (value << 16) >> 16; - break; - case R_RBK: - reg_rbk = value; - break; - case R_GBK: - reg_gbk = value; - break; - case R_BBK: - reg_bbk = value; - break; - case R_LR1LR2: - reg_lc.m11 = (value << 16) >> 16; - reg_lc.m12 = value >> 16; - break; - case R_LR3LG1: - reg_lc.m13 = (value << 16) >> 16; - reg_lc.m21 = value >> 16; - break; - case R_LG2LG3: - reg_lc.m22 = (value << 16) >> 16; - reg_lc.m23 = value >> 16; - break; - case R_LB1LB2: - reg_lc.m31 = (value << 16) >> 16; - reg_lc.m32 = value >> 16; - break; - case R_LB3: - reg_lc.m33 = (value << 16) >> 16; - break; - case R_RFC: - reg_rfc = value; - break; - case R_GFC: - reg_gfc = value; - break; - case R_BFC: - reg_bfc = value; - break; - case R_OFX: - reg_ofx = value; - break; - case R_OFY: - reg_ofy = value; - break; - case R_H: - reg_h = value & 0xffff; - break; - case R_DQA: - reg_dqa = (value << 16) >> 16; - break; - case R_DQB: - reg_dqb = value; - break; - case R_ZSF3: - reg_zsf3 = (value << 16) >> 16; - break; - case R_ZSF4: - reg_zsf4 = (value << 16) >> 16; - break; - case R_FLAG: - reg_flag = value; - break; - } - } - - public static void interpret_mtc2(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int value = r3000regs[rt]; - - writeRegister(rd, value); - } - - public static void interpret_ctc2(final int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int value = r3000regs[rt]; - - writeRegister(rd + 32, value); - } - - public static void interpret_cop2(final int ci) { - switch (R3000.Util.bits_rs(ci)) { - case 0: - GTE.interpret_mfc2(ci); - return; - case 2: - GTE.interpret_cfc2(ci); - return; - case 4: - GTE.interpret_mtc2(ci); - return; - case 6: - GTE.interpret_ctc2(ci); - return; - case 1: - case 3: - case 5: - case 7: - break; - default: - switch (ci & 0x3f) { - case 0x01: - GTE.interpret_rtps(ci); - return; - case 0x06: - GTE.interpret_nclip(ci); - return; - case 0x0c: - GTE.interpret_op(ci); - return; - case 0x10: - GTE.interpret_dpcs(ci); - return; - case 0x11: - GTE.interpret_intpl(ci); - return; - case 0x12: - GTE.interpret_mvmva(ci); - return; - case 0x13: - GTE.interpret_ncds(ci); - return; - case 0x14: - GTE.interpret_cdp(ci); - return; - case 0x16: - GTE.interpret_ncdt(ci); - return; - case 0x1b: - GTE.interpret_nccs(ci); - return; - case 0x1c: - GTE.interpret_cc(ci); - return; - case 0x1e: - GTE.interpret_ncs(ci); - return; - case 0x20: - GTE.interpret_nct(ci); - return; - case 0x28: - GTE.interpret_sqr(ci); - return; - case 0x29: - GTE.interpret_dcpl(ci); - return; - case 0x2a: - GTE.interpret_dpct(ci); - return; - case 0x2d: - GTE.interpret_avsz3(ci); - return; - case 0x2e: - GTE.interpret_avsz4(ci); - return; - case 0x30: - GTE.interpret_rtpt(ci); - return; - case 0x3d: - GTE.interpret_gpf(ci); - return; - case 0x3e: - GTE.interpret_gpl(ci); - return; - case 0x3f: - GTE.interpret_ncct(ci); - return; - } - } - CoreComponentConnections.SCP.resolve().signalReservedInstructionException(); - } - - public static void interpret_lwc2(final int ci) { - int base = R3000.Util.bits_rs(ci); - int rt = R3000.Util.bits_rt(ci); - int offset = (ci << 16) >> 16; - int addr = r3000regs[base] + offset; - addressSpace.tagAddressAccessRead32(r3000.getPC(), addr); - writeRegister(rt, addressSpace.read32(addr)); - } - - public static void interpret_swc2(final int ci) { - int base = R3000.Util.bits_rs(ci); - int rt = R3000.Util.bits_rt(ci); - int offset = (ci << 16) >> 16; - int addr = r3000regs[base] + offset; - addressSpace.tagAddressAccessWrite(r3000.getPC(), addr); - addressSpace.write32(addr, readRegister(rt)); - } - - public static void interpret_rtpt(final int ci) { - reg_flag = 0; - - // todo is no SF bit allowed? - if (0 == (ci & GTE_SF_MASK)) { - log.warn("RTPS with SF field!"); - } - - long vx = reg_v0.x; - long vy = reg_v0.y; - long vz = reg_v0.z; - - reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); - reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); - reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - reg_sz0 = LiD(reg_mac3); - if (debugLimit && reg_sz0 == 0) { - MiscUtil.assertionMessage("rtpt overflow 0"); - } - - - long hsz = LiE(divide(reg_h, reg_sz0)); - reg_sx0 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); - reg_sy0 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); - reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); - reg_ir0 = LiH(reg_mac0); - - // --------------------------------------------------- - - vx = reg_v1.x; - vy = reg_v1.y; - vz = reg_v1.z; - - reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); - reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); - reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - reg_sz1 = LiD(reg_mac3); - - if (debugLimit && reg_sz1 == 0) { - MiscUtil.assertionMessage("rtpt overflow 1"); - } - - hsz = LiE(divide(reg_h, reg_sz1)); - reg_sx1 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); - reg_sy1 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); - reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); - reg_ir0 = LiH(reg_mac0); - - // --------------------------------------------------- - - vx = reg_v2.x; - vy = reg_v2.y; - vz = reg_v2.z; - - reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); - reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); - reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - reg_sz2 = LiD(reg_mac3); - - if (debugLimit && reg_sz2 == 0) { - MiscUtil.assertionMessage("rtpt overflow 2"); - } - - hsz = LiE(divide(reg_h, reg_sz2)); - reg_sx2 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); - reg_sy2 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); - reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); - reg_ir0 = LiH(reg_mac0); - } - - public static void interpret_rtps(final int ci) { -// In: V0 Vector to transform. [1,15,0] -// R Rotation matrix [1,3,12] -// TR Translation vector [1,31,0] -// H View plane distance [0,16,0] -// DQA Depth que interpolation values. [1,7,8] -// DQB [1,7,8]OFX Screen offset values. [1,15,16] -// OFY [1,15,16] -// Out: SXY fifo Screen XY coordinates.(short) [1,15,0] -// SZ fifo Screen Z coordinate.(short) [0,16,0] -// IR0 Interpolation value for depth queing. [1,3,12] -// IR1 Screen X (short) [1,15,0] -// IR2 Screen Y (short) [1,15,0] -// IR3 Screen Z (short) [1,15,0] -// MAC1 Screen X (long) [1,31,0] -// MAC2 Screen Y (long) [1,31,0] -// MAC3 Screen Z (long) [1,31,0] -// Calculation: -// [1,31,0] MAC1=A1[TRX + R11*VX0 + R12*VY0 + R13*VZ0] [1,31,12] -// [1,31,0] MAC2=A2[TRY + R21*VX0 + R22*VY0 + R23*VZ0] [1,31,12] -// [1,31,0] MAC3=A3[TRZ + R31*VX0 + R32*VY0 + R33*VZ0] [1,31,12] -// [1,15,0] IR1= Lm_B1[MAC1] [1,31,0] -// [1,15,0] IR2= Lm_B2[MAC2] [1,31,0] -// [1,15,0] IR3= Lm_B3[MAC3] [1,31,0] -// SZ0<-SZ1<-SZ2<-SZ3 -// [0,16,0] SZ3= Lm_D(MAC3) [1,31,0] -// SX0<-SX1<-SX2, SY0<-SY1<-SY2 -// [1,15,0] SX2= Lm_G1[F[OFX + IR1*(H/SZ)]] [1,27,16] -// [1,15,0] SY2= Lm_G2[F[OFY + IR2*(H/SZ)]] [1,27,16] -// [1,31,0] MAC0= F[DQB + DQA * (H/SZ)] [1,19,24] -// [1,15,0] IR0= Lm_H[MAC0] [1,31,0] - - // or - - -// IR1 = MAC1 = (TRX*1000h + RT11*VX0 + RT12*VY0 + RT13*VZ0) SAR (sf*12) -// IR2 = MAC2 = (TRY*1000h + RT21*VX0 + RT22*VY0 + RT23*VZ0) SAR (sf*12) -// IR3 = MAC3 = (TRZ*1000h + RT31*VX0 + RT32*VY0 + RT33*VZ0) SAR (sf*12) -// SZ3 = MAC3 SAR ((1-sf)*12) ;ScreenZ FIFO 0..+FFFFh -// MAC0=(((H*20000h/SZ3)+1)/2)*IR1+OFX, SX2=MAC0/10000h ;ScrX FIFO -400h..+3FFh -// MAC0=(((H*20000h/SZ3)+1)/2)*IR2+OFY, SY2=MAC0/10000h ;ScrY FIFO -400h..+3FFh -// MAC0=(((H*20000h/SZ3)+1)/2)*DQA+DQB, IR0=MAC0/1000h ;Depth cueing 0..+1000h - - reg_flag = 0; - - long vx = reg_v0.x; - long vy = reg_v0.y; - long vz = reg_v0.z; - - // todo is no SF bit allowed? - if (0 == (ci & GTE_SF_MASK)) { - log.warn("RTPS with SF field!"); - } - reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); - reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); - reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - reg_szx = reg_sz0; - reg_sz0 = reg_sz1; - reg_sz1 = reg_sz2; - reg_sz2 = LiD(reg_mac3); - - reg_sx0 = reg_sx1; - reg_sy0 = reg_sy1; - reg_sx1 = reg_sx2; - reg_sy1 = reg_sy2; - - if (debugLimit && reg_sz2 == 0) { - MiscUtil.assertionMessage("rtps overflow"); - } - - long hsz = LiE(divide(reg_h, reg_sz2)); - // [1,15,0] SX2= LG1[F[OFX + IR1*(H/SZ)]] [1,27,16] - reg_sx2 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); - // [1,15,0] SY2= LG2[F[OFY + IR2*(H/SZ)]] [1,27,16] - reg_sy2 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); - // [1,31,0] MAC0= F[DQB + DQA * (H/SZ)] [1,19,24] - reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); - - // [1,15,0] IR0= LH[MAC0] [1,31,0] - reg_ir0 = LiH(reg_mac0); - } - - public static long SIGNED_BIG(int src) { - if (src == 0) - return 0; - if (src > 0) - return 0x10000000000000L; - return -0x10000000000000L; - } - - public static void interpret_mvmva(final int ci) { -// Fields: sf, cv, lm -// R/LLM/LCM Rotation, light or color matrix. [1,3,12] -// TR/BK Translation or background color vector. -// out: [IR1,IR2,IR3] Short vector -// [MAC1,MAC2,MAC3] Long vector -// Calculation: -// MAC1=A1[CV1 + MX11*V1 + MX12*V2 + MX13*V3] -// MAC2=A2[CV2 + MX21*V1 + MX22*V2 + MX23*V3] -// MAC3=A3[CV3 + MX31*V1 + MX32*V2 + MX33*V3] -// IR1=Lm_B1[MAC1] -// IR2=Lm_B2[MAC2] -// IR3=Lm_B3[MAC3] -// Notes: -// The cv field allows selection of the far color vector, but this vector -// is not added correctly by the GTE. - - -// NOTE: int64/A1,A2,A3 can only happen with IR I think - - reg_flag = 0; - - Matrix matrix; - switch (ci & GTE_MX_MASK) { - case GTE_MX_LIGHT: - matrix = reg_ls; - break; - case GTE_MX_COLOR: - matrix = reg_lc; - break; - default: - matrix = reg_rot; - break; - } - - long vx; - long vy; - long vz; - switch (ci & GTE_V_MASK) { - case GTE_V_IR: - vx = reg_ir1; - vy = reg_ir2; - vz = reg_ir3; - break; - case GTE_V_V2: - vx = reg_v2.x; - vy = reg_v2.y; - vz = reg_v2.z; - break; - case GTE_V_V1: - vx = reg_v1.x; - vy = reg_v1.y; - vz = reg_v1.z; - break; - default: - vx = reg_v0.x; - vy = reg_v0.y; - vz = reg_v0.z; - break; - } - - // v values s15.0 or s31.0 (s19.12 in SF case?) - - long ssx = matrix.m11 * vx + matrix.m12 * vy + matrix.m13 * vz; - long ssy = matrix.m21 * vx + matrix.m22 * vy + matrix.m23 * vz; - long ssz = matrix.m31 * vx + matrix.m32 * vy + matrix.m33 * vz; - - if (0 != (ci & GTE_SF_MASK)) { - ssx >>= 12; - ssy >>= 12; - ssz >>= 12; - } - - // ss values are up to about s36.12 - switch (ci & GTE_CV_MASK) { - case GTE_CV_TR: - ssx += reg_trx; - ssy += reg_try; - ssz += reg_trz; - break; - case GTE_CV_BK: - ssx += reg_rbk; - ssy += reg_gbk; - ssz += reg_bbk; - break; - case GTE_CV_FC: - ssx += reg_rfc; - ssy += reg_gfc; - ssz += reg_bfc; - break; - default: - break; - } - - reg_mac1 = A1(ssx << 12); - reg_mac2 = A2(ssy << 12); - reg_mac3 = A3(ssz << 12); - - if (0 != (ci & GTE_LM_MASK)) { - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - } else { - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - } - } - - public static int LiB1_0(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B1; - if (debugLimitB) log.info("B1_0 + "+src); - return 0x7fff; - } else if (src < -0x8000) { - reg_flag |= FLAG_B1; - if (debugLimitB) log.info("B1_0 - "+src); - return -0x8000; - } - return src; - } - - - public static int LiB1_1(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B1; - if (debugLimitB) log.info("B1_1 + "+src); - return 0x7fff; - } else if (src < 0) { - reg_flag |= FLAG_B1; - if (debugLimitB) log.info("B1_1 0 "+src); - return 0; - } - return src; - } - - public static int LiB2_0(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B2; - if (debugLimitB) log.info("B2_0 + "+src); - return 0x7fff; - } else if (src < -0x8000) { - reg_flag |= FLAG_B2; - if (debugLimitB) log.info("B2_0 - "+src); - return -0x8000; - } - return src; - } - - public static int LiB2_1(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B2; - if (debugLimitB) log.info("B2_1 + "+src); - return 0x7fff; - } else if (src < 0) { - reg_flag |= FLAG_B2; - if (debugLimitB) log.info("B2_1 0 "+src); - return 0; - } - return src; - } - - public static int LiB3_0(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B3; - if (debugLimitB) log.info("B3_0 + "+src); - return 0x7fff; - } else if (src < -0x8000) { - reg_flag |= FLAG_B3; - if (debugLimitB) log.info("B3_0 - "+src); - return -0x8000; - } - return src; - } - - public static int LiB3_1(int src) { - if (src >= 0x8000) { - reg_flag |= FLAG_B3; - if (debugLimitB) log.info("B3_1 + "+src); - return 0x7fff; - } else if (src < 0) { - reg_flag |= FLAG_B3; - if (debugLimitB) log.info("B3_1 0 "+src); - return 0; - } - return src; - } - - public static int LiC1(int src) { - if (src < 0) { - reg_flag |= FLAG_C1; - return 0; - } else if (src > 0xfff) { - reg_flag |= FLAG_C1; - return 0xff; - } - return src>>4; - } - - public static int LiC2(int src) { - if (src < 0) { - reg_flag |= FLAG_C2; - return 0; - } else if (src > 0xfff) { - reg_flag |= FLAG_C2; - return 0xff; - } - return src>>4; - } - - public static int LiC3(int src) { - if (src < 0) { - reg_flag |= FLAG_C3; - return 0; - } else if (src > 0xfff) { - reg_flag |= FLAG_C3; - return 0xff; - } - return src>>4; - } - - public static int LiD(int src) { - if (src < 0) { - reg_flag |= FLAG_D; - if (debugLimitD) log.info("D 0 "+src); - return 0; - } else if (src >= 0x10000) { - reg_flag |= FLAG_D; - if (debugLimitD) log.info("D + "+src); - return 0xffff; - } - return src; - } - - private static int LiE(int src) { - if (src >= 0x20000) { - reg_flag |= FLAG_E; - src = 0x1ffff; - } - return src; - } - - private static int LiF(long src) { - if (src >= BIT47) { - reg_flag |= FLAG_FP; - if (debugLimit) log.info("F + "+src); -// return 0x7fffffff; - } else if (src <= -BIT47) { - reg_flag |= FLAG_FN; - if (debugLimit) log.info("F - "+src); -// return 0x80000000; - } - return (int) (src >> 16); - } - - public static int LiG1(int src) { - if (src >= 0x400) { - reg_flag |= FLAG_G1; - if (debugLimitG) log.info("G1 + "+src); - return 0x3ff; - } else if (src < -0x400) { - reg_flag |= FLAG_G1; - if (debugLimitG) log.info("G1 - "+src); - return -0x400; - } - return src; - } - - public static int LiG2(int src) { - if (src >= 0x400) { - reg_flag |= FLAG_G2; - if (debugLimitG) log.info("G2 + "+src); - return 0x3ff; - } else if (src < -0x400) { - reg_flag |= FLAG_G2; - if (debugLimitG) log.info("G2 - "+src); - return -0x400; - } - return src; - } - - public static int LiH(int src) { - if (src >= 0x1000) { - reg_flag |= FLAG_H; -// if (debugLimit) log.info("H "+src); - return 0xfff; - } else if (src < 0) { - reg_flag |= FLAG_H; -// if (debugLimit) log.info("H "+src); - return 0; - } - return src; - } - - private static int A1(long val) { - if (val >= BIT43) { - reg_flag |= FLAG_A1P; - } else if (val <= -BIT43) { - reg_flag |= FLAG_A1N; - } - return (int) (val >> 12); - } - - private static int A2(long val) { - if (val >= BIT43) { - reg_flag |= FLAG_A2P; - } else if (val <= -BIT43) { - reg_flag |= FLAG_A2N; - } - return (int) (val >> 12); - } - - private static long mac3_64; - - private static int A3(long val) { - if (val >= BIT43) { - reg_flag |= FLAG_A3P; - } else if (val <= -BIT43) { - reg_flag |= FLAG_A3N; - } - return (int) (val >> 12); - } - - public static void interpret_op(final int ci) { - // checked except todo unclear whether lm is supported - added here -// Fields: sf -// in: [R11R12,R22R23,R33] vector 1 -// [IR1,IR2,IR3] vector 2 -// out: [IR1,IR2,IR3] outer product -// [MAC1,MAC2,MAC3] outer product -// Calculation: (D1=R11R12,D2=R22R23,D3=R33) -// MAC1=A1[D2*IR3 - D3*IR2] -// MAC2=A2[D3*IR1 - D1*IR3] -// MAC3=A3[D1*IR2 - D2*IR1] -// IR1=Lm_B1[MAC0] -// IR2=Lm_B2[MAC1] -// IR3=Lm_B3[MAC2] - reg_flag = 0; - - long a1 = reg_rot.m11; - long a2 = reg_rot.m22; - long a3 = reg_rot.m33; - - long ss1 = a2 * reg_ir3 - a3 * reg_ir2; - long ss2 = a3 * reg_ir1 - a1 * reg_ir3; - long ss3 = a1 * reg_ir2 - a2 * reg_ir1; - - if (0 == (ci & GTE_SF_MASK)) { - ss1 <<= 12; - ss2 <<= 12; - ss3 <<= 12; - } - - reg_mac1 = A1(ss1); - reg_mac2 = A2(ss2); - reg_mac3 = A3(ss3); - if (0 != (ci & GTE_LM_MASK)) { - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - } else { - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - } - } - - public static void interpret_avsz3(final int ci) { - // checked -// in: SZ1, SZ2, SZ3 Z-Values [0,16,0] -// ZSF3 Divider [1,3,12] -// out: OTZ Average. [0,16,0] -// MAC0 Average. [1,31,0] -// Calculation: -// [1,31,0] MAC0=F[ZSF3*SZ1 + ZSF3*SZ2 + ZSF3*SZ3] [1,31,12] -// [0,16,0] OTZ=Lm_D[MAC0] [1,31,0] - - reg_flag = 0; - reg_mac0 = LiF(reg_zsf3 * (long)((reg_sz0 + reg_sz1 + reg_sz2)<<4)); - reg_otz = LiD(reg_mac0); - } - - public static void interpret_avsz4(final int ci) { - // checked -// Fields: -// in: SZ1,SZ2,SZ3,SZ4 Z-Values [0,16,0] -// ZSF4 Divider [1,3,12] -// out: OTZ Average. [0,16,0] -// MAC0 Average. [1,31,0] -// Calculation: -// [1,31,0] MAC0=F[ZSF4*SZ0 + ZSF4*SZ1 + ZSF4*SZ2 + ZSF4*SZ3] [1,31,12] -// [0,16,0] OTZ=Lm_D[MAC0] [1,31,0] - - reg_flag = 0; - reg_mac0 = LiF(reg_zsf4 * (long)((reg_sz0 + reg_sz1 + reg_sz2 + reg_szx)<<4)); - reg_otz = LiD(reg_mac0); - } - - public static void interpret_nclip(final int ci) { - /* - NOTE: I don't think nclip should clear the FLAG register. - - In Tomb Raider, there is code which looks something like this: - RTPT - NCLIP - f = gte->R_FLAG - if (f & 0x7fc7e000) goto skip_polygon; - - Since the RTPT can only set SX0,SX1,SX2,SY0,SY1,SY2 to values in the - range -0x800 to 0x800, there is no way NCLIP's calculation can overflow. - Hence, if NCLIP clears the FLAG register there is no way the branch - in the above code can ever be taken. - Whereas, if NCLIP _doesn't_ clear the FLAG, the above code actually - makes sense. - */ - reg_flag = 0; - - // [1,31,0] MAC0 = F[SX0*SY1+SX1*SY2+SX2*SY0-SX0*SY2-SX1*SY0-SX2*SY1] [1,43,0] - // @@ not too worried about liF() here... - reg_mac0 = reg_sx0 * reg_sy1 + reg_sx1 * reg_sy2 + reg_sx2 * reg_sy0 - - reg_sx0 * reg_sy2 - reg_sx1 * reg_sy0 - reg_sx2 * reg_sy1; - } - - public static void interpret_ncct(final int ci) { - // untested - reg_flag = 0; - - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - long ss1 = m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z; - long ss2 = m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z; - long ss3 = m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z; - - int mac1 = A1(ss1); - int mac2 = A2(ss2); - int mac3 = A3(ss3); - - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); - ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); - ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - mac1 = A1(r * ir1); - mac2 = A2(g * ir2); - mac3 = A3(b * ir3); - - int rr = LiC1(mac1); - int gg = LiC2(mac2); - int bb = LiC3(mac3); - reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; - - // 2 - ss1 = m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z; - ss2 = m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z; - ss3 = m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z; - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); - ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); - ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - mac1 = A1(r * ir1); - mac2 = A2(g * ir2); - mac3 = A3(b * ir3); - - // gcs 011802 added >>4 - rr = LiC1(mac1); - gg = LiC2(mac2); - bb = LiC3(mac3); - reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; - - // 3 - ss1 = m11 * reg_v2.x + m12 * reg_v2.y + m13 * reg_v2.z; - ss2 = m21 * reg_v2.x + m22 * reg_v2.y + m23 * reg_v2.z; - ss3 = m31 * reg_v2.x + m32 * reg_v2.y + m33 * reg_v2.z; - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); - ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); - ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - reg_mac1 = A1(r * ir1); - reg_mac2 = A2(g * ir2); - reg_mac3 = A3(b * ir3); - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - - // gcs 011802 added >>4 - rr = LiC1(reg_mac1); - gg = LiC2(reg_mac2); - bb = LiC3(reg_mac3); - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_gpf(final int ci) { - reg_flag = 0; - // MAC1=A1[IR0 * IR1] - // MAC2=A2[IR0 * IR2] - // MAC3=A3[IR0 * IR3] - // IR1=LB1[MAC1] - // IR2=LB2[MAC2] - // IR3=LB3[MAC3] - //[0,8,0] Cd0<-Cd1<-Cd2<- CODE - //[0,8,0] R0<-R1<-R2<- LC1[MAC1] - //[0,8,0] G0<-G1<-G2<- LC2[MAC2] - //[0,8,0] B0<-B1<-B2<- LC3[MAC3] - - long m = reg_ir0; - if (0 != (ci & GTE_SF_MASK)) { - reg_mac1 = A1(m * reg_ir1); - reg_mac2 = A2(m * reg_ir2); - reg_mac3 = A3(m * reg_ir3); - } else { - reg_mac1 = A1((m * reg_ir1) << 12); - reg_mac2 = A2((m * reg_ir2) << 12); - reg_mac3 = A3((m * reg_ir3) << 12); - } - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); - } - - public static void interpret_dcpl(final int ci) { - -// In: RGB Primary color. R,G,B,CODE [0,8,0] -// IR0 interpolation value. [1,3,12] -// [IR1,IR2,IR3] Local color vector. [1,3,12] -// CODE Code value from RGB. CODE [0,8,0] -// FC Far color. [1,27,4] -// Out: RGBn RGB fifo Rn,Gn,Bn,CDn [0,8,0] -// [IR1,IR2,IR3] Color vector [1,11,4] -// [MAC1,MAC2,MAC3] Color vector [1,27,4] -// Calculation: -// [1,27,4] MAC1=A1[R*IR1 + IR0*(Lm_B1[RFC-R* IR1])] [1,27,16] -// [1,27,4] MAC2=A2[G*IR2 + IR0*(Lm_B1[GFC-G* IR2])] [1,27,16] -// [1,27,4] MAC3=A3[B*IR3 + IR0*(Lm_B1[BFC-B* IR3])] [1,27,16] -// [1,11,4] IR1=Lm_B1[MAC1] [1,27,4] -// [1,11,4] IR2=Lm_B2[MAC2] [1,27,4] -// [1,11,4] IR3=Lm_B3[MAC3] [1,27,4] -// [0,8,0] Cd0<-Cd1<-Cd2<- CODE -// [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] -// [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] -// [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] - - reg_flag = 0; - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - // TODO - is this B1 all the way correct? - reg_mac1 = A1(r * reg_ir1 + reg_ir0 * LiB1_0(reg_rfc - ((r * reg_ir1) >> 12))); - reg_mac2 = A2(g * reg_ir2 + reg_ir0 * LiB1_0(reg_gfc - ((g * reg_ir2) >> 12))); - reg_mac3 = A3(b * reg_ir3 + reg_ir0 * LiB1_0(reg_bfc - ((b * reg_ir3) >> 12))); - - // TODO - is this B1 all the way correct? - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_dpcs(final int ci) { - // checked - /** - In: IR0 Interpolation value [1,3,12] - RGB Color R,G,B,CODE [0,8,0] - FC Far color RFC,GFC,BFC [1,27,4] - - Out: RGBn RGB fifo Rn,Gn,Bn,CDn [0,8,0] - [IR1,IR2,IR3] Color vector [1,11,4] - [MAC1,MAC2,MAC3] Color vector [1,27,4] - - [1,27,4] MAC1=A1[(R + IR0*(Lm_B1[RFC - R])] [1,27,16][lm=0] - [1,27,4] MAC2=A2[(G + IR0*(Lm_B1[GFC - G])] [1,27,16][lm=0] - [1,27,4] MAC3=A3[(B + IR0*(Lm_B1[BFC - B])] [1,27,16][lm=0] - [1,11,4] IR1=Lm_B1[MAC1] [1,27,4][lm=0] - [1,11,4] IR2=Lm_B2[MAC2] [1,27,4][lm=0] - [1,11,4] IR3=Lm_B3[MAC3] [1,27,4][lm=0] - [0,8,0] Cd0<-Cd1<-Cd2<- CODE - [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] - [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] - [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] - */ - reg_flag = 0; - - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - reg_mac1 = A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r)); - reg_mac2 = A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g)); - reg_mac3 = A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_intpl(final int ci) { - reg_flag = 0; - int chi = reg_rgb & 0xff000000; - - long ir0 = reg_ir0; - reg_mac1 = A1((reg_ir1 << 12) + ir0 * LiB1_0(reg_rfc - reg_ir1)); - reg_mac2 = A2((reg_ir2 << 12) + ir0 * LiB2_0(reg_gfc - reg_ir2)); - reg_mac3 = A3((reg_ir3 << 12) + ir0 * LiB3_0(reg_bfc - reg_ir3)); - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_sqr(final int ci) { - // checked -// Fields: sf -// in: [IR1,IR2,IR3] vector [1,15,0][1,3,12] -// out: [IR1,IR2,IR3] vector^2 [1,15,0][1,3,12] -// [MAC1,MAC2,MAC3] vector^2 [1,31,0][1,19,12] -// Calculation: (left format sf=0, right format sf=1) -// [1,31,0][1,19,12] MAC1=A1[IR1*IR1] [1,43,0][1,31,12] -// [1,31,0][1,19,12] MAC2=A2[IR2*IR2] [1,43,0][1,31,12] -// [1,31,0][1,19,12] MAC3=A3[IR3*IR3] [1,43,0][1,31,12] -// [1,15,0][1,3,12] IR1=Lm_B1[MAC1] [1,31,0][1,19,12][lm=1] -// [1,15,0][1,3,12] IR2=Lm_B2[MAC2] [1,31,0][1,19,12][lm=1] -// [1,15,0][1,3,12] IR3=Lm_B3[MAC3] [1,31,0][1,19,12][lm=1] - - reg_flag = 0; - - // [1,31,0] MAC1=A1[IR1*IR1] [1,43,0] - // [1,31,0] MAC2=A2[IR2*IR2] [1,43,0] - // [1,31,0] MAC3=A3[IR3*IR3] [1,43,0] - // [1,15,0] IR1=LB1[MAC1] [1,31,0][lm=1] - // [1,15,0] IR2=LB2[MAC2] [1,31,0][lm=1] - // [1,15,0] IR3=LB3[MAC3] [1,31,0][lm=1] - - int i1 = reg_ir1 * reg_ir1; - int i2 = reg_ir2 * reg_ir2; - int i3 = reg_ir3 * reg_ir3; - - if (0 != (ci & GTE_SF_MASK)) { - i1 >>= 12; - i2 >>= 12; - i3 >>= 12; - } - - // A1,A2,A3 not possible since the inputs are signed 16 bit - reg_mac1 = i1; - reg_mac2 = i2; - reg_mac3 = i3; - - // lm=0 also not pertinent - reg_ir1 = LiB1_1(i1); - reg_ir2 = LiB2_1(i2); - reg_ir3 = LiB3_1(i3); - } - - public static void interpret_ncs(final int ci) { - // test with ridge racer - reg_flag = 0; - int chi = reg_rgb & 0xff000000; - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); - int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); - int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); - - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - reg_mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - reg_mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - reg_mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_nct(final int ci) { - // test with ridge racer - reg_flag = 0; - int chi = reg_rgb & 0xff000000; - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); - int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); - int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); - - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - int rr = LiC1(mac1); - int gg = LiC2(mac2); - int bb = LiC3(mac3); - reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; - - // 2 - - mac1 = A1(m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z); - mac2 = A2(m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z); - mac3 = A3(m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - rr = LiC1(mac1); - gg = LiC2(mac2); - bb = LiC3(mac3); - reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; - - // 3 - - mac1 = A1(m11 * reg_v2.x + m12 * reg_v2.y + m13 * reg_v2.z); - mac2 = A2(m21 * reg_v2.x + m22 * reg_v2.y + m23 * reg_v2.z); - mac3 = A3(m31 * reg_v2.x + m32 * reg_v2.y + m33 * reg_v2.z); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - reg_mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - reg_mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - reg_mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - - rr = LiC1(reg_mac1); - gg = LiC2(reg_mac2); - bb = LiC3(reg_mac3); - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_ncds(final int ci) { - reg_flag = 0; - - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - // [1,19,12] MAC1=A1[L11*VX0 + L12*VY0 + L13*VZ0] [1,19,24] - // [1,19,12] MAC2=A1[L21*VX0 + L22*VY0 + L23*VZ0] [1,19,24] - // [1,19,12] MAC3=A1[L31*VX0 + L32*VY0 + L33*VZ0] [1,19,24] - // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); - int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); - int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] - // [1,19,12] MAC2=A1[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] - // [1,19,12] MAC3=A1[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] - // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - // [1,27,4] MAC1=A1[R*IR1 + IR0*(LB1[RFC-R*IR1])] [1,27,16][lm=0] - // [1,27,4] MAC2=A1[G*IR2 + IR0*(LB2[GFC-G*IR2])] [1,27,16][lm=0] - // [1,27,4] MAC3=A1[B*IR3 + IR0*(LB3[BFC-B*IR3])] [1,27,16][lm=0] - // [1,3,4] IR1= LB1[MAC1] [1,27,4][lm=1] - // [1,3,4] IR2= LB2[MAC2] [1,27,4][lm=1] - // [1,3,4] IR3= LB3[MAC3] [1,27,4][lm=1] - long ir0 = reg_ir0; - reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); - reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); - reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); - - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - - // [0,8,0] Cd0<-Cd1<-Cd2<- CODE - // [0,8,0] R0<-R1<-R2<- LC1[MAC1] [1,27,4] - // [0,8,0] G0<-G1<-G2<- LC2[MAC2] [1,27,4] - // [0,8,0] B0<-B1<-B2<- LC3[MAC3] [1,27,4] - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_ncdt(final int ci) { - reg_flag = 0; - - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - // [1,19,12] MAC1=A1[L11*VX0 + L12*VY0 + L13*VZ0] [1,19,24] - // [1,19,12] MAC2=A1[L21*VX0 + L22*VY0 + L23*VZ0] [1,19,24] - // [1,19,12] MAC3=A1[L31*VX0 + L32*VY0 + L33*VZ0] [1,19,24] - // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); - int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); - int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] - // [1,19,12] MAC2=A1[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] - // [1,19,12] MAC3=A1[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] - // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - // [1,27,4] MAC1=A1[R*IR1 + IR0*(LB1[RFC-R*IR1])] [1,27,16][lm=0] - // [1,27,4] MAC2=A1[G*IR2 + IR0*(LB2[GFC-G*IR2])] [1,27,16][lm=0] - // [1,27,4] MAC3=A1[B*IR3 + IR0*(LB3[BFC-B*IR3])] [1,27,16][lm=0] - // [1,3,4] IR1= LB1[MAC1] [1,27,4][lm=1] - // [1,3,4] IR2= LB2[MAC2] [1,27,4][lm=1] - // [1,3,4] IR3= LB3[MAC3] [1,27,4][lm=1] - long ir0 = reg_ir0; - reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); - reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); - reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); - - // [0,8,0] Cd0<-Cd1<-Cd2<- CODE - // [0,8,0] R0<-R1<-R2<- LC1[MAC1] [1,27,4] - // [0,8,0] G0<-G1<-G2<- LC2[MAC2] [1,27,4] - // [0,8,0] B0<-B1<-B2<- LC3[MAC3] [1,27,4] - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; - - // 2 ---- - - mac1 = A1(m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z); - mac2 = A2(m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z); - mac3 = A3(m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z); - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); - reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); - reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); - - rr = LiC1(reg_mac1); - gg = LiC2(reg_mac2); - bb = LiC3(reg_mac3); - reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; - - // 3 ---- - - mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); - mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); - mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); - reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); - reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); - - rr = LiC1(reg_mac1); - gg = LiC2(reg_mac2); - bb = LiC3(reg_mac3); - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_dpct(final int ci) { - // checked -// [1,27,4] MAC1=A1[R0+ IR0*(Lm_B1[RFC - R0])] [1,27,16][lm=0] -// [1,27,4] MAC2=A2[G0+ IR0*(Lm_B1[GFC - G0])] [1,27,16][lm=0] -// [1,27,4] MAC3=A3[B0+ IR0*(Lm_B1[BFC - B0])] [1,27,16][lm=0] -// [1,11,4] IR1=Lm_B1[MAC1] [1,27,4][lm=0] -// [1,11,4] IR2=Lm_B2[MAC2] [1,27,4][lm=0] -// [1,11,4] IR3=Lm_B3[MAC3] [1,27,4][lm=0] -// [0,8,0] Cd0<-Cd1<-Cd2<- CODE -// [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] -// [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] -// [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] -// *3 - - reg_flag = 0; - - // 1 ---- - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb0 & 0xff) << 4; - int g = (reg_rgb0 & 0xff00) >> 4; - int b = (reg_rgb0 & 0xff0000) >> 12; - - int rr = LiC1(A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r))); - int gg = LiC2(A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g))); - int bb = LiC3(A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b))); - reg_rgb0 = chi | rr | (gg << 8) | (bb << 16); - - // 2 ---- - - r = (reg_rgb1 & 0xff) << 4; - g = (reg_rgb1 & 0xff00) >> 4; - b = (reg_rgb1 & 0xff0000) >> 12; - - rr = LiC1(A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r))); - gg = LiC2(A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g))); - bb = LiC3(A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b))); - reg_rgb1 = chi | rr | (gg << 8) | (bb << 16); - - // 3 ---- - - r = (reg_rgb2 & 0xff) << 4; - g = (reg_rgb2 & 0xff00) >> 4; - b = (reg_rgb2 & 0xff0000) >> 12; - - reg_mac1 = A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r)); - reg_mac2 = A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g)); - reg_mac3 = A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b)); - - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - - rr = LiC1(reg_mac1); - gg = LiC2(reg_mac2); - bb = LiC3(reg_mac3); - reg_rgb2 = chi | rr | (gg << 8) | (bb << 16); - } - - public static void interpret_nccs(final int ci) { - // untested - reg_flag = 0; - - int chi = reg_rgb & 0xff000000; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - - long m11 = reg_ls.m11; - long m12 = reg_ls.m12; - long m13 = reg_ls.m13; - long m21 = reg_ls.m21; - long m22 = reg_ls.m22; - long m23 = reg_ls.m23; - long m31 = reg_ls.m31; - long m32 = reg_ls.m32; - long m33 = reg_ls.m33; - - long ss1 = m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z; - long ss2 = m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z; - long ss3 = m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z; - - int mac1 = A1(ss1); - int mac2 = A2(ss2); - int mac3 = A3(ss3); - - int ir1 = LiB1_1(mac1); - int ir2 = LiB2_1(mac2); - int ir3 = LiB3_1(mac3); - - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); - ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); - ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); - - mac1 = A1(ss1); - mac2 = A2(ss2); - mac3 = A3(ss3); - - ir1 = LiB1_1(mac1); - ir2 = LiB2_1(mac2); - ir3 = LiB3_1(mac3); - - reg_mac1 = A1(r * ir1); - reg_mac2 = A2(g * ir2); - reg_mac3 = A3(b * ir3); - reg_ir1 = LiB1_1(reg_mac1); - reg_ir2 = LiB2_1(reg_mac2); - reg_ir3 = LiB3_1(reg_mac3); - - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; - } - - public static void interpret_cdp(final int ci) { - // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] - // [1,19,12] MAC2=A2[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] - // [1,19,12] MAC3=A3[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] - int ir1 = reg_ir1; - int ir2 = reg_ir2; - int ir3 = reg_ir3; - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - int mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - int mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - int mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - // [1,3,12] IR1= Lm_B1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= Lm_B2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= Lm_B3[MAC3] [1,19,12][lm=1] - ir1 = LiB1_1(mac1); - ir2 = LiB1_1(mac2); - ir3 = LiB1_1(mac3); - - // [1,27,4] MAC1=A1[R*IR1 + IR0*(Lm_B1[RFC-R*IR1])] [1,27,16][lm=0] - // [1,27,4] MAC2=A2[G*IR2 + IR0*(Lm_B2[GFC-G*IR2])] [1,27,16][lm=0] - // [1,27,4] MAC3=A3[B*IR3 + IR0*(Lm_B3[BFC-B*IR3])] [1,27,16][lm=0] - // [1,3,12] IR1= Lm_B1[MAC1] [1,27,4][lm=1] - // [1,3,12] IR2= Lm_B2[MAC2] [1,27,4][lm=1] - // [1,3,12] IR3= Lm_B3[MAC3] [1,27,4][lm=1] - long ir0 = reg_ir0; - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); - reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); - reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); - reg_ir1 = LiB1_1(mac1); - reg_ir2 = LiB1_1(mac2); - reg_ir3 = LiB1_1(mac3); - - // [0,8,0] Cd0<-Cd1<-Cd2<- CODE - // [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] - // [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] - // [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); - } - - public static void interpret_cc(final int ci) { - // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] - // [1,19,12] MAC2=A2[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] - // [1,19,12] MAC3=A3[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] - int ir1 = reg_ir1; - int ir2 = reg_ir2; - int ir3 = reg_ir3; - long c11 = reg_lc.m11; - long c12 = reg_lc.m12; - long c13 = reg_lc.m13; - long c21 = reg_lc.m21; - long c22 = reg_lc.m22; - long c23 = reg_lc.m23; - long c31 = reg_lc.m31; - long c32 = reg_lc.m32; - long c33 = reg_lc.m33; - - long bkr = reg_rbk; - long bkg = reg_gbk; - long bkb = reg_bbk; - - int mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); - int mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); - int mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); - - // [1,3,12] IR1= Lm_B1[MAC1] [1,19,12][lm=1] - // [1,3,12] IR2= Lm_B2[MAC2] [1,19,12][lm=1] - // [1,3,12] IR3= Lm_B3[MAC3] [1,19,12][lm=1] - ir1 = LiB1_1(mac1); - ir2 = LiB1_1(mac2); - ir3 = LiB1_1(mac3); - - // [1,27,4] MAC1=A1[R*IR1] [1,27,16] - // [1,27,4] MAC2=A2[G*IR2] [1,27,16] - // [1,27,4] MAC3=A3[B*IR3] [1,27,16] - // [1,3,12] IR1= Lm_B1[MAC1] [1,27,4][lm=1] - // [1,3,12] IR2= Lm_B2[MAC2] [1,27,4][lm=1] - // [1,3,12] IR3= Lm_B3[MAC3] [1,27,4][lm=1] - int r = (reg_rgb & 0xff) << 4; - int g = (reg_rgb & 0xff00) >> 4; - int b = (reg_rgb & 0xff0000) >> 12; - reg_mac1 = A1(r * ir1); - reg_mac2 = A2(g * ir2); - reg_mac3 = A3(b * ir3); - reg_ir1 = LiB1_1(mac1); - reg_ir2 = LiB1_1(mac2); - reg_ir3 = LiB1_1(mac3); - - // [0,8,0] Cd0<-Cd1<-Cd2<- CODE - // [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] - // [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] - // [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); - } - - public static void interpret_gpl(final int ci) { - reg_flag = 0; - - long i = reg_ir0; - if (0 != (ci & GTE_SF_MASK)) { - reg_mac1 = A1((((long) reg_mac1) << 12) + i * reg_ir1); - reg_mac2 = A2((((long) reg_mac2) << 12) + i * reg_ir2); - reg_mac3 = A3((((long) reg_mac3) << 12) + i * reg_ir3); - } else { - reg_mac1 = A1((reg_mac1 + i * reg_ir1) << 12); - reg_mac2 = A2((reg_mac2 + i * reg_ir2) << 12); - reg_mac3 = A3((reg_mac3 + i * reg_ir3) << 12); - } - reg_ir1 = LiB1_0(reg_mac1); - reg_ir2 = LiB2_0(reg_mac2); - reg_ir3 = LiB3_0(reg_mac3); - int rr = LiC1(reg_mac1); - int gg = LiC2(reg_mac2); - int bb = LiC3(reg_mac3); - reg_rgb0 = reg_rgb1; - reg_rgb1 = reg_rgb2; - reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); - } - - static int table[] = - { - 0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3, - 0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8, - 0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb, 0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0, - 0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a, - 0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74, - 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, - 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, - 0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48, - 0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, - 0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f, - 0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24, - 0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, - 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11, - 0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, - 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, - 0x00 - }; - - static int dividex(int numerator, int denominator) { - if (denominator == 0) { - return Integer.MAX_VALUE; - } - return (int)((((long)numerator)<<16)/denominator); - } - - static int divide(int numerator, int denominator) { - if (denominator == 0) { - return Integer.MAX_VALUE; - } - if (numerator <= 0x7fff) { - return (numerator<<16)/denominator; - } else { - return (int)((((long)numerator)<<16)/denominator); - } - } - - static int gte_divide(int numerator, int denominator) { - if (numerator < (denominator * 2)) { - int shift = Integer.numberOfLeadingZeros(denominator) - 16; - - int r1 = (denominator << shift) & 0x7fff; - int r2 = table[((r1 + 0x40) >> 7)] + 0x101; - int r3 = ((0x80 - (r2 * (r1 + 0x8000))) >> 8) & 0x1ffff; - int reciprocal = ((r2 * r3) + 0x80) >> 8; - - return (int) ((((long) reciprocal * (numerator << shift)) + 0x8000) >> 16); - } - - return Integer.MAX_VALUE; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java b/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java deleted file mode 100644 index 6a1e8d5..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.mdec; - -public class IDCT { - private static final int W1 = 2841; // 2048*sqrt(2)*cos(1*pi/16) - private static final int W2 = 2676; // 2048*sqrt(2)*cos(2*pi/16) - private static final int W3 = 2408; // 2048*sqrt(2)*cos(3*pi/16) - private static final int W5 = 1609; // 2048*sqrt(2)*cos(5*pi/16) - private static final int W6 = 1108; // 2048*sqrt(2)*cos(6*pi/16) - private static final int W7 = 565; // 2048*sqrt(2)*cos(7*pi/16) - - private static final int clamp[] = new int[2048]; - - private static void idctrow(int[] blk, int base) { - int x0, x1, x2, x3, x4, x5, x6, x7, x8; - - if (0 == ((x1 = blk[base + 4] << 11) | (x2 = blk[base + 6]) | (x3 = blk[base + 2]) | - (x4 = blk[base + 1]) | (x5 = blk[base + 7]) | (x6 = blk[base + 5]) | (x7 = blk[base + 3]))) { - blk[base + 0] = blk[base + 1] = blk[base + 2] = blk[base + 3] = blk[base + 4] = blk[base + 5] = blk[base + 6] = blk[base + 7] = blk[base + 0] << 3; - return; - } - - x0 = (blk[base + 0] << 11) + 128; - - x8 = W7 * (x4 + x5); - x4 = x8 + (W1 - W7) * x4; - x5 = x8 - (W1 + W7) * x5; - x8 = W3 * (x6 + x7); - x6 = x8 - (W3 - W5) * x6; - x7 = x8 - (W3 + W5) * x7; - - x8 = x0 + x1; - x0 -= x1; - x1 = W6 * (x3 + x2); - x2 = x1 - (W2 + W6) * x2; - x3 = x1 + (W2 - W6) * x3; - x1 = x4 + x6; - x4 -= x6; - x6 = x5 + x7; - x5 -= x7; - - x7 = x8 + x3; - x8 -= x3; - x3 = x0 + x2; - x0 -= x2; - x2 = (181 * (x4 + x5) + 128) >> 8; - x4 = (181 * (x4 - x5) + 128) >> 8; - - blk[base + 0] = (x7 + x1) >> 8; - blk[base + 1] = (x3 + x2) >> 8; - blk[base + 2] = (x0 + x4) >> 8; - blk[base + 3] = (x8 + x6) >> 8; - blk[base + 4] = (x8 - x6) >> 8; - blk[base + 5] = (x0 - x4) >> 8; - blk[base + 6] = (x3 - x2) >> 8; - blk[base + 7] = (x7 - x1) >> 8; - } - - private static void idctcol(int[] blk, int base) { - int x0, x1, x2, x3, x4, x5, x6, x7, x8; - - if (0 == ((x1 = (blk[base + 8 * 4] << 8)) | (x2 = blk[base + 8 * 6]) | (x3 = blk[base + 8 * 2]) | - (x4 = blk[base + 8 * 1]) | (x5 = blk[base + 8 * 7]) | (x6 = blk[base + 8 * 5]) | (x7 = blk[base + 8 * 3]))) { - blk[base + 8 * 0] = blk[base + 8 * 1] = blk[base + 8 * 2] = blk[base + 8 * 3] = blk[base + 8 * 4] = blk[base + 8 * 5] = blk[base + 8 * 6] = blk[base + 8 * 7] = - clamp[1024 + ((blk[base + 8 * 0] + 32) >> 6)]; - return; - } - - x0 = (blk[base + 8 * 0] << 8) + 8192; - - x8 = W7 * (x4 + x5) + 4; - x4 = (x8 + (W1 - W7) * x4) >> 3; - x5 = (x8 - (W1 + W7) * x5) >> 3; - x8 = W3 * (x6 + x7) + 4; - x6 = (x8 - (W3 - W5) * x6) >> 3; - x7 = (x8 - (W3 + W5) * x7) >> 3; - - x8 = x0 + x1; - x0 -= x1; - x1 = W6 * (x3 + x2) + 4; - x2 = (x1 - (W2 + W6) * x2) >> 3; - x3 = (x1 + (W2 - W6) * x3) >> 3; - x1 = x4 + x6; - x4 -= x6; - x6 = x5 + x7; - x5 -= x7; - - x7 = x8 + x3; - x8 -= x3; - x3 = x0 + x2; - x0 -= x2; - x2 = (181 * (x4 + x5) + 128) >> 8; - x4 = (181 * (x4 - x5) + 128) >> 8; - - blk[base + 8 * 0] = clamp[1024 + ((x7 + x1) >> 14)]; - blk[base + 8 * 1] = clamp[1024 + ((x3 + x2) >> 14)]; - blk[base + 8 * 2] = clamp[1024 + ((x0 + x4) >> 14)]; - blk[base + 8 * 3] = clamp[1024 + ((x8 + x6) >> 14)]; - blk[base + 8 * 4] = clamp[1024 + ((x8 - x6) >> 14)]; - blk[base + 8 * 5] = clamp[1024 + ((x0 - x4) >> 14)]; - blk[base + 8 * 6] = clamp[1024 + ((x3 - x2) >> 14)]; - blk[base + 8 * 7] = clamp[1024 + ((x7 - x1) >> 14)]; - } - - public static void transform(int[] block) { - for (int i = 0; i < 64; i += 8) - idctrow(block, i); - - for (int i = 0; i < 8; i++) - idctcol(block, i); - } - - static { - for (int i = 0; i < 2048; i++) { - if (i < 1024) { - clamp[i] = 0; - } else if (i < (1024 + 256)) { - clamp[i] = i - 1024; - } else { - clamp[i] = 255; - } - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java b/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java deleted file mode 100644 index e65aa02..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.mdec; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.DMAChannelOwnerBase; -import org.jpsx.runtime.util.MiscUtil; - -public class MDEC extends JPSXComponent implements MemoryMapped { - private static final Logger log = Logger.getLogger("MDEC"); - - private static final boolean debugMDEC = log.isDebugEnabled(); - - private static final int ADDR_MDEC_CTRL = 0x1f801820; - private static final int ADDR_MDEC_STATUS = 0x1f801824; - - // abe mdec_in_sync waits for bit 0x20000000 to clear - // abe mdec_out_sync waits for bit 0x01000000 to clear - private static final int NFIFO0 = 0x80000000; - private static final int FIFO1 = 0x40000000; - private static final int BUSY0 = 0x20000000; - private static final int DREQ0 = 0x10000000; - private static final int DREQ1 = 0x08000000; - private static final int RGB24 = 0x02000000; - private static final int BUSY1 = 0x01000000; - private static final int STP = 0x00800000; - -// private static final int BUSY0 = 0x80000000; -// private static final int DREQ0 = 0x40000000; -// private static final int DREQ1 = 0x20000000; - // private static final int RGB24 = 0x08000000; - // private static final int BUSY1 = 0x04000000; - // private static final int STP = 0x02000000; - private static final int CTRL_RGB24 = 0x08000000; - private static final int CTRL_STP = 0x02000000; - - private static final int[] yqm = new int[64]; - private static final int[] uvqm = new int[64]; - - private static final int unzig[] = new int[]{ - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, - 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, - 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 - }; - - private static AddressSpace addressSpace; - private static int ctrl; - private static int status; - private static int stp; - private static AddressSpace.ResolveResult source = new AddressSpace.ResolveResult(); - private static int sourceRemaining; - - public MDEC() { - super("JPSX Movie Decoder"); - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new InChannel()); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new OutChannel()); - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - } - - public void registerAddresses(AddressSpaceRegistrar registrar) { - registrar.registerWrite32Callback(ADDR_MDEC_CTRL, MDEC.class, "writeCtrl32"); - registrar.registerWrite32Callback(ADDR_MDEC_STATUS, MDEC.class, "writeStatus32"); - registrar.registerRead32Callback(ADDR_MDEC_CTRL, MDEC.class, "readCtrl32"); - registrar.registerRead32Callback(ADDR_MDEC_STATUS, MDEC.class, "readStatus32"); - } - - public static void writeStatus32(int address, int value) { - if (debugMDEC) log.debug("MDEC status write32 " + MiscUtil.toHex(value, 8)); - if (value == 0x80000000) { - if (debugMDEC) log.debug("MDEC turn off FIFO"); - status = value; - } else if (value == 0x60000000) { - if (debugMDEC) log.debug("MDEC turn on FIFO"); - status = value & ~BUSY0; - } else { - throw new IllegalStateException("MDEC unknown status write " + MiscUtil.toHex(value, 8)); - } - } - - public static void writeCtrl32(int address, int value) { - if (debugMDEC) log.debug("MDEC ctrl write32 " + MiscUtil.toHex(value, 8)); - - ctrl = value; - if (0 != (ctrl & CTRL_RGB24)) { - status &= ~RGB24; - } else { - status |= RGB24; - } - if (0 != (ctrl & CTRL_STP)) { - status |= STP; - stp = 0x8000; - } else { - status &= ~STP; - stp = 0; - } - } - - public static int readStatus32(int address) { - int rc = status; - if (debugMDEC) log.debug("MDEC status read32 " + MiscUtil.toHex(rc, 8)); - return rc; - } - - public static int readCtrl32(int address) { - //int rc = m_ctrl; - //if (debugMDEC) log.debug("MDEC ctrl read32 "+MiscUtil.toHex( rc, 8)); - //return rc; - throw new IllegalStateException("wahhh?"); - } - - private static class InChannel extends DMAChannelOwnerBase { - public final int getDMAChannel() { - return DMAController.DMA_MDEC_IN; - } - - public final String getName() { - return "MDEC-In"; - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - if (debugMDEC) - log.debug("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - int size = blocks * blockSize; - - if (MDEC.ctrl == 0x60000000) { - if (debugMDEC) log.debug("INIT COSINE TABLE size=" + MiscUtil.toHex(size, 4)); - } else if (MDEC.ctrl == 0x40000001) { - if (debugMDEC) log.debug("INIT QTABLE size=" + MiscUtil.toHex(size, 4)); - for (int i = 0; i < 64; i++) { - yqm[i] = addressSpace.read8(base + i); - } - for (int i = 0; i < 64; i++) { - uvqm[i] = addressSpace.read8(base + 64 + i); - } - // todo figure these commands out -// } else if (0!=(m_ctrl & BUSY0) && (0!=(m_ctrl&DREQ0)) && 0==(m_ctrl & NFIFO0)) { - } else { - //log.debug("MDEC cmd "+MiscUtil.toHex( m_ctrl, 8)); - if (debugMDEC) - log.debug("INCOMING DATA FROM " + MiscUtil.toHex(base, 8) + " SIZE = " + MiscUtil.toHex(size, 8) + " low16 = " + MiscUtil.toHex(MDEC.ctrl & 0xffff, 4)); - - //m_status |= BUSY0; -// m_status &= ~DREG0; -// m_status &= ~NFIFO0; - - addressSpace.resolve(base, size * 4, true, source); - sourceRemaining = size * 4; -// } else { -// throw new IllegalStateException("unknown MDEC ctrl = "+MiscUtil.toHex( m_ctrl, 8)); - } - signalTransferComplete(); - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - throw new IllegalStateException("unknown mdec dma from channel 0"); - //if (debugMDEC) log.debug( "begin DMA transfer from "+getName()+" "+MiscUtil.toHex( base, 8)+" 0x"+Integer.toHexString(blocks)+"*0x"+Integer.toHexString( blockSize)+" ctrl "+MiscUtil.toHex( ctrl, 8)); - //signalTransferComplete(); - } - - public void cancelDMATransfer(int ctrl) { - if (debugMDEC) log.debug("cancel " + getName() + " DMA transfer"); - } - } - - //private static final int SIGNED10BITS(x) - //{ - // return (x<<22)>>22; - //} - - private static class OutChannel extends DMAChannelOwnerBase { - private final int[] ycoeffs = new int[64]; - private final int[] ucoeffs = new int[64]; - private final int[] vcoeffs = new int[64]; - - public final int getDMAChannel() { - return DMAController.DMA_MDEC_OUT; - } - - public final String getName() { - return "MDEC-Out"; - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - throw new IllegalStateException("unknown mdec dma to channel 1"); -// if (debugMDEC) log.debug( "begin DMA transfer to "+getName()+" "+MiscUtil.toHex( base, 8)+" 0x"+Integer.toHexString(blocks)+"*0x"+Integer.toHexString( blockSize)+" ctrl "+MiscUtil.toHex( ctrl, 8)); -// signalTransferComplete(); - } - - - private static int rgb15(int y, int v, int u) { - int r = y + ((0x0000059B * u) >> 10); - int g = y + ((-0x15F * v) >> 10) + ((-0x2DB * u) >> 10); - int b = y + ((0x00000716 * v) >> 10); - if (r < 0) r = 0; - if (r > 255) r = 255; - if (g < 0) g = 0; - if (g > 255) g = 255; - if (b < 0) b = 0; - if (b > 255) b = 255; - return stp | ((b >> 3) << 10) + ((g >> 3) << 5) + (r >> 3); - } - - private static int rgb24(int y, int v, int u) { - int r = y + ((0x0000059B * u) >> 10); - int g = y + ((-0x15F * v) >> 10) + ((-0x2DB * u) >> 10); - int b = y + ((0x00000716 * v) >> 10); - if (r < 0) r = 0; - if (r > 255) r = 255; - if (g < 0) g = 0; - if (g > 255) g = 255; - if (b < 0) b = 0; - if (b > 255) b = 255; - return (r << 16) | (g << 8) | b; - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if (debugMDEC) - log.debug("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - - //assert 0!=(m_status&FIFO1); - // if (0==(m_status&FIFO1)) { - // m_status|=NFIFO0; - // signalTransferComplete(); - // } - //int baseTime = MTScheduler.getTime(); - //log.debug("configure mdec out time = "+baseTime); - int size = blocks * blockSize * 4; - - boolean rgb24 = 0 != (status & RGB24); - int mbsize = 256 * (rgb24 ? 3 : 2); - int mbcount = size / mbsize; - - AddressSpace.ResolveResult target = new AddressSpace.ResolveResult(); - addressSpace.resolve(base, size, false, target); - - int dword = source.mem[source.offset]; - - outer: - for (; mbcount > 0; mbcount--) { -// // make IRQ keep happening for sake of CD streaming -// r3000.checkAndHandleBreakout(); - if (debugMDEC) log.debug("mbcount " + mbcount + " remaining " + sourceRemaining); - for (int mb = 0; mb < 6; mb++) { - int word; - if (sourceRemaining <= 0) break outer; - if (0 == (sourceRemaining & 2)) { - dword = source.mem[source.offset]; - word = dword & 0xffff; - } else { - source.offset++; - word = (dword >> 16) & 0xffff; - } - sourceRemaining -= 2; - - int dc = (word & 0x3ff) ^ 0x200; - int qf = word >> 10; - - //if (mbcount==(size/mbsize)) dc = 0; - - int[] coeffs; - int[] qm; - if (mb == 0) { - coeffs = vcoeffs; - qm = uvqm; - } else if (mb == 1) { - coeffs = ucoeffs; - qm = uvqm; - } else { - coeffs = ycoeffs; - qm = yqm; - } - - for (int i = 1; i < 64; i++) coeffs[i] = 0; - coeffs[0] = dc * qm[0]; - - int index = 0; - do { - if (sourceRemaining <= 0) break outer; - if (0 == (sourceRemaining & 2)) { - dword = source.mem[source.offset]; - word = dword & 0xffff; - } else { - source.offset++; - word = (dword >> 16) & 0xffff; - } - sourceRemaining -= 2; - if (word == 0xfe00) - break; - index += (word >> 10) + 1; - coeffs[unzig[index]] = (qf * ((word << 22) >> 22) * qm[index]) >> 3; - } while (true); - - IDCT.transform(coeffs); - - final int[] mem = target.mem; - if (rgb24) { - if (mb >= 2) { - int uvoffset = 0; - int which = mb - 2; - int offset = target.offset; - if (0 != (which & 1)) { - offset += 6; - uvoffset += 4; - } - if (0 != (which & 2)) { - offset += 96; - uvoffset += 32; - } - for (int i = 0; i < 64; i += 4) { - int u0 = ucoeffs[uvoffset] - 128; - int u1 = ucoeffs[uvoffset + 1] - 128; - int v0 = vcoeffs[uvoffset] - 128; - int v1 = vcoeffs[uvoffset + 1] - 128; - - int p0 = coeffs[i]; - int p1 = coeffs[i + 1]; - int p2 = coeffs[i + 2]; - int p3 = coeffs[i + 3]; - int q0 = coeffs[i + 8]; - int q1 = coeffs[i + 9]; - int q2 = coeffs[i + 10]; - int q3 = coeffs[i + 11]; - - p0 = rgb24(p0, u0, v0); - p1 = rgb24(p1, u0, v0); - p2 = rgb24(p2, u1, v1); - p3 = rgb24(p3, u1, v1); - - mem[offset] = p0 | (p1 << 24); // b1r0g0b0 - mem[offset + 1] = ((p1 >> 8) & 0xffff) | (p2 << 16); // g2b2r1g1 - mem[offset + 2] = ((p2 >> 16) & 0xff) | (p3 << 8); // r3g3b3r2 - - q0 = rgb24(q0, u0, v0); - q1 = rgb24(q1, u0, v0); - q2 = rgb24(q2, u1, v1); - q3 = rgb24(q3, u1, v1); - - mem[offset + 12] = q0 | (q1 << 24); - mem[offset + 13] = ((q1 >> 8) & 0xffff) | (q2 << 16); - mem[offset + 14] = ((q2 >> 16) & 0xff) | (q3 << 8); - - offset += 3; - uvoffset += 2; - if (4 == (i & 7)) { - i += 8; - offset += 18; - uvoffset += 4; - } - } - } - } else { - if (mb >= 2) { - int uvoffset = 0; - int which = mb - 2; - int offset = target.offset; - if (0 != (which & 1)) { - offset += 4; - uvoffset += 4; - } - if (0 != (which & 2)) { - offset += 64; - uvoffset += 32; - } - for (int i = 0; i < 64; i += 4) { - int u0 = ucoeffs[uvoffset] - 128; - int u1 = ucoeffs[uvoffset + 1] - 128; - int v0 = vcoeffs[uvoffset] - 128; - int v1 = vcoeffs[uvoffset + 1] - 128; - - int p0 = coeffs[i]; - int p1 = coeffs[i + 1]; - int p2 = coeffs[i + 2]; - int p3 = coeffs[i + 3]; - int q0 = coeffs[i + 8]; - int q1 = coeffs[i + 9]; - int q2 = coeffs[i + 10]; - int q3 = coeffs[i + 11]; - - p0 = rgb15(p0, u0, v0); - p1 = rgb15(p1, u0, v0); - p2 = rgb15(p2, u1, v1); - p3 = rgb15(p3, u1, v1); - - mem[offset] = p0 | (p1 << 16); - mem[offset + 1] = p2 | (p3 << 16); - - q0 = rgb15(q0, u0, v0); - q1 = rgb15(q1, u0, v0); - q2 = rgb15(q2, u1, v1); - q3 = rgb15(q3, u1, v1); - - mem[offset + 8] = q0 | (q1 << 16); - mem[offset + 9] = q2 | (q3 << 16); - - offset += 2; - uvoffset += 2; - if (4 == (i & 7)) { - i += 8; - offset += 12; - uvoffset += 4; - } - } - } - } - } - target.offset += mbsize >> 2; - } - - - if (sourceRemaining == 0) { - if (debugMDEC) log.debug("COMPLETE!!"); - - status &= ~BUSY0; - status &= ~BUSY1; - } - - signalTransferComplete(); - //log.debug("end mdec out dtime = "+(MTScheduler.getTime()-baseTime)); - } - - public void cancelDMATransfer(int ctrl) { - if (debugMDEC) log.debug("cancel " + getName() + " DMA transfer"); - } - } -} \ No newline at end of file diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java b/src/runtime/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java deleted file mode 100644 index f1b14be..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.media; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.hardware.cd.CDDrive; -import org.jpsx.api.components.hardware.cd.CDMedia; -import org.jpsx.api.components.hardware.cd.MediaException; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.CDUtil; -import org.jpsx.runtime.util.MiscUtil; - -import java.io.*; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.RandomAccessFile; - -public class CueBinImageDrive extends SingletonJPSXComponent implements CDDrive { - public static final String PROPERTY_IMAGE_FILE = "image"; - - private static final String CATEGORY = "CDImage"; - private static final Logger log = Logger.getLogger(CATEGORY); - private static final String DEFAULT_CUE_FILE = "rips/wipeoutxl.cue"; - private CDMedia currentMedia; - - private boolean refreshed = false; - - public CueBinImageDrive() { - super("JPSX CUE/BIN Image CD Drive"); - } - - public void init() { - super.init(); - HardwareComponentConnections.CD_DRIVE.set(this); - } - - public CDMedia getCurrentMedia() { - if (!refreshed) { - refreshMedia(); - refreshed = true; - } - return currentMedia; - } - - public boolean isDriveOpen() { - return false; - } - - public void refreshMedia() { - String cueFilename = getProperty(PROPERTY_IMAGE_FILE, DEFAULT_CUE_FILE); - currentMedia = CueBinImageMedia.create(cueFilename); - } - - private static class CueBinImageMedia implements CDMedia { - int first; - int last; - int[] msf = new int[100]; - TrackType[] trackType = new TrackType[100]; - byte[] byteBuf = new byte[2352]; - RandomAccessFile binFile; - - private CueBinImageMedia() { - } - - public TrackType getTrackType(int track) { - return trackType[track]; - } - - public static CueBinImageMedia create(String cueFilename) { - CueBinImageMedia rc = new CueBinImageMedia(); - if (!rc.parse(cueFilename)) { - return null; - } - return rc; - } - - private boolean parse(String cueFilename) { - LineNumberReader reader; - try { - reader = new LineNumberReader(new FileReader(cueFilename)); - } catch (IOException e) { - log.warn("Unable to open CUE file " + cueFilename+": "+e.getMessage()); - return false; - } - String binFilename = cueFilename; - - int offset = 150; - try { - first = 99; - last = 0; - int dot = binFilename.lastIndexOf("."); - if (dot >= 0) binFilename = binFilename.substring(0, dot) + ".bin"; - - String line = reader.readLine(); - int trackNum = -1; - while (line != null) { - line = line.trim(); - String uline = line.toUpperCase(); - if (uline.startsWith("TRACK")) { - trackNum = readNumber(line.substring(5)); - if (trackNum < first) first = trackNum; - if (trackNum > last) last = trackNum; - String typeString = uline.substring(8).trim(); - trackType[trackNum] = CDMedia.TrackType.UNKNOWN; - if (typeString.equals("MODE2/2352")) { - trackType[trackNum] = CDMedia.TrackType.MODE2_2352; - } else if (typeString.equals("AUDIO")) { - trackType[trackNum] = CDMedia.TrackType.AUDIO; - } - } else if (uline.startsWith("INDEX 01")) { - msf[trackNum] = toMSF(parseMSFStringAsLBA(line.substring(8)) + offset); - } else if (uline.startsWith("FILE")) { - int q1 = line.indexOf("\""); - if (q1 >= 0) { - int q2 = line.indexOf("\"", q1 + 1); - if (q2 >= q1) { - binFilename = line.substring(q1 + 1, q2); - } - } - } - line = reader.readLine(); - } - } catch (IOException e) { - log.warn("Error reading CUE file " + cueFilename); - return false; - } finally { - try { - reader.close(); - } catch (IOException e) { - } - } - // hack - binFilename = binFilename.replace('\\','/'); - binFilename = binFilename.toLowerCase(); - File file = new File(binFilename); - if (!file.exists()) { - file = new File(new File(cueFilename).getParent(), file.getName()); - log.info("try "+file); - if (file.exists()) { - binFilename = file.getAbsolutePath(); - } - } - binFile = null; - long length; - try { - binFile = new RandomAccessFile(binFilename, "r"); - length = binFile.length(); - } catch (IOException e) { - log.warn("Unable to open BIN file " + binFilename+": "+e.getMessage()); - return false; - } - msf[0] = toMSF(offset + (int) (length / 2352L)); - if (log.isDebugEnabled()) { - for (int i = first; i <= last; i++) { - log.debug("track " + i + " " + printMSF(msf[i])); - } - log.debug("end " + printMSF(msf[0])); - } - return true; - } - - public void readSector(int num, byte[] buffer) throws MediaException { - try { - // note findbugs complains about this, but we know that the value can't overflow - binFile.seek(num * 2352); - binFile.readFully(buffer, 0, 2352); - } catch (IOException e) { - throw new MediaException("readSector failed", e); - } - } - - public void readSector(int num, int[] buffer) throws MediaException { - try { - // note findbugs complains about this, but we know that the value can't overflow - binFile.seek(num * 2352); - binFile.readFully(byteBuf); - for (int i = 0; i < 2352 / 4; i++) { - buffer[i] = ((((int) byteBuf[i * 4 + 3]) & 0xff) << 24) | - ((((int) byteBuf[i * 4 + 2]) & 0xff) << 16) | - ((((int) byteBuf[i * 4 + 1]) & 0xff) << 8) | - ((((int) byteBuf[i * 4]) & 0xff)); - } - } catch (IOException e) { - throw new MediaException("readSector failed", e); - } - } - - public int getFirstTrack() { - return first; - } - - public int getLastTrack() { - return last; - } - - public int getTrackMSF(int trackIndex) { - return msf[trackIndex]; - } - - static int toMSF(int sector) { - int f = sector % 75; - sector /= 75; - int s = sector % 60; - sector /= 60; - int m = sector; - return (CDUtil.toBCD(m) << 16) | (CDUtil.toBCD(s) << 8) | CDUtil.toBCD(f); - } - - static String printMSF(int msf) { - int m = (msf & 0xff0000) >> 16; - int s = (msf & 0xff00) >> 8; - int f = msf & 0xff; - return MiscUtil.toHex(m, 2) + ":" + MiscUtil.toHex(s, 2) + ":" + MiscUtil.toHex(f, 2); - } - - static int readNumber(String s) { - // read a two digit number - int rc = 0; - s = s.trim(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (!Character.isDigit(c)) break; - rc = rc * 10 + (c - '0'); - } - return rc; - } - - static int parseMSFStringAsLBA(String msf) { - msf = msf.trim(); - int c1 = msf.indexOf(':'); - int c2 = msf.indexOf(':', c1 + 1); - int m = readNumber(msf.substring(0, c1)); - int s = readNumber(msf.substring(c1 + 1, c2)); - int f = readNumber(msf.substring(c2 + 1)); - return ((m * 60) + s) * 75 + f; - } - - } - -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java b/src/runtime/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java deleted file mode 100644 index 245256a..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java +++ /dev/null @@ -1,2947 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.r3000; - -import org.apache.bcel.generic.*; -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.*; -import org.jpsx.runtime.FinalResolvedConnectionCache; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.R3000Impl; - -// todo move reg_hi/reg_lo into compilation context -public final class R3000InstructionSet extends JPSXComponent implements InstructionProvider { - public static final Logger log = Logger.getLogger("R3000 Instruction Set"); - - private static final String R3000_CLASS = R3000Impl.class.getName(); - private static final String CLASS = R3000InstructionSet.class.getName(); - - private static final boolean ignoreArithmeticOverflow = true; - - private static class Refs extends FinalResolvedConnectionCache { - public static final AddressSpace addressSpace = resolve(CoreComponentConnections.ADDRESS_SPACE); - public static final R3000 r3000 = resolve(CoreComponentConnections.R3000); - public static final int[] r3000Regs = resolve(CoreComponentConnections.R3000).getInterpreterRegs(); - public static final SCP scp = resolve(CoreComponentConnections.SCP); - } - - public R3000InstructionSet() { - super("JPSX R3000 Instruction Set"); - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); - } - - // instructions and interpreters - - public void addInstructions(InstructionRegistrar registrar) { - log.info("Adding R3000 instructions..."); - CPUInstruction i_add; - if (ignoreArithmeticOverflow) { - i_add = new CPUInstruction("add", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) + context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - int val = context.getRegValue(rs); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IADD()); - } - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IADD()); - } - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new IADD()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rs] + regs[rt]; - } - return true; - } - }; - } else { - i_add = new CPUInstruction("add", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - } - CPUInstruction i_addi; - if (ignoreArithmeticOverflow) { - i_addi = new CPUInstruction("addi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - assert false; - int val = context.getRegValue(rs) + imm; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rt); - } else { - context.emitGetReg(il, rs); - if (imm != 0) { - il.append(new PUSH(cp, imm)); - il.append(new IADD()); - } - context.emitSetReg(il, rt); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - if (rt != 0) { - regs[rt] = regs[rs] + imm; - } - return true; - } - }; - } else { - i_addi = new CPUInstruction("addi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - } - CPUInstruction i_addiu = new CPUInstruction("addiu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - int val = context.getRegValue(rs) + imm; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rt); - } else { - context.emitGetReg(il, rs); - if (imm != 0) { - il.append(new PUSH(cp, imm)); - il.append(new IADD()); - } - context.emitSetReg(il, rt); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - if (rt != 0) { - regs[rt] = regs[rs] + imm; - } - return true; - } - }; - CPUInstruction i_addu = new CPUInstruction("addu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) + context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - int val = context.getRegValue(rs); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IADD()); - } - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IADD()); - } - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new IADD()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rs] + regs[rt]; - } - return true; - } - }; - CPUInstruction i_and = new CPUInstruction("and", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) & context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - int val = context.getRegValue(rs); - context.emitGetReg(il, rt); - il.append(new PUSH(cp, val)); - il.append(new IAND()); - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - il.append(new PUSH(cp, val)); - il.append(new IAND()); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new IAND()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rs] & regs[rt]; - } - return true; - } - }; - CPUInstruction i_andi = new CPUInstruction("andi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - assert false; - int val = context.getRegValue(rs) & imm; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rt); - } else { - context.emitGetReg(il, rs); - if (imm != 0) { - il.append(new PUSH(cp, imm)); - il.append(new IAND()); - } - context.emitSetReg(il, rt); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - if (rt != 0) { - regs[rt] = regs[rs] & imm; - } - return true; - } - }; - CPUInstruction i_beq = new CPUInstruction("beq", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rs == rt) { - context.emitDelaySlot(il); - il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } else { - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - if (0 != (cr & (1 << rt))) { - // rs const, rt const - il.append(new PUSH(cp, context.getRegValue(rs))); - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitDelaySlot(il); - il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } else { - // rs const, rt varied - il.append(new PUSH(cp, context.getRegValue(rs))); - context.emitGetReg(il, rt); - context.emitDelaySlot(il); - il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - if (0 != (cr & (1 << rt))) { - // rs varied, rt const - context.emitGetReg(il, rs); - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitDelaySlot(il); - il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } else { - // rs varied, rt varied - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - context.emitDelaySlot(il); - il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != R3000.Util.bits_rt(ci)) - return BRANCH_SOMETIMES; - return BRANCH_ALWAYS; - } - }; - CPUInstruction i_bgez = new CPUInstruction("bgez", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - context.emitDelaySlot(il); - if (context.getRegValue(rs) >= 0) { - il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - il.append(new IFGE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_ALWAYS; - } - }; - CPUInstruction i_bgezal = new CPUInstruction("bgezal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_LINK) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - int target = address + 4 + R3000.Util.signed_branch_delta(ci); - if (0 != (cr & (1 << rs))) { - log.warn("Untested constant bgezal"); - context.emitDelaySlot(il); - if (context.getRegValue(rs) >= 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, R3000.R_RETADDR); - context.emitCall(il, target, address + 8); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - // skip over the call if not GE - IFLT lt = new IFLT(null); - il.append(lt); - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, R3000.R_RETADDR); - context.emitCall(il, target, address + 8); - // Link up the to whatever comes next - since we don't now what that is, we'll insert a NOP - lt.setTarget(il.append(new NOP())); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_ALWAYS; - } - }; - CPUInstruction i_bgtz = new CPUInstruction("bgtz", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - context.emitDelaySlot(il); - if (context.getRegValue(rs) > 0) { - il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - il.append(new IFGT(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_NEVER; - } - }; - CPUInstruction i_blez = new CPUInstruction("blez", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - context.emitDelaySlot(il); - if (context.getRegValue(rs) <= 0) { - il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - il.append(new IFLE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_ALWAYS; - } - }; - CPUInstruction i_bltz = new CPUInstruction("bltz", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - context.emitDelaySlot(il); - if (context.getRegValue(rs) < 0) { - il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - il.append(new IFLT(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_NEVER; - } - }; - CPUInstruction i_bltzal = new CPUInstruction("bltzal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_LINK) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - - int cr = context.getConstantRegs(); - int target = address + 4 + R3000.Util.signed_branch_delta(ci); - if (0 != (cr & (1 << rs))) { - log.warn("Untested constant bltzal"); - context.emitDelaySlot(il); - if (context.getRegValue(rs) < 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, R3000.R_RETADDR); - context.emitCall(il, target, address + 8); - } - } else { - context.emitGetReg(il, rs); - context.emitDelaySlot(il); - // skip over the call if not LT - IFGE ge = new IFGE(null); - il.append(ge); - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, R3000.R_RETADDR); - context.emitCall(il, target, address + 8); - // Link up the to whatever comes next - since we don't now what that is, we'll insert a NOP - ge.setTarget(il.append(new NOP())); - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != 0) - return BRANCH_SOMETIMES; - return BRANCH_NEVER; - } - }; - CPUInstruction i_bne = new CPUInstruction("bne", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rs != rt) { - // todo constant values! - int cr = context.getConstantRegs(); - if (0 != (cr & (1 << rs))) { - if (0 != (cr & (1 << rt))) { - // rs const, rt const - il.append(new PUSH(cp, context.getRegValue(rs))); - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitDelaySlot(il); - il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } else { - // rs const, rt varied - il.append(new PUSH(cp, context.getRegValue(rs))); - context.emitGetReg(il, rt); - context.emitDelaySlot(il); - il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } else { - if (0 != (cr & (1 << rt))) { - // rs varied, rt const - context.emitGetReg(il, rs); - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitDelaySlot(il); - il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } else { - // rs varied, rt varied - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - context.emitDelaySlot(il); - il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); - } - } - } - } - - public int getBranchType(int ci) { - if (R3000.Util.bits_rs(ci) != R3000.Util.bits_rt(ci)) - return BRANCH_SOMETIMES; - return BRANCH_NEVER; - } - }; - CPUInstruction i_break = new CPUInstruction("break", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - CPUInstruction i_div = new CPUInstruction("div", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - // reg_lo = regs[rs]/regs[rt]; - // reg_hi = regs[rs]%regs[rt]; - - IFEQ gotoDivideByZero = null; - GOTO gotoWriteRegHi = null; - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - gotoDivideByZero = new IFEQ(null); - il.append(gotoDivideByZero); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, context.getRegValue(rs))); - } else { - context.emitGetReg(il, rs); - } - - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - il.append(new IDIV()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, context.getRegValue(rs))); - } else { - context.emitGetReg(il, rs); - } - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - il.append(new IREM()); - gotoWriteRegHi = new GOTO(null); - il.append(gotoWriteRegHi); - } - // Code for divide by zero - InstructionHandle end = il.getEnd(); - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, context.getRegValue(rs))); - } else { - context.emitGetReg(il, rs); - } - if (gotoDivideByZero != null) { - gotoDivideByZero.setTarget(end.getNext()); - } - il.append(new DUP()); - il.append(new PUSH(cp, 31)); - il.append(new ISHR()); - il.append(new PUSH(cp, 1)); - il.append(new ISHL()); - il.append(new PUSH(cp, 1)); - il.append(new ISUB()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - - InstructionHandle writeRegHi = il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); - if (gotoWriteRegHi != null) { - gotoWriteRegHi.setTarget(writeRegHi); - } - } - }; - - CPUInstruction i_divu = new CPUInstruction("divu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - //long a = longFromUnsigned( regs[rs]); - //long b = longFromUnsigned( regs[rt]); - //reg_lo = (int)(a/b); - //reg_hi = (int)(a%b); - - IFEQ gotoDivideByZero = null; - GOTO gotoWriteRegHi = null; - - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - gotoDivideByZero = new IFEQ(null); - il.append(gotoDivideByZero); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); - } else { - context.emitGetReg(il, rs); - emitLongFromUnsigned(cp, il); - } - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); - } else { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - } - il.append(new LDIV()); - il.append(new L2I()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); - } else { - context.emitGetReg(il, rs); - emitLongFromUnsigned(cp, il); - } - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); - } else { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - } - il.append(new LREM()); - il.append(new L2I()); - gotoWriteRegHi = new GOTO(null); - il.append(gotoWriteRegHi); - } - // Code for divide by zero - InstructionHandle divdieByZero = il.append(new PUSH(cp, -1)); - if (gotoDivideByZero != null) { - gotoDivideByZero.setTarget(divdieByZero); - } - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, context.getRegValue(rs))); - } else { - context.emitGetReg(il, rs); - } - InstructionHandle writeRegHi = il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); - if (gotoWriteRegHi != null) { - gotoWriteRegHi.setTarget(writeRegHi); - } - } - }; - CPUInstruction i_j = new CPUInstruction("j", R3000InstructionSet.class, 0, CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_FAR_TARGET | CPUInstruction.FLAG_UNCONDITIONAL) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - context.emitDelaySlot(il); - int delay = address + 4; - int target = delay & 0xf0000000; - target += ((ci & 0x3ffffff) << 2); - il.append(new GOTO(context.getBranchTarget(target))); - } - }; - CPUInstruction i_jal = new CPUInstruction("jal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_FAR_TARGET | CPUInstruction.FLAG_UNCONDITIONAL | CPUInstruction.FLAG_LINK) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - context.emitDelaySlot(il); - int delay = address + 4; - int target = delay & 0xf0000000; - target += ((ci & 0x3ffffff) << 2); - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, R3000.R_RETADDR); - context.emitCall(il, target, address + 8); - } - }; - CPUInstruction i_jalr = new CPUInstruction("jalr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_UNCONDITIONAL | CPUInstruction.FLAG_LINK) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - - int rs = bits_rs(ci); - int rd = bits_rd(ci); - context.emitDelaySlot(il); - // todo constant! - context.emitGetReg(il, rs); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, address + 8)); - context.emitSetReg(il, rd); - } - context.emitCall(il, address + 8); - } - }; - CPUInstruction i_jr = new CPUInstruction("jr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_UNCONDITIONAL) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - context.emitDelaySlot(il); - int r = bits_rs(ci); - if (0 != (context.getConstantRegs() & (1 << r))) { - context.emitJump(il, context.getRegValue(r)); - } else { - context.emitGetReg(il, bits_rs(ci)); - context.emitJump(il); - } - } - }; - - CPUInstruction i_lb = new CPUInstruction("lb", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM8) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem8(il, context.getRegValue(base) + offset, true); - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } else { - context.emitReadMem8(il, base, offset); - if (rt != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, 24)); - il.append(new ISHL()); - il.append(new PUSH(cp, 24)); - il.append(new ISHR()); - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - } - }; - CPUInstruction i_lbu = new CPUInstruction("lbu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM8) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem8(il, context.getRegValue(base) + offset, false); - } else { - context.emitReadMem8(il, base, offset); - } - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - }; - CPUInstruction i_lh = new CPUInstruction("lh", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM16) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem16(il, context.getRegValue(base) + offset, true); - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } else { - context.emitReadMem16(il, base, offset); - if (rt != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il.append(new PUSH(cp, 16)); - il.append(new ISHL()); - il.append(new PUSH(cp, 16)); - il.append(new ISHR()); - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - } - }; - CPUInstruction i_lhu = new CPUInstruction("lhu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM16) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem16(il, context.getRegValue(base) + offset, false); - } else { - context.emitReadMem16(il, base, offset); - } - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - }; - - CPUInstruction i_lui = new CPUInstruction("lui", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rt = bits_rt(ci); - if (rt != 0) { - il.append(new PUSH(context.getConstantPoolGen(), ci << 16)); - context.emitSetReg(il, rt); - } - } - - public boolean simulate(int ci, int[] regs) { - int rt = bits_rt(ci); - if (rt != 0) { - regs[rt] = ci << 16; - } - return true; - } - }; - CPUInstruction i_lw = new CPUInstruction("lw", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitReadMem32(il, context.getRegValue(base) + offset, false); - } else { - context.emitReadMem32(il, base, offset, false); - } - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - }; - CPUInstruction i_lwc1 = new CPUInstruction("lwc1", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - CPUInstruction i_lwc3 = new CPUInstruction("lwc3", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - CPUInstruction i_lwl = new CPUInstruction("lwl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - // regs[rt]=(regs[rt]&lwl_mask[addr&3])|(value<> low2x8 - // shift = 24 - low2x8; - - // regs[rt] - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - // mask - il.append(new PUSH(cp, 0x00ffffff)); - il.append(new ILOAD(low2x8)); - il.append(new ISHR()); - - // & - il.append(new IAND()); - - // value - context.emitReadMem32(il, base, offset, true); - - // shift - il.append(new PUSH(cp, 24)); - il.append(new ILOAD(low2x8)); - il.append(new ISUB()); - - // << - il.append(new ISHL()); - - // | - il.append(new IOR()); - } - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - }; - CPUInstruction i_lwr = new CPUInstruction("lwr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - // regs[rt]=(regs[rt]&lwr_mask[addr&3])|((value>>lwr_shift[addr&3])&~lwr_mask[addr&3]); - - if (0 != (context.getConstantRegs() & (1 << base))) { - // constant address - int addr = context.getRegValue(base) + offset; - int mask = lwr_mask[addr & 3]; - int shift = lwr_shift[addr & 3]; - - // regs[rt]&mask; - if (0 != (context.getConstantRegs() & (1 << rt))) { - int val = context.getRegValue(rt); - if (mask != 0) { - il.append(new PUSH(cp, val & mask)); - } - } else { - if (mask != 0) { - context.emitGetReg(il, rt); - il.append(new PUSH(cp, mask)); - il.append(new IAND()); - } - } - - // value>>shift - context.emitReadMem32(il, addr, true); - if (0 != shift) { - il.append(new PUSH(cp, shift)); - il.append(new ISHR()); - } - - if (0 != mask) { - int nmask = ~mask; - il.append(new PUSH(cp, nmask)); - il.append(new IAND()); - il.append(new IOR()); - } - } else { - // low2x8 = ((regs[base]+offset)&3) << 8 - int low2x8 = context.getTempLocal(0); - int mask = context.getTempLocal(1); - - context.emitGetReg(il, base); - if (offset != 0) { - il.append(new PUSH(cp, offset)); - il.append(new IADD()); - } - il.append(new PUSH(cp, 3)); - il.append(new IAND()); - il.append(new PUSH(cp, 3)); - il.append(new ISHL()); - il.append(new ISTORE(low2x8)); - - // private final static int[] lwr_mask = new int[] { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00}; - // private final static int[] lwr_shift = new int[] { 0, 8, 16, 24}; - - // mask = 0xffffff00 << (24 - low2x8); - // shift = low2x8 - - // regs[rt]&mask - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - } - - if (false) { - // for some reason this causes a MASSIVE slowdown, but I can't figure - // out why; the hotspot compiler produces identical code!!!... would be good - // to know so we don't hit similar things elsewhere. - il.append(new PUSH(cp, 0xffffff00)); - il.append(new PUSH(cp, 24)); - il.append(new ILOAD(low2x8)); - il.append(new ISUB()); - il.append(new ISHL()); - il.append(new IAND()); - } else { - il.append(new PUSH(cp, 24)); - il.append(new ILOAD(low2x8)); - il.append(new ISUB()); - il.append(new PUSH(cp, 0xffffff00)); - il.append(new SWAP()); - il.append(new ISHL()); - il.append(new ISTORE(mask)); - il.append(new ILOAD(mask)); - il.append(new IAND()); - } - - // value>>shift; - context.emitReadMem32(il, base, offset, true); - il.append(new ILOAD(low2x8)); - il.append(new ISHR()); - - // &~mask - il.append(new ILOAD(mask)); - il.append(new PUSH(cp, -1)); - il.append(new IXOR()); - il.append(new IAND()); - - il.append(new IOR()); - } - if (rt != 0) { - context.emitSetReg(il, rt); - } else { - il.append(new POP()); - } - } - }; - CPUInstruction i_mfhi = new CPUInstruction("mfhi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - //int rs = bits_rs( ci ); - //int rt = bits_rt( ci ); - int rd = bits_rd(ci); - if (rd != 0) { - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); - context.emitSetReg(il, rd); - } - - } - }; - CPUInstruction i_mflo = new CPUInstruction("mflo", R3000InstructionSet.class, 0, CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - //int rs = bits_rs( ci ); - //int rt = bits_rt( ci ); - int rd = bits_rd(ci); - if (rd != 0) { - il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - context.emitSetReg(il, rd); - } - - } - }; - CPUInstruction i_mthi = new CPUInstruction("mthi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS); - CPUInstruction i_mtlo = new CPUInstruction("mtlo", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS); - CPUInstruction i_mult = new CPUInstruction("mult", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - // long result = ((long)regs[rs])*((long)regs[rt]); - - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, (long) context.getRegValue(rs))); - } else { - context.emitGetReg(il, rs); - il.append(new I2L()); - } - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, (long) context.getRegValue(rt))); - } else { - context.emitGetReg(il, rt); - il.append(new I2L()); - } - il.append(new LMUL()); - il.append(new DUP2()); - il.append(new PUSH(cp, 32)); - il.append(new LSHR()); - il.append(new L2I()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); - il.append(new L2I()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - } - }; - CPUInstruction i_multu = new CPUInstruction("multu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - // long result = (longFromUnsigned(regs[rs]))*(longFromUnsigned(regs[rt])); - if (0 != (context.getConstantRegs() & (1 << rs))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); - } else { - context.emitGetReg(il, rs); - emitLongFromUnsigned(cp, il); - } - if (0 != (context.getConstantRegs() & (1 << rt))) { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); - } else { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - } - il.append(new LMUL()); - il.append(new DUP2()); - il.append(new PUSH(cp, 32)); - il.append(new LSHR()); - il.append(new L2I()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); - il.append(new L2I()); - il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); - } - }; - CPUInstruction i_nor = new CPUInstruction("nor", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = (context.getRegValue(rs) | context.getRegValue(rt)) ^ 0xffffffff; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - int val = context.getRegValue(rs); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IOR()); - } - il.append(new PUSH(cp, 0xffffffff)); - il.append(new IXOR()); - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IOR()); - } - il.append(new PUSH(cp, 0xffffffff)); - il.append(new IXOR()); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new IOR()); - il.append(new PUSH(cp, 0xffffffff)); - il.append(new IXOR()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = (regs[rs] | regs[rt]) ^ 0xffffffff; - } - return true; - } - }; - CPUInstruction i_or = new CPUInstruction("or", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) | context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - int val = context.getRegValue(rs); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IOR()); - } - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new IOR()); - } - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new IOR()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rs] | regs[rt]; - } - return true; - } - }; - CPUInstruction i_ori = new CPUInstruction("ori", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rt != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - int val = context.getRegValue(rs) | imm; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rt); - } else { - context.emitGetReg(il, rs); - if (imm != 0) { - il.append(new PUSH(cp, imm)); - il.append(new IOR()); - } - context.emitSetReg(il, rt); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - if (rt != 0) { - regs[rt] = regs[rs] | imm; - } - return true; - } - }; - CPUInstruction i_sb = new CPUInstruction("sb", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM16) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - InstructionList il2 = new InstructionList(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il2.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il2, rt); - } - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitWriteMem8(il, context.getRegValue(base) + offset, il2); - } else { - il.append(il2); - context.emitWriteMem8(il, base, offset); - } - il2.dispose(); - } - }; - - CPUInstruction i_sh = new CPUInstruction("sh", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM8) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - InstructionList il2 = new InstructionList(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il2.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il2, rt); - } - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitWriteMem16(il, context.getRegValue(base) + offset, il2); - } else { - il.append(il2); - context.emitWriteMem16(il, base, offset); - } - il2.dispose(); - } - }; - CPUInstruction i_sll = new CPUInstruction("sll", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int sa = bits_sa(ci); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rt) << sa; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - il.append(new PUSH(cp, sa)); - il.append(new ISHL()); - context.emitSetReg(il, rd); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int sa = bits_sa(ci); - if (rd != 0) { - regs[rd] = regs[rt] << sa; - } - return true; - } - }; - CPUInstruction i_sllv = new CPUInstruction("sllv", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int rs = bits_rs(ci); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - assert false; - int val = context.getRegValue(rt) << (context.getRegValue(rs) & 31); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - return; - } else { - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rs))) { - context.emitGetReg(il, rt); - il.append(new PUSH(cp, context.getRegValue(rs) & 31)); - } else { - context.emitGetReg(il, rt); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } - il.append(new ISHL()); - context.emitSetReg(il, rd); - } - } - - public boolean simulate(int ci, int[] regs) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int rs = bits_rs(ci); - if (rd != 0) { - regs[rd] = regs[rt] << (regs[rs] & 31); - } - return true; - } - }; - CPUInstruction i_slt = new CPUInstruction("slt", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - // regs[rd]=(regs[rs]imm - IFLT lt = new IFLT(null); - il.append(lt); - il.append(new ICONST(0)); - GOTO gt = new GOTO(null); - il.append(gt); - lt.setTarget(il.append(new ICONST(1))); - context.emitSetReg(il, rt); - // the goto is whatever got emitted after the ICONST(1); - gt.setTarget(lt.getTarget().getNext()); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - if (rt != 0) { - regs[rt] = (longFromUnsigned(regs[rs]) < (long) imm) ? 1 : 0; - } - return true; - } - }; - CPUInstruction i_sltu = new CPUInstruction("sltu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - //regs[rt] = (longFromUnsigned(regs[rs])rt - IFLT lt = new IFLT(null); - il.append(lt); - il.append(new ICONST(0)); - GOTO gt = new GOTO(null); - il.append(gt); - lt.setTarget(il.append(new ICONST(1))); - context.emitSetReg(il, rd); - // the goto is whatever got emitted after the ICONST(1); - gt.setTarget(lt.getTarget().getNext()); - - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = (longFromUnsigned(regs[rs]) < longFromUnsigned(regs[rt])) ? 1 : 0; - } - return true; - } - }; - CPUInstruction i_sra = new CPUInstruction("sra", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int sa = bits_sa(ci); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rt) >> sa; - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - il.append(new PUSH(cp, sa)); - il.append(new ISHR()); - context.emitSetReg(il, rd); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int sa = bits_sa(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rt] >> sa; - } - return true; - } - }; - CPUInstruction i_srav = new CPUInstruction("srav", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int rs = bits_rs(ci); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - assert false; - int val = context.getRegValue(rt) >> (context.getRegValue(rs) & 31); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - return; - } else { - il.append(new PUSH(cp, context.getRegValue(rt))); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rs))) { - context.emitGetReg(il, rt); - il.append(new PUSH(cp, context.getRegValue(rs) & 31)); - } else { - context.emitGetReg(il, rt); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } - il.append(new ISHR()); - context.emitSetReg(il, rd); - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = regs[rt] >> regs[rs]; - } - return true; - } - }; - CPUInstruction i_srl = new CPUInstruction("srl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int sa = bits_sa(ci); - // regs[rd] = (int)((longFromUnsigned(regs[rt]))>>sa); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = (int) (longFromUnsigned(context.getRegValue(rt)) >> sa); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - il.append(new PUSH(cp, sa)); - il.append(new LSHR()); - il.append(new L2I()); - context.emitSetReg(il, rd); - } - } - } - - public boolean simulate(int ci, int[] regs) { - int sa = bits_sa(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = (int) ((longFromUnsigned(regs[rt])) >> sa); - } - return true; - } - }; - CPUInstruction i_srlv = new CPUInstruction("srlv", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int rs = bits_rs(ci); - if (rd != 0) { - ConstantPoolGen cp = context.getConstantPoolGen(); - if (0 != (context.getConstantRegs() & (1 << rt))) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - assert false; - int val = (int) longFromUnsigned(context.getRegValue(rt)) >> (context.getRegValue(rs) & 31); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - return; - } else { - il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rs))) { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - il.append(new PUSH(cp, context.getRegValue(rs) & 31)); - } else { - context.emitGetReg(il, rt); - emitLongFromUnsigned(cp, il); - context.emitGetReg(il, rs); - il.append(new PUSH(cp, 31)); - il.append(new IAND()); - } - } - il.append(new LSHR()); - il.append(new L2I()); - context.emitSetReg(il, rd); - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - regs[rd] = (int) ((longFromUnsigned(regs[rt])) >> regs[rs]); - } - return true; - } - }; - CPUInstruction i_sub; - if (ignoreArithmeticOverflow) { - i_sub = new CPUInstruction("sub", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) - context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - il.append(new PUSH(cp, context.getRegValue(rs))); - context.emitGetReg(il, rt); - il.append(new ISUB()); - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new ISUB()); - } - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new ISUB()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - if (rd != 0) { - regs[rd] = regs[rs] - regs[rt]; - } - return true; - } - }; - } else { - i_sub = new CPUInstruction("sub", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - } - CPUInstruction i_subu = new CPUInstruction("subu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - ConstantPoolGen cp = context.getConstantPoolGen(); - - if (rd != 0) { - if (0 != (context.getConstantRegs() & (1 << rs))) { - if (0 != (context.getConstantRegs() & (1 << rt))) { - assert false; - int val = context.getRegValue(rs) - context.getRegValue(rt); - il.append(new PUSH(cp, val)); - context.emitSetReg(il, rd); - } else { - il.append(new PUSH(cp, context.getRegValue(rs))); - context.emitGetReg(il, rt); - il.append(new ISUB()); - context.emitSetReg(il, rd); - } - } else { - if (0 != (context.getConstantRegs() & (1 << rt))) { - context.emitGetReg(il, rs); - int val = context.getRegValue(rt); - if (val != 0) { - il.append(new PUSH(cp, val)); - il.append(new ISUB()); - } - context.emitSetReg(il, rd); - } else { - context.emitGetReg(il, rs); - context.emitGetReg(il, rt); - il.append(new ISUB()); - context.emitSetReg(il, rd); - } - } - } - } - - public boolean simulate(int ci, int[] regs) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - if (rd != 0) { - regs[rd] = regs[rs] - regs[rt]; - } - return true; - } - }; - CPUInstruction i_sw = new CPUInstruction("sw", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - InstructionList il2 = new InstructionList(); - - if (0 != (context.getConstantRegs() & (1 << rt))) { - ConstantPoolGen cp = context.getConstantPoolGen(); - il2.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il2, rt); - } - if (0 != (context.getConstantRegs() & (1 << base))) { - context.emitWriteMem32(il, context.getRegValue(base) + offset, il2, false); - } else { - context.emitWriteMem32(il, base, offset, il2, false); - } - il2.dispose(); - } - }; - - CPUInstruction i_swc1 = new CPUInstruction("swc1", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - CPUInstruction i_swc3 = new CPUInstruction("swc3", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); - CPUInstruction i_swl = new CPUInstruction("swl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - InstructionList il2 = new InstructionList(); - // private static final int[] swl_mask = new int[] { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000}; - // private static final int[] swl_shift = new int[] { 24, 16, 8, 0}; - // value = (value&swl_mask[addr&3])|((regs[rt]>>swl_shift[addr&3])&~swl_mask[addr&3]); - - if (0 != (context.getConstantRegs() & (1 << base))) { - // constant address - int addr = context.getRegValue(base) + offset; - int mask = swl_mask[addr & 3]; - int shift = swl_shift[addr & 3]; - - // regs[rt]>>shift & ~mask; - if (0 != (context.getConstantRegs() & (1 << rt))) { - il2.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il2, rt); - } - if (0 != shift) { - il2.append(new PUSH(cp, shift)); - il2.append(new ISHR()); - } - if (mask != 0) { - il2.append(new PUSH(cp, ~mask)); - il2.append(new IAND()); - } - - // value&mask - context.emitReadMem32(il2, addr, true); - il2.append(new PUSH(cp, mask)); - il2.append(new IAND()); - - il2.append(new IOR()); - context.emitWriteMem32(il, addr, il2, true); - } else { - // low2x8 = ((regs[base]+offset)&3) << 8 - int low2x8 = context.getTempLocal(0); - int maskVar = context.getTempLocal(1); - context.emitGetReg(il2, base); - if (offset != 0) { - il2.append(new PUSH(cp, offset)); - il2.append(new IADD()); - } - il2.append(new PUSH(cp, 3)); - il2.append(new IAND()); - il2.append(new PUSH(cp, 3)); - il2.append(new ISHL()); - il2.append(new ISTORE(low2x8)); - - // mask = 0xffffff00 << low2x8 - // shift = 24 - low2x8; - - il2.append(new PUSH(cp, 0xffffff00)); - il2.append(new ILOAD(low2x8)); - il2.append(new ISHL()); - il2.append(new ISTORE(maskVar)); - - // regs[rt]>>shift & ~mask; - if (0 != (context.getConstantRegs() & (1 << rt))) { - il2.append(new PUSH(cp, context.getRegValue(rt))); - } else { - context.emitGetReg(il2, rt); - } - il2.append(new PUSH(cp, 24)); - il2.append(new ILOAD(low2x8)); - il2.append(new ISUB()); - il2.append(new ISHR()); - - il2.append(new ILOAD(maskVar)); - il2.append(new PUSH(cp, 0xffffffff)); - il2.append(new IXOR()); - il2.append(new IAND()); - - // value&mask; - context.emitReadMem32(il2, base, offset, true); - il2.append(new ILOAD(maskVar)); - il2.append(new IAND()); - - il2.append(new IOR()); - context.emitWriteMem32(il, base, offset, il2, true); - } - il2.dispose(); - } - }; - CPUInstruction i_swr = new CPUInstruction("swr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { - public void compile(CompilationContext context, int address, int ci, InstructionList il) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - - ConstantPoolGen cp = context.getConstantPoolGen(); - - InstructionList il2 = new InstructionList(); - // private static final int[] swr_mask = new int[] { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff}; - // private static final int[] swr_shift = new int[] { 0, 8, 16, 24}; - // value = (value&swr_mask[addr&3])|(regs[rt]<> (24-low2x8) - // shift = low2x8; - - // regs[rt]<> 21) & 0x1f; - } - - private static final int bits_rt(final int ci) { - return (ci >> 16) & 0x1f; - } - - private static final int bits_rd(final int ci) { - return (ci >> 11) & 0x1f; - } - - private static final int bits_sa(final int ci) { - return (ci >> 6) & 0x1f; - } - - private static final boolean mask_bit31(int x) { - return (x < 0); - } - - private static final int bits25_6(int x) { - return (x >> 6) & 0xfffff; - } - - private static final int sign_extend(int x) { - return ((x) << 16) >> 16; - } - - private static final int signed_branch_delta(int x) { - return sign_extend(x) << 2; - } - - private static final int lo(int x) { - return x & 0xffff; - } - - private static final long longFromUnsigned(int x) { - return ((long) x) & 0xffffffffL; - } - - public static void interpret_add(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - int res = Refs.r3000Regs[rs] + Refs.r3000Regs[rt]; - - // arithmetic overflow if rs and rs have same top bit (i.e. sign) - // and the result has a different sign - if (!ignoreArithmeticOverflow) { - if (!mask_bit31(Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]) && mask_bit31(res ^ Refs.r3000Regs[rs])) { - Refs.scp.signalIntegerOverflowException(); - return; - } - } - if (rd != 0) { - Refs.r3000Regs[rd] = res; - } - } - - public static void interpret_addi(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - - int res = Refs.r3000Regs[rs] + imm; - - // arithmetic overflow if rs and rs have same top bit (i.e. sign) - // and the result has a different sign - if (!ignoreArithmeticOverflow) { - if (!mask_bit31(Refs.r3000Regs[rs] ^ imm) && mask_bit31(res ^ Refs.r3000Regs[rs])) { - Refs.scp.signalIntegerOverflowException(); - return; - } - } - if (rt != 0) { - Refs.r3000Regs[rt] = res; - } - } - - // getstatic #reg1 - // iconst imm - // iadd - // putstatic #reg2 - - public static void interpret_addiu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - - if (rt != 0) { - Refs.r3000Regs[rt] = Refs.r3000Regs[rs] + imm; - } - } - - public static void interpret_addu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rs] + Refs.r3000Regs[rt]; - } - } - - public static void interpret_and(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rs] & Refs.r3000Regs[rt]; - } - } - - public static void interpret_andi(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - - if (rt != 0) { - Refs.r3000Regs[rt] = Refs.r3000Regs[rs] & imm; - } - } - - public static void interpret_beq(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - if (Refs.r3000Regs[rs] == Refs.r3000Regs[rt]) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - public static void interpret_bgez(final int ci) { - int rs = bits_rs(ci); - - if (Refs.r3000Regs[rs] >= 0) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - public static void interpret_bgezal(final int ci) { - int rs = bits_rs(ci); - // note operation is undefined if rs==31 so we don't care - if (Refs.r3000Regs[rs] >= 0) { - Refs.r3000Regs[R3000.R_RETADDR] = Refs.r3000.getPC() + 8; // return address - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - } - - public static void interpret_bgtz(final int ci) { - int rs = bits_rs(ci); - - if (Refs.r3000Regs[rs] > 0) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - public static void interpret_blez(final int ci) { - int rs = bits_rs(ci); - - if (Refs.r3000Regs[rs] <= 0) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - public static void interpret_bltz(final int ci) { - int rs = bits_rs(ci); - - if (Refs.r3000Regs[rs] < 0) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - public static void interpret_bltzal(final int ci) { - int rs = bits_rs(ci); - // note operation is undefined if rs==31 so we don't care - if (Refs.r3000Regs[rs] < 0) { - Refs.r3000Regs[R3000.R_RETADDR] = Refs.r3000.getPC() + 8; // return address - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - } - - public static void interpret_bne(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - if (Refs.r3000Regs[rs] != Refs.r3000Regs[rt]) - Refs.r3000.interpreterBranch(signed_branch_delta(ci)); - } - - // todo recheck this; this is a hack to avoid problems with certain versions of HotSpot (perhaps 1.4?) - protected static boolean breakHotspot; - - public static void interpret_break(final int ci) { - // TODO - note this is used for division by zero in wipeout! - breakHotspot = false; - Refs.scp.signalBreakException(); - } - - public static void interpret_div(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - if (Refs.r3000Regs[rt] != 0) { - Refs.r3000.setLO(Refs.r3000Regs[rs] / Refs.r3000Regs[rt]); - Refs.r3000.setHI(Refs.r3000Regs[rs] % Refs.r3000Regs[rt]); - } else { - // According to docs, this is what it does - Refs.r3000.setLO(((Refs.r3000Regs[rs] >>> 31) << 1) - 1); - Refs.r3000.setHI(Refs.r3000Regs[rs]); - } - } - - public static void interpret_divu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - if (Refs.r3000Regs[rt] != 0) { - long a = longFromUnsigned(Refs.r3000Regs[rs]); - long b = longFromUnsigned(Refs.r3000Regs[rt]); - Refs.r3000.setLO((int) (a / b)); - Refs.r3000.setHI((int) (a % b)); - } else { - // According to docs, this is what it does - Refs.r3000.setLO(-1); - Refs.r3000.setHI(Refs.r3000Regs[rs]); - } - } - - public static void interpret_j(final int ci) { - int delay = Refs.r3000.getPC() + 4; - int target = delay & 0xf0000000; - target += ((ci & 0x3ffffff) << 2); - Refs.r3000.interpreterBranch(target - delay); - } - - - public static void interpret_jal(final int ci) { - int pc = Refs.r3000.getPC(); - int delay = pc + 4; - int target = (delay & 0xf0000000); - target += ((ci & 0x3ffffff) << 2); - - Refs.addressSpace.tagClearPollCounters(); - Refs.r3000Regs[R3000.R_RETADDR] = pc + 8; - Refs.r3000.interpreterJumpAndLink(target - delay, target, pc + 8); - } - - public static void interpret_jalr(final int ci) { - int rs = bits_rs(ci); - int rd = bits_rd(ci); - int pc = Refs.r3000.getPC(); - if (rd != 0) { - Refs.r3000Regs[rd] = pc + 8; - } - Refs.addressSpace.tagClearPollCounters(); - int delay = pc + 4; - int target = Refs.r3000Regs[rs]; - Refs.r3000.interpreterJumpAndLink(target - delay, target, pc + 8); - } - - public static void interpret_jr(final int ci) { - int rs = bits_rs(ci); - // for now, mask to low PC - int target = Refs.r3000Regs[rs]; - int delay = Refs.r3000.getPC() + 4; - Refs.r3000.interpreterJump(target - delay, target); - } - - public static void interpret_lb(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead8(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read8(addr); - //System.out.println("lb "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( (value<<24)>>24, 8)); - if (rt != 0) { - value = (value << 24) >> 24; - Refs.r3000Regs[rt] = value; - } - } - - public static void interpret_lbu(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead8(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read8(addr); - //System.out.println("lbu "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( value, 8)); - if (rt != 0) { - Refs.r3000Regs[rt] = value; - } - } - - public static void interpret_lh(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead16(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read16(addr); - //System.out.println("lh "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( (value<<16)>>16, 8)); - if (rt != 0) { - value = (value << 16) >> 16; - Refs.r3000Regs[rt] = value; - } - } - - public static void interpret_lhu(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead16(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read16(addr); - //System.out.println("lhu "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( value, 8)); - if (rt != 0) { - Refs.r3000Regs[rt] = value; - } - } - - public static void interpret_lui(final int ci) { - int rt = bits_rt(ci); - if (rt != 0) { - Refs.r3000Regs[rt] = ci << 16; - } - } - - public static void interpret_lw(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read32(addr); - if (rt != 0) { - Refs.r3000Regs[rt] = value; - } - } - - public static void interpret_lwc1(final int ci) { - breakHotspot = false; - Refs.scp.signalReservedInstructionException(); - } - - public static void interpret_lwc3(final int ci) { - breakHotspot = false; - Refs.scp.signalReservedInstructionException(); - } - - private final static int[] lwl_mask = new int[]{0x00ffffff, 0x0000ffff, 0x000000ff, 0x00000000}; - private final static int[] lwl_shift = new int[]{24, 16, 8, 0}; - - public static void interpret_lwl(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read32(addr & ~3); - if (rt != 0) { - Refs.r3000Regs[rt] = (Refs.r3000Regs[rt] & lwl_mask[addr & 3]) | (value << lwl_shift[addr & 3]); - } - } - - private final static int[] lwr_mask = new int[]{0x00000000, 0xff000000, 0xffff0000, 0xffffff00}; - private final static int[] lwr_shift = new int[]{0, 8, 16, 24}; - - public static void interpret_lwr(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); - } - int value = Refs.addressSpace.read32(addr & ~3); - if (rt != 0) { - Refs.r3000Regs[rt] = (Refs.r3000Regs[rt] & lwr_mask[addr & 3]) | ((value >> lwr_shift[addr & 3]) & ~lwr_mask[addr & 3]); - } - } - - public static void interpret_mfhi(final int ci) { - int rd = bits_rd(ci); - Refs.r3000Regs[rd] = Refs.r3000.getHI(); - } - - public static void interpret_mflo(final int ci) { - int rd = bits_rd(ci); - Refs.r3000Regs[rd] = Refs.r3000.getLO(); - } - - public static void interpret_mthi(final int ci) { - int rs = bits_rs(ci); - Refs.r3000.setHI(Refs.r3000Regs[rs]); - } - - public static void interpret_mtlo(final int ci) { - int rs = bits_rs(ci); - Refs.r3000.setLO(Refs.r3000Regs[rs]); - } - - public static void interpret_mult(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - long result = ((long) Refs.r3000Regs[rs]) * ((long) Refs.r3000Regs[rt]); - Refs.r3000.setLO((int) result); - Refs.r3000.setHI((int) (result >> 32)); - } - - public static void interpret_multu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - - long result = (longFromUnsigned(Refs.r3000Regs[rs])) * (longFromUnsigned(Refs.r3000Regs[rt])); - Refs.r3000.setLO((int) result); - Refs.r3000.setHI((int) (result >> 32)); - } - - public static void interpret_nor(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = (Refs.r3000Regs[rs] | Refs.r3000Regs[rt]) ^ 0xffffffff; - } - } - - public static void interpret_or(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rs] | Refs.r3000Regs[rt]; - } - } - - public static void interpret_ori(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - if (rt != 0) { - Refs.r3000Regs[rt] = Refs.r3000Regs[rs] | lo(ci); - } - } - - public static void interpret_sb(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); - } - Refs.addressSpace.write8(addr, Refs.r3000Regs[rt]); - } - - public static void interpret_sh(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); - } - Refs.addressSpace.write16(addr, Refs.r3000Regs[rt]); - } - - public static void interpret_sll(final int ci) { - if (ci == 0) - return; // nop - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int sa = bits_sa(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rt] << sa; - } - } - - public static void interpret_sllv(final int ci) { - int rd = bits_rd(ci); - int rt = bits_rt(ci); - int rs = bits_rs(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rt] << (Refs.r3000Regs[rs] & 31); - } - } - - public static void interpret_slt(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = (Refs.r3000Regs[rs] < Refs.r3000Regs[rt]) ? 1 : 0; - } - } - - public static void interpret_slti(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = sign_extend(ci); - if (rt != 0) { - Refs.r3000Regs[rt] = (Refs.r3000Regs[rs] < imm) ? 1 : 0; - } - } - - public static void interpret_sltiu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int imm = lo(ci); - if (rt != 0) { - Refs.r3000Regs[rt] = (longFromUnsigned(Refs.r3000Regs[rs]) < (long) imm) ? 1 : 0; - } - } - - public static void interpret_sltu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = (longFromUnsigned(Refs.r3000Regs[rs]) < longFromUnsigned(Refs.r3000Regs[rt])) ? 1 : 0; - } - } - - public static void interpret_srl(final int ci) { - int sa = bits_sa(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = (int) ((longFromUnsigned(Refs.r3000Regs[rt])) >> sa); - } - } - - public static void interpret_srlv(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = (int) ((longFromUnsigned(Refs.r3000Regs[rt])) >> Refs.r3000Regs[rs]); - } - } - - public static void interpret_sra(final int ci) { - int sa = bits_sa(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rt] >> sa; - } - } - - public static void interpret_srav(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rt] >> Refs.r3000Regs[rs]; - } - } - - public static void interpret_sub(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - int res = Refs.r3000Regs[rs] - Refs.r3000Regs[rt]; - - // arithmetic overflow if rs and rs have different top bit (i.e. sign) - // and the result has a different sign to rs - if (!ignoreArithmeticOverflow) { - if (mask_bit31(Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]) && mask_bit31(res ^ Refs.r3000Regs[rs])) { - Refs.scp.signalIntegerOverflowException(); - return; - } - } - if (rd != 0) { - Refs.r3000Regs[rd] = res; - } - } - - public static void interpret_subu(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rs] - Refs.r3000Regs[rt]; - } - } - - public static void interpret_sw(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - if (base != R3000.R_SP) { - Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); - } - Refs.addressSpace.write32(addr, Refs.r3000Regs[rt]); - - // tmp hack - //if (addr==0x800dee54) { - // System.out.println("Write cdCurrentCmd "+MiscUtil.toHex( Refs.r3000Regs[rt], 8)+" at "+MiscUtil.toHex( Refs.r3000.getPC(), 8)); - // m_cpuCmdPending = true; - //} - } - - public static void interpret_swc1(final int ci) { - breakHotspot = false; - Refs.scp.signalReservedInstructionException(); - } - - public static void interpret_swc3(final int ci) { - breakHotspot = false; - Refs.scp.signalReservedInstructionException(); - } - - private static final int[] swl_mask = new int[]{0xffffff00, 0xffff0000, 0xff000000, 0x00000000}; - private static final int[] swl_shift = new int[]{24, 16, 8, 0}; - - public static void interpret_swl(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); - int value = Refs.addressSpace.read32(addr & ~3); - value = (value & swl_mask[addr & 3]) | ((Refs.r3000Regs[rt] >> swl_shift[addr & 3]) & ~swl_mask[addr & 3]); - Refs.addressSpace.write32(addr & ~3, value); - } - - private static final int[] swr_mask = new int[]{0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff}; - private static final int[] swr_shift = new int[]{0, 8, 16, 24}; - - public static void interpret_swr(final int ci) { - int base = bits_rs(ci); - int rt = bits_rt(ci); - int offset = sign_extend(ci); - int addr = Refs.r3000Regs[base] + offset; - Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); - int value = Refs.addressSpace.read32(addr & ~3); - value = (value & swr_mask[addr & 3]) | (Refs.r3000Regs[rt] << swr_shift[addr & 3]); - Refs.addressSpace.write32(addr & ~3, value); - } - - public static void interpret_syscall(final int ci) { - breakHotspot = false; - Refs.scp.signalSyscallException(); - } - - public static void interpret_xor(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - int rd = bits_rd(ci); - if (rd != 0) { - Refs.r3000Regs[rd] = Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]; - } - } - - public static void interpret_xori(final int ci) { - int rs = bits_rs(ci); - int rt = bits_rt(ci); - if (rt != 0) { - Refs.r3000Regs[rt] = Refs.r3000Regs[rs] ^ lo(ci); - } - } - - public static void emitLongFromUnsigned(ConstantPoolGen cp, InstructionList il) { - il.append(new I2L()); - il.append(new PUSH(cp, 0xffffffffL)); - il.append(new LAND()); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java b/src/runtime/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java deleted file mode 100644 index e59d201..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.sio; - -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; - -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.util.Map; - -// todo allow different mappings -public class AWTKeyboardController extends StandardController implements KeyListener { - protected KeyMapping mapping; - - protected static final KeyMapping DEF_CONTROLLER_0_MAPPING; - - static { - DEF_CONTROLLER_0_MAPPING = new KeyMapping(); - - DEF_CONTROLLER_0_MAPPING.put(PADstart, KeyEvent.VK_SPACE); - DEF_CONTROLLER_0_MAPPING.put(PADselect, KeyEvent.VK_S); - DEF_CONTROLLER_0_MAPPING.put(PADLup, KeyEvent.VK_UP); - DEF_CONTROLLER_0_MAPPING.put(PADLleft, KeyEvent.VK_LEFT); - DEF_CONTROLLER_0_MAPPING.put(PADLright, KeyEvent.VK_RIGHT); - DEF_CONTROLLER_0_MAPPING.put(PADLdown, KeyEvent.VK_DOWN); - DEF_CONTROLLER_0_MAPPING.put(PADRup, KeyEvent.VK_8); - DEF_CONTROLLER_0_MAPPING.put(PADRup, KeyEvent.VK_KP_UP); - DEF_CONTROLLER_0_MAPPING.put(PADRdown, KeyEvent.VK_K); - DEF_CONTROLLER_0_MAPPING.put(PADRleft, KeyEvent.VK_KP_LEFT); - DEF_CONTROLLER_0_MAPPING.put(PADRright, KeyEvent.VK_I); - DEF_CONTROLLER_0_MAPPING.put(PADRright, KeyEvent.VK_KP_RIGHT); - DEF_CONTROLLER_0_MAPPING.put(PADRdown, KeyEvent.VK_KP_DOWN); - DEF_CONTROLLER_0_MAPPING.put(PADRleft, KeyEvent.VK_U); - DEF_CONTROLLER_0_MAPPING.put(PADL1, KeyEvent.VK_1); - DEF_CONTROLLER_0_MAPPING.put(PADL2, KeyEvent.VK_Q); - DEF_CONTROLLER_0_MAPPING.put(PADR1, KeyEvent.VK_2); - DEF_CONTROLLER_0_MAPPING.put(PADR2, KeyEvent.VK_W); - } - - public static class KeyMapping { - private Map map = CollectionsFactory.newHashMap(); - - public int get(int vkey) { - Integer mask = map.get(vkey); - if (mask != null) - return mask; - return 0; - } - - public void put(int mask, int vkey) { - map.put(vkey, mask); - } - } - - public AWTKeyboardController() { - this(DEF_CONTROLLER_0_MAPPING); - } - - public AWTKeyboardController(KeyMapping mapping) { - super("JPSX AWT Keyboard Controller"); - this.mapping = mapping; - } - - @Override - public void init() { - super.init(); - RuntimeConnections.KEY_LISTENERS.add(this); - } - - public void resolveConnections() { - // for now just connect to the left serial port - HardwareComponentConnections.LEFT_PORT_INSTANCE.resolve().connect(this); - } - - public void keyTyped(KeyEvent e) { - } - - public void keyPressed(KeyEvent e) { - int vkey = e.getKeyCode(); - pressed(mapping.get(vkey)); - } - - public void keyReleased(KeyEvent e) { - int vkey = e.getKeyCode(); - released(mapping.get(vkey)); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java b/src/runtime/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java deleted file mode 100644 index 35da454..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.sio; - -import org.jpsx.api.components.hardware.sio.SerialDevice; -import org.jpsx.runtime.JPSXComponent; - -/** - * just old BIOS style pad - no two way comms - */ -public abstract class BasicPad extends JPSXComponent implements SerialDevice { - public abstract int getType(); // e.g. 0x41 for standard controller (type and size really!) - - public abstract void getState(byte[] buffer); - - protected BasicPad(String description) { - super(description); - } - - protected byte[] rxBuffer = new byte[32]; - protected byte[] txBuffer = new byte[32]; - protected int state; - protected int txIndex; - - public void prepareForTransfer() { - getState(rxBuffer); - state = 0; - txIndex = 0; - } - - public int receive() { - int rc; - if (state == 0) { - rc = 0x00; - } else if (state == 1) { - rc = getType(); - if (rc == 0x41) { - if (txBuffer[0] == 0x43) { - rc = 0x43; - } - if (txBuffer[0] == 0x45) { - rc = 0xf3; - } - } - } else if (state == 2) { - rc = 0x5a; - } else { - rc = rxBuffer[state - 3]; - } - state++; - return rc; - } - - public void send(int data) { - txBuffer[txIndex++] = (byte) data; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/SIO0.java b/src/runtime/java/org/jpsx/runtime/components/hardware/sio/SIO0.java deleted file mode 100644 index a96e2cc..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/SIO0.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.sio; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.irq.IRQController; -import org.jpsx.api.components.hardware.sio.SerialDevice; -import org.jpsx.api.components.hardware.sio.SerialPort; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.IRQOwnerBase; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -public class SIO0 extends SingletonJPSXComponent implements MemoryMapped { - private static final Logger log = Logger.getLogger("SIO0"); - private static final boolean debugSIO = false; - - private static final int ADDR_SIO0_DATA = 0x1f801040; - private static final int ADDR_SIO0_STATUS = 0x1f801044; - private static final int ADDR_SIO0_MODE = 0x1f801048; - private static final int ADDR_SIO0_CTRL = 0x1f80104a; - private static final int ADDR_SIO0_BAUD = 0x1f80104e; - - private static final int CTL_TX_ENABLE = 0x0001; - private static final int CTL_DTR = 0x0002; - private static final int CTL_RX_ENABLE = 0x0004; - private static final int CTL_ERR_RESET = 0x0010; - private static final int CTL_RESET = 0x0040; - private static final int CTL_DSR_IRQ = 0x1000; - private static final int CTL_SELECT = 0x2000; - - private static final int STAT_TX_READY = 0x0001; // can become set without anything connected - private static final int STAT_RX_READY = 0x0002; // can become set without anything connected - private static final int STAT_TX_EMPTY = 0x0004; - private static final int STAT_PARITY_ERR = 0x0008; - private static final int STAT_RX_OVERRUN = 0x0010; - private static final int STAT_FRAMING_ERR = 0x0020; - private static final int STAT_SYNC_DETEXT = 0x0040; - private static final int STAT_DSR = 0x0080; - private static final int STAT_CTS = 0x0100; - private static final int STAT_IRQ = 0x0200; - - private static SerialDevice[] devices = new SerialDevice[2]; - - public SIO0() { - super("JPSX Serial Controller 0"); - } - - public void init() { - super.init(); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - HardwareComponentConnections.LEFT_PORT_INSTANCE.set(new Port(0)); - HardwareComponentConnections.RIGHT_PORT_INSTANCE.set(new Port(1)); - irq = new IRQ(); - CoreComponentConnections.IRQ_OWNERS.add(irq); - } - - private static class Port implements SerialPort { - private int index; - - public Port(int index) { - this.index = index; - } - - public void connect(SerialDevice device) { - connectDevice(index, device); - } - - public void disconnect() { - disconnectDevice(index); - } - } - - private static void connectDevice(int which, SerialDevice device) { - devices[which] = device; - log.info("Connected " + device.getDescription() + " to port " + which); - } - - private static void disconnectDevice(int which) { - devices[which] = null; - } - - private static class IRQ extends IRQOwnerBase { - public IRQ() { - super(IRQController.IRQ_SIO0, "SIO0"); - } - } - - private static IRQ irq; - - public void registerAddresses(AddressSpaceRegistrar registrar) { - registrar.registerWrite8Callback(ADDR_SIO0_DATA, SIO0.class, "writeData8"); - registrar.registerWrite16Callback(ADDR_SIO0_DATA, SIO0.class, "writeData16"); - registrar.registerWrite32Callback(ADDR_SIO0_DATA, SIO0.class, "writeData32"); - registrar.registerRead8Callback(ADDR_SIO0_DATA, SIO0.class, "readData8"); - registrar.registerRead16Callback(ADDR_SIO0_DATA, SIO0.class, "readData16"); - registrar.registerRead32Callback(ADDR_SIO0_DATA, SIO0.class, "readData32"); - - registrar.registerWrite16Callback(ADDR_SIO0_MODE, SIO0.class, "writeMode16"); - registrar.registerRead16Callback(ADDR_SIO0_MODE, SIO0.class, "readMode16"); - registrar.registerWrite16Callback(ADDR_SIO0_CTRL, SIO0.class, "writeCtrl16"); - registrar.registerRead16Callback(ADDR_SIO0_CTRL, SIO0.class, "readCtrl16"); - registrar.registerWrite16Callback(ADDR_SIO0_BAUD, SIO0.class, "writeBaud16"); - registrar.registerRead16Callback(ADDR_SIO0_BAUD, SIO0.class, "readBaud16"); - registrar.registerRead16Callback(ADDR_SIO0_STATUS, SIO0.class, "readStatus16"); - } - - private static int m_baud; - private static int m_mode; - private static int m_ctrl; - private static int m_status; - - private static boolean communicating = false; - - private static SerialDevice currentDevice; - - public static void writeData8(int address, int value) { - value &= 0xff; - if (debugSIO) System.out.println("SIO DATA WRITE 8 " + MiscUtil.toHex(value, 2)); - if (!communicating) { - if (value == 1) { - currentDevice = 0 == (m_ctrl & CTL_SELECT) ? devices[0] : devices[1]; - if (currentDevice != null) - currentDevice.prepareForTransfer(); - if (debugSIO) { - System.out.println("Select SIO device: " + ((currentDevice == null) ? "not connected" : currentDevice.getDescription())); - } - communicating = true; - } else if (value == 0x81) { - if (log.isDebugEnabled()) { - log.debug("CARD SELECT " + (((m_ctrl & CTL_SELECT) != 0) ? "1" : "0")); - } - } - } else { - if (currentDevice != null) { - if (value == 0x43) { - m_status |= STAT_DSR; - } - currentDevice.send(value); - } - } - m_status |= STAT_RX_READY; - } - - public static void writeData16(int address, int value) { - if (debugSIO) System.out.println("SIO DATA WRITE 16 " + MiscUtil.toHex(value, 16)); - } - - public static void writeData32(int address, int value) { - if (debugSIO) System.out.println("SIO DATA WRITE 32 " + MiscUtil.toHex(value, 32)); - } - - public static int readData8(int address) { - int rc = 0; - - // this isn't probably right, however the bios does... - - // (enable DSR IRQ) - // write data - // sleep - // clear IRQ - // wait for receive ready - // read data - // wait for IRQ - // - // ideally the irq should just be delayed... still this is OK for now - if (currentDevice != null) - rc = currentDevice.receive(); - - if (debugSIO) System.out.println("SIO DATA READ 8 " + MiscUtil.toHex(rc, 2)); - if (0 != (m_ctrl & CTL_DSR_IRQ)) { - if (currentDevice != null) { - if (debugSIO) { - System.out.println("SIO setting DSR IRQ at end of read from connected device!"); - } - m_status |= STAT_IRQ; - irq.raiseIRQ(); - } - } - m_status &= ~STAT_RX_READY; - return rc; - } - - public static int readData16(int address) { - int rc = 0; - if (debugSIO) System.out.println("SIO DATA READ 16 " + MiscUtil.toHex(rc, 4)); - return rc; - } - - public static int readData32(int address) { - int rc = 0; - if (debugSIO) System.out.println("SIO DATA READ 32 " + MiscUtil.toHex(rc, 8)); - return rc; - } - - public static void writeMode16(int address, int value) { - m_mode = value & 0xffff; - if (debugSIO) System.out.println("SIO MODE WRITE 16 " + MiscUtil.toHex(m_mode, 4)); - } - - public static int readMode16(int address) { - if (debugSIO) System.out.println("SIO MODE READ 16 " + MiscUtil.toHex(m_mode, 4)); - return m_mode; - } - - public static void writeCtrl16(int address, int value) { - if (debugSIO) System.out.println("SIO CTRL WRITE 16 " + MiscUtil.toHex(value, 4)); - m_ctrl = value & ~CTL_ERR_RESET; - // todo some things - if (0 != (m_ctrl & CTL_RESET)) { - if (debugSIO) System.out.println("SIO0 RESET"); - m_status |= STAT_TX_READY; - m_status &= ~STAT_DSR; - communicating = false; - } - if (0 != (value & CTL_ERR_RESET)) { - m_status &= ~STAT_IRQ; - } - if (value == 0) { - currentDevice = null; - communicating = false; - } - } - - public static int readCtrl16(int address) { - int rc = m_ctrl; - if (debugSIO) System.out.println("SIO CTRL READ 16 " + MiscUtil.toHex(rc, 4)); - return rc; - } - - public static void writeBaud16(int address, int value) { - m_baud = value; - if (debugSIO) System.out.println("SIO BAUD WRITE 16 " + MiscUtil.toHex(m_baud, 4)); - } - - public static int readBaud16(int address) { - if (debugSIO) System.out.println("SIO BAUD READ 16 " + MiscUtil.toHex(m_baud, 4)); - return m_baud; - } - - public static int readStatus16(int address) { - int rc = m_status; - if (debugSIO) System.out.println("SIO STATUS READ 16 " + MiscUtil.toHex(rc, 4)); - return rc; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/StandardController.java b/src/runtime/java/org/jpsx/runtime/components/hardware/sio/StandardController.java deleted file mode 100644 index d5a4d99..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/sio/StandardController.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.sio; - -public abstract class StandardController extends BasicPad { - protected int padState = 0xffff; - - protected StandardController(String description) { - super(description); - } - - public static final int PADLup = (1 << 12); - public static final int PADLdown = (1 << 14); - public static final int PADLleft = (1 << 15); - public static final int PADLright = (1 << 13); - public static final int PADRup = (1 << 4); - public static final int PADRdown = (1 << 6); - public static final int PADRleft = (1 << 7); - public static final int PADRright = (1 << 5); - - public static final int PADi = (1 << 9); - public static final int PADj = (1 << 10); - public static final int PADk = (1 << 8); - public static final int PADl = (1 << 3); - public static final int PADm = (1 << 1); - public static final int PADn = (1 << 2); - public static final int PADo = (1 << 0); - public static final int PADh = (1 << 11); - - public static final int PADL1 = PADn; - public static final int PADL2 = PADo; - public static final int PADR1 = PADl; - public static final int PADR2 = PADm; - public static final int PADstart = PADh; - public static final int PADselect = PADk; - - public int getType() { - return 0x41; - } - - public void getState(byte[] state) { - state[0] = (byte) ((padState >> 8) & 0xff); - state[1] = (byte) (padState & 0xff); - } - - public void pressed(int mask) { - padState &= ~mask; -// System.out.println("Controller state now: "+MiscUtil.toHex( padState, 4)); - } - - public void released(int mask) { - padState |= mask; -// System.out.println("Controller state now: "+MiscUtil.toHex( padState, 4)); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java b/src/runtime/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java deleted file mode 100644 index 1a653f0..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.spu; - -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.DMAChannelOwnerBase; -import org.jpsx.runtime.util.MiscUtil; - -/** - * Empty SPU that does enough to not prevent games from working at all - */ -public class NullSPU extends SingletonJPSXComponent implements MemoryMapped { - protected static final int ADDR_VOICES = 0x1f801c00; - - protected static final int ADDR_MAIN_VOL_L = 0x1f801d80; - protected static final int ADDR_MAIN_VOL_R = 0x1f801d82; - protected static final int ADDR_REVERB_L = 0x1f801d84; - protected static final int ADDR_REVERB_R = 0x1f801d86; - protected static final int ADDR_CHANNEL_ON0 = 0x1f801d88; - protected static final int ADDR_CHANNEL_ON1 = 0x1f801d8a; - protected static final int ADDR_CHANNEL_OFF0 = 0x1f801d8c; - protected static final int ADDR_CHANNEL_OFF1 = 0x1f801d8e; - protected static final int ADDR_CHANNEL_FM0 = 0x1f801d90; - protected static final int ADDR_CHANNEL_FM1 = 0x1f801d92; - protected static final int ADDR_CHANNEL_NOISE0 = 0x1f801d94; - protected static final int ADDR_CHANNEL_NOISE1 = 0x1f801d96; - protected static final int ADDR_CHANNEL_REVERB0 = 0x1f801d98; - protected static final int ADDR_CHANNEL_REVERB1 = 0x1f801d9a; - protected static final int ADDR_CHANNEL_MUTE0 = 0x1f801d9c; - protected static final int ADDR_CHANNEL_MUTE1 = 0x1f801d9e; - - protected static final int ADDR_TRANSFER_ADDR = 0x1f801da6; - protected static final int ADDR_TRANSFER_DATA = 0x1f801da8; - - protected static final int ADDR_SPU_CTRL = 0x1f801daa; - protected static final int ADDR_SPU_STATUS = 0x1f801dae; - - protected static final int ADDR_CD_VOL_L = 0x1f801db0; - protected static final int ADDR_CD_VOL_R = 0x1f801db2; - - protected static final int VOICES = 24; - - protected static final int VOICE_VOL_L = 0x0; - protected static final int VOICE_VOL_R = 0x2; - protected static final int VOICE_PITCH = 0x4; - protected static final int VOICE_START_OFFSET = 0x6; - protected static final int VOICE_ADS_LEVEL = 0x8; - protected static final int VOICE_SR_RATE = 0xa; - protected static final int VOICE_ADSR_VOL = 0xc; - protected static final int VOICE_REPEAT_OFFSET = 0xe; - - protected static int m_ctrl; - protected static int m_transferAddress; - - public NullSPU() { - super("JPSX Null (no sound) SPU"); - } - - - @Override - public void init() { - super.init(); - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new SPUDMAChannel()); - } - - // figure out RAM - public void registerAddresses(AddressSpaceRegistrar registrar) { - - for (int i = 0; i < VOICES; i++) { - int base = ADDR_VOICES + i * 0x10; - registrar.registerWrite16Callback(base + VOICE_VOL_L, NullSPU.class, "writeVolLeft"); - registrar.registerWrite16Callback(base + VOICE_VOL_R, NullSPU.class, "writeVolRight"); - registrar.registerWrite16Callback(base + VOICE_PITCH, NullSPU.class, "writePitch"); - registrar.registerWrite16Callback(base + VOICE_START_OFFSET, NullSPU.class, "writeStartOffset"); - registrar.registerWrite16Callback(base + VOICE_ADS_LEVEL, NullSPU.class, "writeADSLevel"); - registrar.registerWrite16Callback(base + VOICE_SR_RATE, NullSPU.class, "writeSRRate"); - registrar.registerWrite16Callback(base + VOICE_ADSR_VOL, NullSPU.class, "writeADSRVol"); - registrar.registerWrite16Callback(base + VOICE_REPEAT_OFFSET, NullSPU.class, "writeRepeatOffset"); - } - registrar.registerWrite16Callback(ADDR_MAIN_VOL_L, NullSPU.class, "writeMainVolLeft"); - registrar.registerWrite16Callback(ADDR_MAIN_VOL_R, NullSPU.class, "writeMainVolRight"); - registrar.registerWrite16Callback(ADDR_REVERB_L, NullSPU.class, "writeReverbLeft"); - registrar.registerWrite16Callback(ADDR_REVERB_R, NullSPU.class, "writeReverbRight"); - registrar.registerWrite16Callback(ADDR_CHANNEL_ON0, NullSPU.class, "writeChannelOn0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_ON1, NullSPU.class, "writeChannelOn1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_OFF0, NullSPU.class, "writeChannelOff0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_OFF1, NullSPU.class, "writeChannelOff1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_FM0, NullSPU.class, "writeChannelFM0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_FM1, NullSPU.class, "writeChannelFM1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE0, NullSPU.class, "writeChannelNoise0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE1, NullSPU.class, "writeChannelNoise1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB0, NullSPU.class, "writeChannelReverb0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB1, NullSPU.class, "writeChannelReverb1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE0, NullSPU.class, "writeChannelMute0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE1, NullSPU.class, "writeChannelMute1"); - - registrar.registerWrite16Callback(ADDR_SPU_CTRL, NullSPU.class, "writeSPUCtrl"); - registrar.registerRead16Callback(ADDR_SPU_CTRL, NullSPU.class, "readSPUCtrl"); - - registrar.registerWrite16Callback(ADDR_CD_VOL_L, NullSPU.class, "writeCDVolL"); - registrar.registerWrite16Callback(ADDR_CD_VOL_R, NullSPU.class, "writeCDVolR"); - - registrar.registerRead16Callback(ADDR_SPU_STATUS, NullSPU.class, "readSPUStatus"); - - registrar.registerWrite16Callback(ADDR_TRANSFER_ADDR, NullSPU.class, "writeTransferAddr"); - registrar.registerWrite16Callback(ADDR_TRANSFER_DATA, NullSPU.class, "writeTransferData"); - registrar.registerRead16Callback(ADDR_TRANSFER_ADDR, NullSPU.class, "readTransferAddr"); - } - - public static void writeVolLeft(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeVolRight(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writePitch(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeStartOffset(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeADSLevel(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeSRRate(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeADSRVol(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeRepeatOffset(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - } - - public static void writeMainVolLeft(int address, int val) { - } - - public static void writeMainVolRight(int address, int val) { - } - - public static void writeReverbLeft(int address, int val) { - } - - public static void writeReverbRight(int address, int val) { - } - - public static void writeChannelOn0(int address, int val) { - for (int i = 0; i < 16; i++) { - if (0 != (val & (1 << i))) { - //System.out.println("SPU Voice "+i+" on"); - } - } - } - - public static void writeChannelOn1(int address, int val) { - for (int i = 0; i < 8; i++) { - if (0 != (val & (1 << i))) { - //System.out.println("SPU Voice "+(i+16)+" on"); - } - } - } - - public static void writeChannelOff0(int address, int val) { - for (int i = 0; i < 16; i++) { - if (0 != (val & (1 << i))) { - //System.out.println("SPU Voice "+i+" off"); - } - } - } - - public static void writeChannelOff1(int address, int val) { - for (int i = 0; i < 8; i++) { - if (0 != (val & (1 << i))) { - //System.out.println("SPU Voice "+(i+16)+" off"); - } - } - } - - public static void writeChannelFM0(int address, int val) { - } - - public static void writeChannelFM1(int address, int val) { - } - - public static void writeChannelNoise0(int address, int val) { - } - - public static void writeChannelNoise1(int address, int val) { - } - - public static void writeChannelReverb0(int address, int val) { - } - - public static void writeChannelReverb1(int address, int val) { - } - - public static void writeChannelMute0(int address, int val) { - } - - public static void writeChannelMute1(int address, int val) { - } - - public static void writeSPUCtrl(int address, int val) { - m_ctrl = val; - } - - public static int readSPUCtrl(int address) { - return m_ctrl; - } - - public static void writeCDVolL(int address, int val) { - } - - public static void writeCDVolR(int address, int val) { - } - - public static void writeTransferAddr(int address, int val) { - m_transferAddress = val & 0xffff; - } - - public static int readTransferAddr(int address) { - return m_transferAddress; - } - - public static void writeTransferData(int address, int val) { - } - - static boolean toggle; - - public static int readSPUStatus(int address) { - toggle = !toggle; -// System.out.println("READ SPU STATUS!"); - return toggle ? 0x400 : 0; - } - - protected static class SPUDMAChannel extends DMAChannelOwnerBase { - public final int getDMAChannel() { - return DMAController.DMA_SPU; - } - - public final String getName() { - return "SPU"; - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - signalTransferComplete(); - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - signalTransferComplete(); - } - - public void cancelDMATransfer(int ctrl) { - System.out.println("cancel " + getName() + " DMA transfer"); - } - } - -} - diff --git a/src/runtime/java/org/jpsx/runtime/components/hardware/spu/SPU.java b/src/runtime/java/org/jpsx/runtime/components/hardware/spu/SPU.java deleted file mode 100644 index 6c76830..0000000 --- a/src/runtime/java/org/jpsx/runtime/components/hardware/spu/SPU.java +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.components.hardware.spu; - -import org.apache.log4j.Logger; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.MemoryMapped; -import org.jpsx.api.components.core.dma.DMAController; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.api.components.core.scheduler.ScheduledAction; -import org.jpsx.api.components.core.scheduler.Scheduler; -import org.jpsx.api.components.hardware.cd.CDAudioSink; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.components.core.DMAChannelOwnerBase; -import org.jpsx.runtime.components.hardware.HardwareComponentConnections; -import org.jpsx.runtime.util.MiscUtil; - -import javax.sound.sampled.*; - -// todo volume panning -// bit of a mess! needs some work. -// -// TODO - noise/reverb/fm - -// todo check if getLevel is now supported -public class SPU extends SingletonJPSXComponent implements MemoryMapped, CDAudioSink { - private static final Logger log = Logger.getLogger("SPU"); - - private static final boolean noVoices = false; - private static final boolean debugEnvelope = false; - private static final boolean debugVoiceOnOff = false; - private static final boolean debugDMA = false; - - private static final int ADDR_VOICES = 0x1f801c00; - - private static final int ADDR_MAIN_VOL_L = 0x1f801d80; - private static final int ADDR_MAIN_VOL_R = 0x1f801d82; - private static final int ADDR_REVERB_L = 0x1f801d84; - private static final int ADDR_REVERB_R = 0x1f801d86; - private static final int ADDR_CHANNEL_ON0 = 0x1f801d88; - private static final int ADDR_CHANNEL_ON1 = 0x1f801d8a; - private static final int ADDR_CHANNEL_OFF0 = 0x1f801d8c; - private static final int ADDR_CHANNEL_OFF1 = 0x1f801d8e; - private static final int ADDR_CHANNEL_FM0 = 0x1f801d90; - private static final int ADDR_CHANNEL_FM1 = 0x1f801d92; - private static final int ADDR_CHANNEL_NOISE0 = 0x1f801d94; - private static final int ADDR_CHANNEL_NOISE1 = 0x1f801d96; - private static final int ADDR_CHANNEL_REVERB0 = 0x1f801d98; - private static final int ADDR_CHANNEL_REVERB1 = 0x1f801d9a; - private static final int ADDR_CHANNEL_MUTE0 = 0x1f801d9c; - private static final int ADDR_CHANNEL_MUTE1 = 0x1f801d9e; - - private static final int ADDR_TRANSFER_ADDR = 0x1f801da6; - private static final int ADDR_TRANSFER_DATA = 0x1f801da8; - - private static final int ADDR_SPU_CTRL = 0x1f801daa; - private static final int ADDR_SPU_STATUS = 0x1f801dae; - - private static final int ADDR_CD_VOL_L = 0x1f801db0; - private static final int ADDR_CD_VOL_R = 0x1f801db2; - - private static final int VOICES = 24; - - private static final int VOICE_VOL_L = 0x0; - private static final int VOICE_VOL_R = 0x2; - private static final int VOICE_PITCH = 0x4; - private static final int VOICE_START_OFFSET = 0x6; - private static final int VOICE_ADS_LEVEL = 0x8; - private static final int VOICE_SR_RATE = 0xa; - private static final int VOICE_ADSR_VOL = 0xc; - private static final int VOICE_REPEAT_OFFSET = 0xe; - - - private static final int SAMPLE_RATE = 44100; - private static final int MIN_BUFFER_SAMPLE_RATE = 16000; - private static final int BUFFER_MS = 240; - private static final long BUFFER_REFILL_PERIOD_NS = 30 * Quartz.MSEC; - private static final int BUFFER_MAX_FILL_MS = BUFFER_MS; - private static final int BUFFER_MAX_REFILL_MS = 80; - private static final int BUFFER_SAMPLES = (SAMPLE_RATE * BUFFER_MS) / 1000; - - private static final int CD_BUFFER_SAMPLES = SAMPLE_RATE / 2; - private static final byte[] cdAudioBuffer = new byte[2352 * 4 * 4]; // maximum we're likely to get! - private static SourceDataLine cdline; - private static int cdlineFreq; - private static FloatControl cdPanControl; - private static FloatControl cdGainControl; - private static int cdLeftVol = 0; - private static int cdRightVol = 0; - private static int cdLeftVolExternal = 0x3fff; - private static int cdRightVolExternal = 0x3fff; - - private static int m_ctrl; - private static int m_transferOffset; - private static int m_dataTransferWordOffset; - - private static int[] m_ram = new int[512 * 1024 / 4]; - private static short[] m_decoded = new short[1024 * 1024]; - // 4 short header bytes then 28 short samples... * 32768 - - private static Voice[] voices = new Voice[VOICES]; - - private static boolean cdAudio = true; - private static boolean voiceAudio = true; - public static final String PROPERTY_CD_AUDIO = "cdAudio"; - public static final String PROPERTY_VOICE_AUDIO = "voiceAudio"; - - private static int mainLeftVol; - private static int mainRightVol; - - private static AddressSpace addressSpace; - private static Quartz quartz; - private static Scheduler scheduler; - - public SPU() { - super("JPSX JavaSound SPU"); - } - - public void init() { - super.init(); - cdAudio = getBooleanProperty(PROPERTY_CD_AUDIO, true); - voiceAudio = getBooleanProperty(PROPERTY_VOICE_AUDIO, true); - log.info("Voice Audio " + (voiceAudio ? "ON" : "OFF")); - log.info("CD Audio " + (cdAudio ? "ON" : "OFF")); - if (cdAudio) { - HardwareComponentConnections.CD_AUDIO_SINK.set(this); - } - CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); - CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new SPUDMAChannel()); - } - - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - scheduler = CoreComponentConnections.SCHEDULER.resolve(); - } - - public void registerAddresses(AddressSpaceRegistrar registrar) { - for (int i = 0; i < VOICES; i++) { - voices[i] = new Voice(i); - int base = ADDR_VOICES + i * 0x10; - registrar.registerWrite16Callback(base + VOICE_VOL_L, SPU.class, "writeVolLeft"); - registrar.registerWrite16Callback(base + VOICE_VOL_R, SPU.class, "writeVolRight"); - registrar.registerWrite16Callback(base + VOICE_PITCH, SPU.class, "writePitch"); - registrar.registerWrite16Callback(base + VOICE_START_OFFSET, SPU.class, "writeStartOffset"); - registrar.registerWrite16Callback(base + VOICE_ADS_LEVEL, SPU.class, "writeADSLevel"); - registrar.registerWrite16Callback(base + VOICE_SR_RATE, SPU.class, "writeSRRate"); - registrar.registerRead16Callback(base + VOICE_ADSR_VOL, SPU.class, "readADSRVol"); - registrar.registerWrite16Callback(base + VOICE_REPEAT_OFFSET, SPU.class, "writeRepeatOffset"); - - registrar.registerRead16Callback(base + VOICE_VOL_L, SPU.class, "readVolLeft"); - registrar.registerRead16Callback(base + VOICE_VOL_R, SPU.class, "readVolRight"); - registrar.registerRead16Callback(base + VOICE_PITCH, SPU.class, "readPitch"); - registrar.registerRead16Callback(base + VOICE_START_OFFSET, SPU.class, "readStartOffset"); - registrar.registerRead16Callback(base + VOICE_ADS_LEVEL, SPU.class, "readADSLevel"); - registrar.registerRead16Callback(base + VOICE_SR_RATE, SPU.class, "readSRRate"); - registrar.registerRead16Callback(base + VOICE_REPEAT_OFFSET, SPU.class, "readRepeatOffset"); - } - registrar.registerWrite16Callback(ADDR_MAIN_VOL_L, SPU.class, "writeMainVolLeft"); - registrar.registerWrite16Callback(ADDR_MAIN_VOL_R, SPU.class, "writeMainVolRight"); - registrar.registerWrite16Callback(ADDR_REVERB_L, SPU.class, "writeReverbLeft"); - registrar.registerWrite16Callback(ADDR_REVERB_R, SPU.class, "writeReverbRight"); - registrar.registerWrite16Callback(ADDR_CHANNEL_ON0, SPU.class, "writeChannelOn0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_ON1, SPU.class, "writeChannelOn1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_OFF0, SPU.class, "writeChannelOff0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_OFF1, SPU.class, "writeChannelOff1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_FM0, SPU.class, "writeChannelFM0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_FM1, SPU.class, "writeChannelFM1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE0, SPU.class, "writeChannelNoise0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE1, SPU.class, "writeChannelNoise1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB0, SPU.class, "writeChannelReverb0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB1, SPU.class, "writeChannelReverb1"); - registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE0, SPU.class, "writeChannelMute0"); - registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE1, SPU.class, "writeChannelMute1"); - - registrar.registerWrite16Callback(ADDR_SPU_CTRL, SPU.class, "writeSPUCtrl"); - registrar.registerRead16Callback(ADDR_SPU_CTRL, SPU.class, "readSPUCtrl"); - - registrar.registerWrite16Callback(ADDR_CD_VOL_L, SPU.class, "writeCDVolL"); - registrar.registerWrite16Callback(ADDR_CD_VOL_R, SPU.class, "writeCDVolR"); - - registrar.registerRead16Callback(ADDR_SPU_STATUS, SPU.class, "readSPUStatus"); - - registrar.registerWrite16Callback(ADDR_TRANSFER_ADDR, SPU.class, "writeTransferAddr"); - registrar.registerWrite16Callback(ADDR_TRANSFER_DATA, SPU.class, "writeTransferData"); - registrar.registerRead16Callback(ADDR_TRANSFER_ADDR, SPU.class, "readTransferAddr"); - - } - - public void begin() { - new SPUCallback().start(); - } - - public static void writeVolLeft(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setLeftVol(val); - } - - public static void writeVolRight(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setRightVol(val); - } - - public static void writePitch(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setPitch(val); - } - - public static void writeStartOffset(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setStartOffset(val); - } - - public static void writeADSLevel(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setADSLevel(val); - } - - public static void writeSRRate(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setSRRate(val); - } - - public static int readADSRVol(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getADSRVol(); - } - - public static void writeRepeatOffset(int address, int val) { - int voice = (address - ADDR_VOICES) >> 4; - voices[voice].setRepeatOffset(val); - } - - public static int readVolLeft(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getLeftVol(); - } - - public static int readVolRight(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getRightVol(); - } - - public static int readPitch(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getPitch(); - } - - public static int readStartOffset(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getStartOffset(); - } - - public static int readADSLevel(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getADSLevel(); - } - - public static int readSRRate(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getSRRate(); - } - - public static int readRepeatOffset(int address) { - int voice = (address - ADDR_VOICES) >> 4; - return voices[voice].getRepeatOffset(); - } - - public static void writeMainVolLeft(int address, int val) { - mainLeftVol = decodeVolume(val); - for (int i = 0; i < VOICES; i++) { - voices[i].updateVolume(); - } - } - - public static void writeMainVolRight(int address, int val) { - mainRightVol = decodeVolume(val); - for (int i = 0; i < VOICES; i++) { - voices[i].updateVolume(); - } - } - - public static void writeReverbLeft(int address, int val) { - } - - public static void writeReverbRight(int address, int val) { - } - - public static void writeChannelOn0(int address, int val) { - for (int i = 0; i < 16; i++) { - if ((val & (1 << i)) != 0) { - voices[i].on(); - } - } - } - - public static void writeChannelOn1(int address, int val) { - for (int i = 0; i < 8; i++) { - if ((val & (1 << i)) != 0) { - voices[i + 16].on(); - } - } - } - - public static void writeChannelOff0(int address, int val) { - for (int i = 0; i < 16; i++) { - if ((val & (1 << i)) != 0) { - voices[i].off(); - } - } - } - - public static void writeChannelOff1(int address, int val) { - for (int i = 0; i < 8; i++) { - if ((val & (1 << i)) != 0) { - voices[i + 16].off(); - } - } - } - - public static void writeChannelFM0(int address, int val) { - for (int i = 0; i < 16; i++) { - voices[i].setFM((val & (1 << i)) != 0); - } - } - - public static void writeChannelFM1(int address, int val) { - for (int i = 0; i < 8; i++) { - voices[i + 16].setFM((val & (1 << i)) != 0); - } - } - - public static void writeChannelNoise0(int address, int val) { - for (int i = 0; i < 16; i++) { - voices[i].setNoise((val & (1 << i)) != 0); - } - } - - public static void writeChannelNoise1(int address, int val) { - for (int i = 0; i < 8; i++) { - voices[i + 16].setNoise((val & (1 << i)) != 0); - } - } - - public static void writeChannelReverb0(int address, int val) { - for (int i = 0; i < 16; i++) { - voices[i].setReverb((val & (1 << i)) != 0); - } - } - - public static void writeChannelReverb1(int address, int val) { - for (int i = 0; i < 8; i++) { - voices[i + 16].setReverb((val & (1 << i)) != 0); - } - } - - public static void writeChannelMute0(int address, int val) { - for (int i = 0; i < 16; i++) { - voices[i].setMute((val & (1 << i)) != 0); - } - } - - public static void writeChannelMute1(int address, int val) { - for (int i = 0; i < 8; i++) { - voices[i + 16].setMute((val & (1 << i)) != 0); - } - } - - public static void writeSPUCtrl(int address, int val) { - if (val == m_ctrl) return; - m_ctrl = val; - /* - boolean spuOn = (val & 0x8000) != 0; - boolean spuMuted = (val & 0x4000) == 0; - boolean spuReverb = (val & 0x80) != 0; - boolean spuIrq = (val & 0x40) != 0; - boolean spuCD = (val & 0x1) != 0; - System.out.println("SPU "+(spuOn?"on":"off")+ - (spuMuted?" muted":"")+ - (spuReverb?" RV":"")+ - (spuIrq?" irq":" noirq")+ - (spuCD?" media":" nocd"));*/ - } - - public static int readSPUCtrl(int address) { - return m_ctrl; - } - - public static void writeCDVolL(int address, int val) { - cdLeftVol = decodeVolume(val); - updateCDVolume(); - } - - public static void writeCDVolR(int address, int val) { - cdRightVol = decodeVolume(val); - updateCDVolume(); - } - - public static void writeTransferAddr(int address, int val) { - m_transferOffset = val & 0xffff; - m_dataTransferWordOffset = m_transferOffset << 2; - } - - public static int readTransferAddr(int address) { - return m_transferOffset; - } - - public static void writeTransferData(int address, int val) { - int index = m_dataTransferWordOffset >> 1; - m_decoded[(m_dataTransferWordOffset << 2) & 0xfffffff0] = 0; - // todo mark area as dirty. - if (0 == (m_dataTransferWordOffset & 1)) { - m_ram[index] = (m_ram[index] & 0xffff0000) | (val & 0xffff); - } else { - m_ram[index] = (m_ram[index] & 0xffff) | (val << 16); - } - m_dataTransferWordOffset++; - } - - static boolean toggle; - - public static int readSPUStatus(int address) { - toggle = !toggle; -// System.out.println("READ SPU STATUS!"); - return toggle ? 0x400 : 0; - } - - private static class SPUDMAChannel extends DMAChannelOwnerBase { - private static AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); - - public final int getDMAChannel() { - return DMAController.DMA_SPU; - } - - public final String getName() { - return "SPU"; - } - - public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { - if (debugDMA) - System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - int destIndex = m_transferOffset << 1; - int size = blocks * blockSize; - addressSpace.resolve(base, size * 4, true, rr); - int srcIndex = rr.offset; - if ((destIndex + size) > 0x20000) { - if (debugDMA) - System.out.println("transfer to SPU overrun buffer by " + ((destIndex + size) - 0x20000) + " dwords"); - size = 0x20000 - destIndex; - } - int[] src = rr.mem; - for (size = size - 1; size >= 0; size--) { - // destIndex = 0->0x020000; - // decoded = 0->0x100000; - m_decoded[(destIndex << 3) & 0xfffffff0] = 0; - m_ram[destIndex++] = src[srcIndex++]; - } - signalTransferComplete(); - } - - public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { - if (debugDMA) - System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); - int srcIndex = m_transferOffset << 1; - int size = blocks * blockSize; - addressSpace.resolve(base, size * 4, false, rr); - int destIndex = rr.offset; - int[] dest = rr.mem; - for (size = size - 1; size >= 0; size--) { - dest[destIndex++] = m_ram[srcIndex++]; - } - signalTransferComplete(); - } - - public void cancelDMATransfer(int ctrl) { - if (debugDMA) System.out.println("cancel " + getName() + " DMA transfer"); - } - } - - public static class SPUCallback implements ScheduledAction { - private long next; - private static byte[] buffer = new byte[BUFFER_SAMPLES * 2]; - - public void start() { - next = quartz.nanoTime() + (BUFFER_REFILL_PERIOD_NS << 4); - scheduler.schedule(next, this); - } - - public long run(long currentTime) { - //System.out.println("invoke "+time); - for (int i = 0; i < VOICES; i++) { - voices[i].fill(buffer, false); - } - next = quartz.nanoTime() + BUFFER_REFILL_PERIOD_NS; - return next; - } - } - - // for debugging - private static byte[] debugbuffer = new byte[BUFFER_SAMPLES * 2]; - - public static void fill() { - for (int i = 0; i < VOICES; i++) { - voices[i].fill(debugbuffer, BUFFER_SAMPLES * 2); - } - } - - private static class Voice { - private int index; - - private static final int OFF = 0; - private static final int ATTACK = 1; - private static final int DECAY = 2; - private static final int SUSTAIN = 3; - private static final int RELEASE = 4; - - private int state; - private boolean mute; - private boolean fm; - private boolean noise; - private boolean reverb; - private int leftVol; - private int rightVol; - private int rateA, rateD, rateS, rateR; - private int levelS; - private boolean expA, expS, expR; - private boolean decS; - private int pitch; - - private int vol; - private int sampleDelta; - private int startOffset; - private int blockOffset; - private int repeatOffset; - private int sample; - private int currentBlockSample; - private boolean locked; - private int envelope; - private int currentMS; - private int currentSubMS; - private int adslevel; - private int srrate; - - private static final int ENVELOPE_HISTORY_SIZE = 256; - private int[] envelopeHistory = new int[ENVELOPE_HISTORY_SIZE]; - private long onTime; - private long offTime; - - private static byte[] buffer = new byte[BUFFER_SAMPLES * 2]; - - private static DataLine.Info desiredLine = new DataLine.Info(SourceDataLine.class, - new AudioFormat[]{new AudioFormat(SAMPLE_RATE, 16, 1, true, false)}, -// Guess this was ignored by the software mixer - doesn't really make much sense -// 0, BUFFER_SAMPLES * 2); - BUFFER_SAMPLES * 2, AudioSystem.NOT_SPECIFIED); - private SourceDataLine line; - private FloatControl panControl; - private FloatControl rateControl; - - private boolean slow; - private int sampleRate; - private int BUFFER_MAX_REFILL_SAMPLES; - private int BUFFER_MAX_FILL_SAMPLES; - - private static int[] adsrRates = initADSR(); - - private static int[] initADSR() { - int[] rates = new int[160]; - int r, rs, rd; - int i; - - r = 3; - rs = 1; - rd = 0; - - for (i = 32; i < 160; i++) { - if (r < 0x3FFFFFFF) { - r += rs; - rd++; - if (rd == 5) { - rd = 1; - rs *= 2; - } - } - if (r > 0x3FFFFFFF) r = 0x3FFFFFFF; - rates[i] = r; - } - return rates; - } - - public String toString() { - return "V" + index + " L" + MiscUtil.toHex(leftVol, 4) + " R" + MiscUtil.toHex(rightVol, 4) + " " + - "pitch " + MiscUtil.toHex(pitch, 4) + " " + - "st " + MiscUtil.toHex(startOffset, 4) + " " + - "rpt " + MiscUtil.toHex(repeatOffset, 4) + - " ar " + rateA + - " dr " + rateD + - " sl " + levelS + - " sr " + rateS + - " rr " + rateR + - (mute ? " muted" : "") + - (fm ? " FM" : "") + - (reverb ? " RV" : ""); - } - - public Voice(int index) { - if (!voiceAudio) return; - this.index = index; - try { - line = (SourceDataLine) AudioSystem.getLine(desiredLine); - line.open(); - if (line.isControlSupported(FloatControl.Type.SAMPLE_RATE)) { - rateControl = (FloatControl) line.getControl(FloatControl.Type.SAMPLE_RATE); - } else { - log.warn("Rate control is NOT supported, hacking around it for now - might sound a bit weird until fixed properly"); - } - if (line.isControlSupported(FloatControl.Type.PAN)) { - panControl = (FloatControl) line.getControl(FloatControl.Type.PAN); - } else { - // todo to fix this we need to make the voice stereo instead (identical channels) - log.warn("Pan control is NOT supported, voices will not be stereo positioned"); - } - } catch (Throwable t) { - throw new IllegalStateException("can't get line for voice " + index, t); - } - state = OFF; - } - - public void on() { - if (!voiceAudio) return; - //if (index!=0) return; - if (debugVoiceOnOff) System.out.println("voice on " + this); - if (isActive()) { -// System.out.println(this+" VOICE ON WHEN ACTIVE!"); - } - state = OFF; - line.flush(); - line.stop(); - //line.drain(); - - repeatOffset = 0; - sample = 0; - currentBlockSample = -28; - blockOffset = startOffset - 2; - currentMS = 0; - currentSubMS = 1000; - - slow = pitch < 0x1000; - if (rateControl == null) { - // temp hack to get around loss of RateControl is JDK7 - // surprised this works, but as far as I recall, I must - // have done the frequency myself for anything higher than - // the SAMPLE_RATE, so forcing slow = false makes - // us do it in software, which might sound bad without filtering - // but is good enough for now - slow = false; - } - sampleRate = slow ? ((SAMPLE_RATE * pitch) >> 12) : SAMPLE_RATE; - int min = sampleRate < MIN_BUFFER_SAMPLE_RATE ? MIN_BUFFER_SAMPLE_RATE : sampleRate; - BUFFER_MAX_REFILL_SAMPLES = (min * BUFFER_MAX_REFILL_MS) / 1000; - BUFFER_MAX_FILL_SAMPLES = (min * BUFFER_MAX_FILL_MS) / 1000; - //System.out.println("slow="+slow+" sample rate="+sampleRate+" max samples="+BUFFER_MAX_REFILL_SAMPLES); - if (rateControl != null) { - rateControl.setValue(sampleRate); - } - if (!noVoices) { - line.start(); - } - - envelope = 0; - //System.out.println("onTime "+onTime); - onTime = quartz.nanoTime(); - offTime = Long.MAX_VALUE; - state = ATTACK; - if (debugEnvelope) System.out.println("voice " + index + " to ATTACK"); - fill(buffer, true); - } - - public void off() { - if (!voiceAudio) return; - if (debugVoiceOnOff) System.out.println("voice off " + this); - if (state != OFF) { - if (debugEnvelope) System.out.println("voice " + index + " to RELEASE"); - state = RELEASE; - } - } - - public void setMute(boolean nMute) { - if (mute != nMute) { - mute = nMute; - //System.out.println( this + " mute changed" ); - } - } - - public boolean isActive() { - return state != OFF; - } - - public void setReverb(boolean nReverb) { - reverb = nReverb; - } - - public void setNoise(boolean nNoise) { - noise = nNoise; - if (noise) throw new IllegalStateException(this + " NOISE!"); - } - - public void setFM(boolean nFM) { - fm = nFM; - if (fm) throw new IllegalStateException(this + " FM!"); - } - - public void setLeftVol(int nVol) { - leftVol = decodeVolume(nVol); - updateVolume(); - } - - public void setRightVol(int nVol) { - rightVol = decodeVolume(nVol); - updateVolume(); - } - - public int getLeftVol() { - return leftVol; - } - - public int getRightVol() { - return leftVol; - } - - public void updateVolume() { - if (!voiceAudio) return; - // set volume to max of left/right, then set pan - // assuming that: - // lscale = (pan<0)?1:(1-pan); - // rscale = (pan<0)?(1+pan):1; - - int l = (leftVol * mainLeftVol) >> 15; - int r = (rightVol * mainRightVol) >> 15; - if (panControl == null) { - // todo fix this, for now without pan control, just average l/r volume - vol = (l + r) / 2; - } else { - if (l == r) { - vol = l; - panControl.setValue(0.0f); - } else if (l > r) { - vol = l; - panControl.setValue(((float) r) / l - 1.0f); - } else { - vol = r; - panControl.setValue(1.0f - ((float) l) / r); - } - } - } - - public void setPitch(int nPitch) { - pitch = nPitch; - sampleDelta = pitch >> 1; - if (state != OFF) { - //System.out.println("XXX SET PITCH WHILE ON: "+this+" pitch is now "+nPitch); - } - } - - public int getPitch() { - return pitch; - } - - public void setStartOffset(int nOffset) { - startOffset = nOffset; - } - - public int getStartOffset() { - return startOffset; - } - - public void setADSLevel(int val) { - adslevel = val; - expA = (val & 0x8000) != 0; - rateA = (val >> 8) & 0x7f; - rateA ^= 0x7f; - rateD = (val >> 4) & 0xf; - // todo - is this really correct? - rateD ^= 0x1f; - levelS = val & 0xf; - } - - public int getADSLevel() { - return adslevel; - } - - public void setSRRate(int val) { - srrate = val; - expS = (val & 0x8000) != 0; - decS = (val & 0x4000) != 0; - rateS = (val >> 6) & 0x7f; - rateS ^= 0x7f; - expR = (val & 0x20) != 0; - rateR = val & 0x1f; - rateR ^= 0x1f; - } - - public int getSRRate() { - return srrate; - } - - public int getADSRVol() { - if (!voiceAudio) return 0; - long time = quartz.nanoTime(); - if (state == OFF && time >= offTime) { - return 0; - } - int ms = (int) ((time - onTime) / Quartz.MSEC); - if (ms > currentMS) - return 0; - int delta = (currentMS - ms) >> 2; - // if we're too far behind, then pick something back towards the beginning of the buffer - // - // note, we can get further behind because our ticks are potentially slower than real time - // due to gc/compilation etc. - if (delta >= ENVELOPE_HISTORY_SIZE) - ms = currentMS - ((ENVELOPE_HISTORY_SIZE - 4) << 2); -// System.out.println( this+" "+(envelopeHistory[(ms>>2)%ENVELOPE_HISTORY_SIZE]>>16)); - return envelopeHistory[(ms >> 2) % ENVELOPE_HISTORY_SIZE] >> 16; - } - - public void setRepeatOffset(int nRepeat) { - repeatOffset = nRepeat; - } - - public int getRepeatOffset() { - return repeatOffset; - } - - public synchronized boolean lock() { - if (locked) - return false; - locked = true; - return true; - } - - public synchronized void unlock() { - locked = false; - } - - private static final int[] expIndex = new int[]{ - 0, 4, 6, 8, 9, 10, 11, 12 - }; - - private final void updateADSR() { - //assert(0==(envelope&0x80000000)); - - switch (state) { - case ATTACK: - if (!expA || envelope < 0x60000000) { - envelope += adsrRates[rateA + 32 - 0x10]; - } else { - envelope += adsrRates[rateA + 32 - 0x18]; - } - if (envelope < 0) { - envelope = 0x7fffffff; - if (debugEnvelope) System.out.println("voice " + index + " to DECAY"); - state = DECAY; - } - return; - case DECAY: - envelope -= adsrRates[4 * rateD + 32 - 0x18 + expIndex[envelope >> 28]]; - if (envelope > 0) { - if (levelS >= (envelope >> 27)) { - state = SUSTAIN; - if (debugEnvelope) System.out.println("voice " + index + " to SUSTAIN"); - } - } else { - envelope = 0; - state = SUSTAIN; - if (debugEnvelope) System.out.println("voice " + index + " to SUSTAIN"); - } - return; - case SUSTAIN: - if (decS) { - // decrementing - if (expS) { - envelope -= adsrRates[rateS + 32 - 0x1b + expIndex[envelope >> 28]]; - } else { - envelope -= adsrRates[rateS + 32 - 0x0f]; - } - if (envelope < 0) { - envelope = 0; - } - } else { - // incrementing - if (!expS || envelope < 0x60000000) { - envelope += adsrRates[rateS + 32 - 0x10]; - } else { - envelope += adsrRates[rateS + 32 - 0x18]; - } - if (envelope < 0) { - envelope = 0x7fffffff; - } - } - return; - case RELEASE: - if (expR) { - envelope -= adsrRates[4 * rateR + 32 - 0x18 + expIndex[envelope >> 28]]; - } else { - envelope -= adsrRates[4 * rateR + 32 - 0x0c]; - } - if (envelope < 0) { - envelope = 0; - } - return; - } - } - - public void fill(byte[] buffer, boolean unlimited) { - int max = unlimited ? BUFFER_MAX_FILL_SAMPLES : BUFFER_MAX_REFILL_SAMPLES; - fill(buffer, max); - } - - public void fill(byte[] buffer, int max) { - if (noVoices) { - return; - } - if (lock()) { - if (state == OFF || sampleDelta == 0) { - //if (line.isActive() && line.available()==line.getBufferSize()) { - // System.out.println(this+" line is drained and off, stopping!"); - // line.close(); - //} - unlock(); - return; - } - //System.out.println( Thread.currentThread().getName()+" thread fills"); - int sampleCount = line.available() >> 1; - if (sampleCount == 0) { - unlock(); - return; - } - if (sampleCount > max) { - sampleCount = max; - } - int bufferBytes = 0; - if (slow) { - // todo removed this because it keeps failing! - //assert sampleDelta <= 0x800; - //System.out.println( this + " filling "+sampleCount+" slow samples"); - for (int count = 0; count < sampleCount; count++) { - int s = sample >> 11; - int sold = s; - do { - updateADSR(); - sample += sampleDelta; - s = sample >> 11; - } while (s == sold); - //updateADSR(); - int decodeIndex = blockOffset << 4; - if (s >= currentBlockSample + 28) { - currentBlockSample += 28; - blockOffset += 2; - decodeIndex += 32; - - int srcIndex = blockOffset << 1; - int code = (m_ram[srcIndex] >> 8) & 0xff; - if (0 != (code & 1)) { - state = OFF; - if (debugEnvelope) System.out.println("voice " + index + " to OFF (sample ended)"); - offTime = onTime + currentMS * Quartz.MSEC; - //System.out.println("offTime "+offTime+" ("+((offTime-onTime)>>4)+")"); - break; - } - if (m_decoded[decodeIndex] == 0) { - //System.out.g(this+" decode block at "+MiscUtil.toHex( nextBlockOffset, 4)+" code "+code); - // System.out.println(" decompress"); - decompressBlock(blockOffset); - } - // note maximum sample step is 16 samples, so we can't skip a block - } - int val = m_decoded[decodeIndex + 4 + s - currentBlockSample]; - val = (val * vol) >> 14; - val = (val * (envelope >> 16)) >> 15; - //if (index==0) System.out.println(index+" "+state+" "+MiscUtil.toHex( envelope, 8)+" "+MiscUtil.toHex( val, 4)); - buffer[bufferBytes++] = (byte) val; - buffer[bufferBytes++] = (byte) (val >> 8); - currentSubMS -= 1000; - if (currentSubMS <= 0) { - envelopeHistory[(currentMS >> 2) % ENVELOPE_HISTORY_SIZE] = envelope; - currentMS += 4; - currentSubMS += sampleRate * 4; - //if (index==0) System.out.println(currentMS+" "+MiscUtil.toHex(envelope>>16,4)); - } - } - } else { - //System.out.println( this + " filling "+sampleCount+" fast samples"); - for (int count = 0; count < sampleCount; count++) { - updateADSR(); - int s = (sample >> 11); - int decodeIndex = blockOffset << 4; - if (s >= currentBlockSample + 28) { - currentBlockSample += 28; - blockOffset += 2; - decodeIndex += 32; - - int srcIndex = blockOffset << 1; - int code = (m_ram[srcIndex] >> 8) & 0xff; - if (0 != (code & 1)) { - state = OFF; - offTime = onTime + (currentMS << 4); - if (debugEnvelope) System.out.println("voice " + index + " to OFF (sample ended)"); - //System.out.println("offTime "+offTime+" ("+((offTime-onTime)>>4)+")"); - break; - } - if (m_decoded[decodeIndex] == 0) { - //System.out.println(this+" decode block at "+MiscUtil.toHex( nextBlockOffset, 4)+" code "+code); - // System.out.println(" decompress"); - decompressBlock(blockOffset); - } - // note maximum sample step is 16 samples, so we can't skip a block - } - int val = m_decoded[decodeIndex + 4 + s - currentBlockSample]; - val = (val * vol) >> 14; - val = (val * (envelope >> 16)) >> 15; - //if (index==0) System.out.println(index+" "+state+" "+MiscUtil.toHex( envelope, 8)+" "+MiscUtil.toHex( val, 4)); - buffer[bufferBytes++] = (byte) val; - buffer[bufferBytes++] = (byte) (val >> 8); - sample += sampleDelta; - currentSubMS -= 1000; - if (currentSubMS <= 0) { - envelopeHistory[(currentMS >> 2) % ENVELOPE_HISTORY_SIZE] = envelope; - currentMS += 4; - currentSubMS += SAMPLE_RATE * 4; - //System.out.println(currentMS+" "+MiscUtil.toHex(envelope>>16,4)); - } - } - } - line.write(buffer, 0, bufferBytes); - unlock(); - } - } - } - - private static final int[] predict1 = new int[]{ - 0, 60, 115, 98, 122 - }; - - private static final int[] predict2 = new int[]{ - 0, 0, -52, -55, -60 - }; - - // blockOffset is in multiples of 8 bytes in src ram. - private static void decompressBlock(int blockOffset) { - int decodeIndex = blockOffset << 4; - int srcIndex = blockOffset << 1; - - int s_1, s_2; - if (false) { - if (decodeIndex < 32) { - s_1 = 0; - s_2 = 0; - } else { - s_1 = m_decoded[decodeIndex - 31]; - s_2 = m_decoded[decodeIndex - 30]; - } - - int dword = m_ram[srcIndex]; - int predictIndex = (dword >> 4) & 0xf; - int shift = dword & 0xf; - - for (int i = 4; i < 32; i++) { - int i7 = i & 7; - int s = (dword >> (i7 << 2)) & 0xf; - //s <<= 12; - //if ((s&0x8000)!=0) s|= 0xffff0000; - //s >>= shift; - //s = (((s<<6) + s_1*predict1[predictIndex] + s_2*predict2[predictIndex])+32)>>6; - - // note this isn't quite the same as above; we include sub bits if shift >12 - s = ((((s << 28) >> (shift + 10)) + s_1 * predict1[predictIndex] + s_2 * predict2[predictIndex]) + 32) >> 6; - - - m_decoded[decodeIndex + i] = (short) s; - s_2 = s_1; - s_1 = s; - if (7 == (i7)) { - dword = m_ram[srcIndex + ((i + 1) >> 3)]; - } - //System.out.print(MiscUtil.toHex(s,4)+" "); - } - m_decoded[decodeIndex] = 1; - m_decoded[decodeIndex + 1] = (short) s_1; - m_decoded[decodeIndex + 2] = (short) s_2; - } else { - if (decodeIndex < 32) { - s_1 = 0; - s_2 = 0; - } else { - s_1 = ((int) m_decoded[decodeIndex - 31] & 0xffff) + (((int) m_decoded[decodeIndex - 29] & 0xff) << 16); - s_2 = ((int) m_decoded[decodeIndex - 30] & 0xffff) + (((int) m_decoded[decodeIndex - 29] & 0xff00) << 8); - s_1 = (s_1 << 8) >> 8; - s_2 = (s_2 << 8) >> 8; - } - - int dword = m_ram[srcIndex]; - int predictIndex = (dword >> 4) & 0xf; - int shift = (dword & 0xf) + 12; - - int ik0 = -predict1[predictIndex]; - int ik1 = -predict2[predictIndex]; - for (int i = 4; i < 32; i++) { - int i7 = i & 7; - int x0 = (dword >> (i7 << 2)) & 0xf; - x0 = (x0 << 28) >> shift; - x0 -= (ik0 * s_1 + ik1 * s_2) >> 6; - m_decoded[decodeIndex + i] = (short) (x0 >> 4); - s_2 = s_1; - s_1 = x0; - if (7 == (i7)) { - dword = m_ram[srcIndex + ((i + 1) >> 3)]; - } - //System.out.print(MiscUtil.toHex(s,4)+" "); - } - m_decoded[decodeIndex] = 1; - m_decoded[decodeIndex + 1] = (short) s_1; - m_decoded[decodeIndex + 2] = (short) s_2; - m_decoded[decodeIndex + 3] = (short) (((s_1 >> 16) & 0xff) | ((s_2 >> 8) & 0xff00)); - } - //System.out.println(); - } - - public int getCDAudioLatency() { - return 0; - } - - private static boolean reBuffer = false; - - public void newCDAudio() { - sectorsSinceReset = 0; - base = System.nanoTime(); - if (cdline != null) { - cdline.flush(); - cdline.stop(); - } - } - - // we can get up to 8 sectors at a time; make slightly bigger for safety - private static final int SECTORS_TO_BUFFER = 10; - private static final int SECTORS_TO_DELAY = 4; - int sectorsSinceReset; - int bytesPerSector; - - public synchronized void setCDAudioRate(int hz) { - if (cdAudio) { - if (hz != cdlineFreq) { - newCDAudio(); - cdline = null; - bytesPerSector = (hz / 75) * 4; - int bytesToBuffer = bytesPerSector * SECTORS_TO_BUFFER; - - DataLine.Info desiredCdLine = new DataLine.Info(SourceDataLine.class, - new AudioFormat[]{new AudioFormat(hz, 16, 2, true, false)}, - bytesToBuffer * 4, bytesToBuffer * 4); - try { - cdline = (SourceDataLine) AudioSystem.getLine(desiredCdLine); - cdline.open(); - //System.out.println(cdline); - reBuffer = true; - cdPanControl = (FloatControl) cdline.getControl(FloatControl.Type.PAN); - cdGainControl = (FloatControl) cdline.getControl(FloatControl.Type.MASTER_GAIN); - updateCDVolume(); - } catch (Throwable t) { - throw new IllegalStateException("can't get line for media audio", t); - } - cdlineFreq = hz; - } - } - } - - static long base; - - public boolean cdAudioData(byte[] data, int offset, int length) { - long now = System.nanoTime(); - double delta = (now - base) / 1000000.0; - if (log.isDebugEnabled()) { - log.debug("AUDIO AT " + delta + " buffer space " + cdline.available() + " length " + length + " in sectors = " + (length / (1.0 * bytesPerSector))); - } - assert (bytesPerSector > 0); - while (length > 0) { - // write one sectors worth at a time - int toWrite = length > bytesPerSector ? bytesPerSector : length; - cdline.write(data, offset, toWrite); - offset += toWrite; - length -= toWrite; - sectorsSinceReset++; - if (sectorsSinceReset == SECTORS_TO_DELAY) { - cdline.start(); - } - } - return sectorsSinceReset >= SECTORS_TO_DELAY; - } - - public void setExternalCDAudioVolumeLeft(int vol) { - vol /= 2; - if (vol > 0x3fff) vol = 0x3fff; - cdLeftVolExternal = vol; - updateCDVolume(); - } - - public void setExternalCDAudioVolumeRight(int vol) { - vol /= 2; - if (vol > 0x3fff) vol = 0x3fff; - cdRightVolExternal = vol; - updateCDVolume(); - } - - private static int volMul(int v1, int v2) { - if (v1 == 0x3fff) v1++; - if (v2 == 0x3fff) v2++; - return (v1 * v2) >> 14; - } - - private static synchronized void updateCDVolume() { - if (cdline != null) { - int l = volMul(mainLeftVol, volMul(cdLeftVol, cdLeftVolExternal)); - int r = volMul(mainRightVol, volMul(cdRightVol, cdRightVolExternal)); - if (log.isDebugEnabled()) { - log.debug("CD Volume L=" + MiscUtil.toHex(mainLeftVol, 4) + "," + MiscUtil.toHex(cdLeftVol, 4) + "," + MiscUtil.toHex(cdLeftVolExternal, 4) + " R=" + MiscUtil.toHex(r, 4)); - } - int vol; - if (l == r) { - vol = l; - cdPanControl.setValue(0.0f); - } else if (l > r) { - vol = l; - cdPanControl.setValue(((float) r) / l - 1.0f); - } else { - vol = r; - cdPanControl.setValue(1.0f - ((float) l) / r); - } - // todo fix this; it is just made up - float db = -10 + (vol - 16384) / 512f; - if (db < -80) db = -80; - cdGainControl.setValue(db); - } - } - - public boolean isCDAudible() { - return cdline != null; - } - - private static int decodeVolume(int vol) { - int rc; - if (0 == (vol & 0x8000)) { - // non sweep - rc = vol & 0x3fff; - } else { - // sweep not supported, just go straight to min/max - if ((vol & 0x2000) == 0) { - // increase - rc = 0x3fff; - } else { - // decrease - rc = 0; - } - } - // phase not yet supported - return rc; - } -} - diff --git a/src/runtime/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java b/src/runtime/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java deleted file mode 100644 index 6f8f083..0000000 --- a/src/runtime/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.debugcomponents.core; - -import org.apache.bcel.generic.ClassGen; -import org.apache.log4j.Logger; -import org.jpsx.api.CPUListener; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; -import org.jpsx.api.components.core.addressspace.Pollable; -import org.jpsx.bootstrap.classloader.ClassModifier; -import org.jpsx.bootstrap.util.CollectionsFactory; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.SingletonJPSXComponent; -import org.jpsx.runtime.components.core.AddressSpaceImpl; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.util.ClassUtil; - -import java.util.List; - -/** - * A debug implementation of address space that gives you the ability to set RAM breakpoints and other goodies. - */ -public final class DebugAddressSpaceImpl extends SingletonJPSXComponent implements ClassModifier, AddressSpace, AddressSpaceRegistrar, CPUListener { - private static final Logger logger = Logger.getLogger(DebugAddressSpaceImpl.class); - private static final AddressSpaceImpl realAddressSpace = new AddressSpaceImpl(); - private static final String HARDWARE_CLASS = ClassUtil.innerClassName(DebugAddressSpaceImpl.class, "Hardware"); - private static List ramBreakpoints = CollectionsFactory.newArrayList(); - private static boolean cpuActive = true; - private static boolean ramBreakpointsActive = false; - public static int[] ramD = realAddressSpace.ramD; - public static final int[] scratch = realAddressSpace.scratch; - public static final int[] bios = realAddressSpace.bios; - - public DebugAddressSpaceImpl() { - super("Debug JPSX Address Space"); - } - - private static void processAddressWrite(int address) { - if (ramBreakpointsActive && ramBreakpoints.contains(address)) { - logger.info("RAM address 0x" + Integer.toHexString(address) + " about to be written; pausing the CPU..."); - // Pause the CPU. - RuntimeConnections.CPU_CONTROL.resolve().pause(); - } - } - - public static void activateRAMBreakpoint(int address) { - ramBreakpoints.add(address); - logger.info("Adding breakpoint at: 0x" + Integer.toHexString(address)); - ramBreakpointsActive = true && cpuActive; - } - - public static void deactivateRAMBreakpoint(int address) { - int index = ramBreakpoints.indexOf(address); - if (index >= 0) { - ramBreakpoints.remove(index); - logger.info("Breakpoint at 0x" + Integer.toHexString(address) + " has been removed."); - ramBreakpointsActive = ramBreakpoints.size() > 0 && cpuActive; - } else { - logger.info("Breakpoint at 0x" + Integer.toHexString(address) + " does not exist."); - } - } - - public static int[] getActiveRAMBreakpoints() { - final int numBreakpoints = ramBreakpoints.size(); - final int[] breakpoints = new int[numBreakpoints]; - for (int i = 0; i < numBreakpoints; i++) { - breakpoints[i] = ramBreakpoints.get(i); - } - return breakpoints; - } - - @Override - public void resolveConnections() { - super.resolveConnections(); - realAddressSpace.resolveConnections(); - } - - @Override - public void init() { - super.init(); - realAddressSpace.init(); - CoreComponentConnections.ADDRESS_SPACE.set(this); - CoreComponentConnections.CPU_LISTENERS.add(this); - } - - @Override - public int internalRead32(int address) { - return realAddressSpace.internalRead32(address); - } - - public static int _internalRead32(int address) { - return AddressSpaceImpl._internalRead32(address); - } - - @Override - public void internalWrite32(int address, int value) { - realAddressSpace.internalWrite32(address, value); - } - - public static void _internalWrite32(int address, int value) { - AddressSpaceImpl._internalWrite32(address, value); - } - - @Override - public int read8(int address) { - return realAddressSpace.read8(address); - } - - public static int _read8(int address) { - return AddressSpaceImpl._read8(address); - } - - @Override - public int read16(int address) { - return realAddressSpace.read16(address); - } - - public static int _read16(int address) { - return AddressSpaceImpl._read16(address); - } - - @Override - public int read32(int address) { - return realAddressSpace.read32(address); - } - - public static int _read32(int address) { - return AddressSpaceImpl._read32(address); - } - - @Override - public void write8(int address, int value) { - realAddressSpace.write8(address, value); - } - - public static void _write8(int address, int value) { - AddressSpaceImpl._write8(address, value); - } - - @Override - public void write16(int address, int value) { - realAddressSpace.write16(address, value); - } - - public static void _write16(int address, int value) { - AddressSpaceImpl._write16(address, value); - } - - @Override - public void write32(int address, int value) { - realAddressSpace.write32(address, value); - } - - public static void _write32(int address, int value) { - AddressSpaceImpl._write32(address, value); - } - - @Override - public void enableMemoryWrite(boolean enable) { - realAddressSpace.enableMemoryWrite(enable); - // RAM might now be a dummy array. - ramD = realAddressSpace.ramD; - } - - @Override - public byte getTag(int pc) { - return realAddressSpace.getTag(pc); - } - - @Override - public void orTag(int pc, byte val) { - realAddressSpace.orTag(pc, val); - } - - @Override - public void resolve(int address, ResolveResult result) { - realAddressSpace.resolve(address, result); - } - - @Override - public void resolve(int address, int size, boolean write, ResolveResult result) { - realAddressSpace.resolve(address, size, write, result); - } - - @Override - public int[] getMainRAM() { - // TODO: Support RAM breakpoints for DMA! - return realAddressSpace.getMainRAM(); - } - - @Override - public void tagAddressAccessWrite(int pc, int address) { - processAddressWrite(address); - realAddressSpace.tagAddressAccessWrite(pc, address); - } - - public static void _tagAddressAccessWrite(int pc, int address) { - processAddressWrite(address); - AddressSpaceImpl._tagAddressAccessWrite(pc, address); - } - - @Override - public void tagAddressAccessRead8(int pc, int address) { - realAddressSpace.tagAddressAccessRead8(pc, address); - } - - public static void _tagAddressAccessRead8(int pc, int address) { - AddressSpaceImpl._tagAddressAccessRead8(pc, address); - } - - @Override - public void tagAddressAccessRead16(int pc, int address) { - realAddressSpace.tagAddressAccessRead16(pc, address); - } - - public static void _tagAddressAccessRead16(int pc, int address) { - AddressSpaceImpl._tagAddressAccessRead16(pc, address); - } - - @Override - public void tagAddressAccessRead32(int pc, int address) { - realAddressSpace.tagAddressAccessRead32(pc, address); - } - - public static void _tagAddressAccessRead32(int pc, int address) { - AddressSpaceImpl._tagAddressAccessRead32(pc, address); - } - - @Override - public void tagClearPollCounters() { - realAddressSpace.tagClearPollCounters(); - } - - public static void _tagClearPollCounters() { - AddressSpaceImpl._tagClearPollCounters(); - } - - @Override - public String getMainStaticInterfaceClassName() { - return DebugAddressSpaceImpl.class.getName(); - } - - @Override - public String getHardwareStaticInterfaceClassName() { - return HARDWARE_CLASS; - } - - @Override - public void registerRead8Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerRead8Callback(address, clazz, methodName); - } - - @Override - public void registerRead16Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerRead16Callback(address, clazz, methodName); - } - - @Override - public void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead) { - realAddressSpace.registerRead16Callback(address, clazz, methodName, allowSubRead); - } - - @Override - public void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead) { - realAddressSpace.registerRead32Callback(address, clazz, methodName, allowSubRead); - } - - @Override - public void registerRead32Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerRead32Callback(address, clazz, methodName); - } - - @Override - public void registerWrite8Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerWrite8Callback(address, clazz, methodName); - } - - @Override - public void registerWrite16Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerWrite16Callback(address, clazz, methodName); - } - - @Override - public void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { - realAddressSpace.registerWrite16Callback(address, clazz, methodName, allowSubWrite); - } - - @Override - public void registerWrite32Callback(int address, Class clazz, String methodName) { - realAddressSpace.registerWrite32Callback(address, clazz, methodName); - } - - @Override - public void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { - realAddressSpace.registerWrite32Callback(address, clazz, methodName, allowSubWrite); - } - - @Override - public void registerPoll32Callback(int address, Pollable pollable) { - realAddressSpace.registerPoll32Callback(address, pollable); - } - - @Override - public ClassGen modifyClass(String classname, ClassGen original) { - return realAddressSpace.modifyClass(classname, original); - } - - @Override - public void cpuResumed() { - cpuActive = true; - ramBreakpointsActive = ramBreakpoints.size() > 0; - } - - @Override - public void cpuPaused() { - cpuActive = false; - ramBreakpointsActive = false; - } - - public static class Hardware { - public static void write8(int address, int value) { - AddressSpaceImpl.Hardware.write8(address, value); - } - - public static void write16(int address, int value) { - AddressSpaceImpl.Hardware.write16(address, value); - } - - public static void write32(int address, int value) { - AddressSpaceImpl.Hardware.write32(address, value); - } - - public static int read8(int address) { - return AddressSpaceImpl.Hardware.read8(address); - } - - public static int read16(int address) { - return AddressSpaceImpl.Hardware.read16(address); - } - - public static int read32(int address) { - return AddressSpaceImpl.Hardware.read32(address); - } - - public static int defaultRead32(int address) { - return AddressSpaceImpl.Hardware.defaultRead32(address); - } - - public static void defaultWrite32(int address, int value) { - AddressSpaceImpl.Hardware.defaultWrite32(address, value); - } - - public static int defaultRead16(int address) { - return AddressSpaceImpl.Hardware.defaultRead16(address); - } - - public static void defaultWrite16(final int address, int value) { - AddressSpaceImpl.Hardware.defaultWrite16(address, value); - } - - public static int defaultRead8(int address) { - return AddressSpaceImpl.Hardware.defaultRead8(address); - } - - public static void defaultWrite8(final int address, int value) { - AddressSpaceImpl.Hardware.defaultWrite8(address, value); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java b/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java deleted file mode 100644 index 5976b2b..0000000 --- a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.debugcomponents.emulator.console; - -import org.jpsx.api.CPUControl; -import org.jpsx.api.CPUListener; -import org.jpsx.api.components.core.addressspace.AddressSpace; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.api.components.core.scheduler.Quartz; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.components.core.CoreComponentConnections; -import org.jpsx.runtime.debugcomponents.core.DebugAddressSpaceImpl; -import org.jpsx.runtime.components.hardware.gte.GTE; -import org.jpsx.runtime.util.MiscUtil; - -import java.io.*; - -public class Console extends JPSXComponent implements Runnable, CPUListener { - protected int lastDisAddress; - protected boolean skipShow = true; - - private AddressSpace addressSpace; - private R3000 r3000; - private CPUControl cpuControl; - private Quartz quartz; - - public void init() { - super.init(); - RuntimeConnections.MAIN.set(this); - CoreComponentConnections.CPU_LISTENERS.add(this); - } - - - public void resolveConnections() { - super.resolveConnections(); - addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); - r3000 = CoreComponentConnections.R3000.resolve(); - cpuControl = RuntimeConnections.CPU_CONTROL.resolve(); - quartz = CoreComponentConnections.QUARTZ.resolve(); - } - - public Console() { - super("JPSX Basic Console"); - } - - public void run() { - System.out.println("JPSX Copyright (C) 2003, 2014 Graham Sanderson"); - System.out.println("This program comes with ABSOLUTELY NO WARRANTY; type 'l' for details."); - System.out.println("This is free software, and you are welcome to redistribute it"); - System.out.println("under certain conditions; type 'l' for details."); - System.out.println(); - dumpMainRegs(); - - int lastDumpAddress = 0; - DataInputStream input = new DataInputStream(System.in); - boolean quit = false; - - long msBase = System.currentTimeMillis(); - long clockBase = quartz.nanoTime(); - showCurrentInstruction(); - try { - while (!quit) { - String line = input.readLine(); - if (line == null || line.length() == 0) { - continue; - } - switch (line.charAt(0)) { - case'r': - dumpMainRegs(); - break; - case'2': - dumpGTERegs(); - break; - case't': - long deltans = 1000000L * (System.currentTimeMillis() - msBase); - long deltaClock = quartz.nanoTime() - clockBase; - System.out.println("Clocks: " + deltans + " " + deltaClock + " " + (1.0 * deltaClock) / deltans); - msBase = System.currentTimeMillis(); - clockBase = quartz.nanoTime(); - break; - case'g': - cpuControl.go(); - break; - case'u': { - String addr = line.substring(1).trim(); - if (addr.length() > 0) - lastDisAddress = MiscUtil.parseHex(addr); - for (int i = 0; i < 20; i++) { - int ci = addressSpace.internalRead32(lastDisAddress); - String dis = r3000.disassemble(lastDisAddress, ci); - System.out.println(MiscUtil.toHex(lastDisAddress, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); - lastDisAddress += 4; - } - break; - } - case'o': { - String sStart = line.substring(1).trim(); - int pos = sStart.indexOf(' '); - if (pos != -1) { - int start = MiscUtil.parseHex(sStart); - int end = MiscUtil.parseHex(sStart.substring(pos).trim()); - try { - PrintWriter fw = new PrintWriter(new FileOutputStream("o.dis")); - for (int i = start; i < end; i += 4) { - int ci = addressSpace.internalRead32(i); - String dis = MiscUtil.toHex(i, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + r3000.disassemble(i, ci); - fw.println(dis); - } - fw.close(); - } catch (IOException e) { - } - } - break; - } - case'l': - LineNumberReader reader = new LineNumberReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("LICENSE"))); - String licenseLine; - while (null != (licenseLine = reader.readLine())) { - System.out.println(licenseLine); - } - break; - case'b': - if (line.length() > 1) { - try { - switch (line.charAt(1)) { - case 'l': { - int[] bps = cpuControl.getBreakpoints(); - for (int i = 0; i < bps.length; i++) { - System.out.println(Integer.toHexString(i) + ": " + MiscUtil.toHex(bps[i], 8)); - } - break; - } - case 'p': - case ' ': { - int address = MiscUtil.parseHex(line.substring(2)); - cpuControl.addBreakpoint(address); - break; - } - case 'c': { - int address = MiscUtil.parseHex(line.substring(2)); - cpuControl.removeBreakpoint(address); - break; - } - } - } catch (Throwable t) { - System.out.println("Failed to set breakpoint: " + t); - } - } else { - cpuControl.pause(); - } - break; - // RAM breakpoints - case'm': - if (line.length() > 1 && addressSpace.getClass() == DebugAddressSpaceImpl.class) { - DebugAddressSpaceImpl debugAddressSpace = (DebugAddressSpaceImpl) addressSpace; - try { - switch (line.charAt(1)) { - case 'l': { - int[] bps = debugAddressSpace.getActiveRAMBreakpoints(); - for (int i = 0; i < bps.length; i++) { - System.out.println(Integer.toHexString(i) + ": " + MiscUtil.toHex(bps[i], 8)); - } - break; - } - case 'p': - case ' ': { - int address = MiscUtil.parseHex(line.substring(2)); - debugAddressSpace.activateRAMBreakpoint(address); - break; - } - case 'c': { - int address = MiscUtil.parseHex(line.substring(2)); - debugAddressSpace.deactivateRAMBreakpoint(address); - break; - } - } - } catch (Throwable t) { - System.out.println("Failed to set breakpoint: " + t); - } - } else if (addressSpace.getClass() != DebugAddressSpaceImpl.class) { - System.out.println("You must use DebugAddressSpaceImpl in order to use this feature. Currently using: " + addressSpace.getClass().getName()); - } - break; - case'c': - System.out.println("calling for gc"); - System.gc(); - break; - case'i': - try { - int i = Integer.parseInt(line.substring(1).trim()); - System.out.println("Raising IRQ " + i); - CoreComponentConnections.IRQ_CONTROLLER.resolve().raiseIRQ(i); - } catch (Throwable t) { - } - break; - case'w': { - int type = 'd'; - int base = 1; - if (base < line.length()) { - if (line.charAt(base) == 'w') { - type = 'w'; - base++; - } else if (line.charAt(base) == 'b') { - type = 'b'; - base++; - } - } - String parse = line.substring(base); - parse = parse.trim(); - if (parse.length() > 0) { - int split = parse.indexOf(' '); - try { - if (split >= 0) { - int address = MiscUtil.parseHex(parse.substring(0, split).trim()); - int value = MiscUtil.parseHex(parse.substring(split).trim()); - //System.out.println("address = "+MiscUtil.toHex( address, 8)+" value = "+MiscUtil.toHex( value, 8)); - switch (type) { - case'd': - addressSpace.write32(address, value); - break; - case'w': - addressSpace.write16(address, value & 0xffff); - break; - case'b': - addressSpace.write8(address, value & 0xff); - break; - } - } - } catch (Throwable t) { - } - } - break; - } - case'd': { - int type = 'd'; - int base = 1; - if (base < line.length()) { - if (line.charAt(base) == 'w') { - type = 'w'; - base++; - } else if (line.charAt(base) == 'b') { - type = 'b'; - base++; - } - } - String parse = line.substring(base); - parse = parse.trim(); - int count = 6; - int address = lastDumpAddress; - if (parse.length() > 0) { - int split = parse.indexOf(' '); - try { - if (split >= 0) { - count = Integer.parseInt(parse.substring(split).trim()); - } - } catch (Throwable t) { - } - address = MiscUtil.parseHex(parse); - } - if (count > 0) { - for (int i = 0; i < count; i++, address += 16) { - int j; - String val = MiscUtil.toHex(address, 8) + ": "; - switch (type) { - case'd': - if (0 != (address & 3)) - address = address & ~3; - for (j = 0; j < 4; j++) { - val += MiscUtil.toHex(addressSpace.read32(address + j * 4), 8) + " "; - } - break; - case'w': - if (0 != (address & 1)) - address = address & ~1; - for (j = 0; j < 8; j++) { - val += MiscUtil.toHex(addressSpace.read16(address + j * 2), 4) + " "; - } - break; - case'b': - for (j = 0; j < 16; j++) { - val += MiscUtil.toHex(addressSpace.read8(address + j), 2) + " "; - } - break; - } - val += " "; - for (j = 0; j < 16; j++) { - int b = addressSpace.read8(address + j); - if (b >= 32 && b < 127) { - val += (char) b; - } else { - val += " "; - } - } - System.out.println(val); - } - lastDumpAddress = address; - } - break; - } - case's': - cpuControl.step(); - break; - case'q': - //if (jsx.core.NativeCompiler.profiling) { - // jsx.core.NativeCompiler.dumpProfiling(); - //} - quit = true; - break; - case'v': - String parse = line.substring(2); - parse = parse.trim(); - if (parse.startsWith("fill")) { - //SPU.fill(); - break; - } - int sp = parse.indexOf(' '); - if (sp > 0) { - try { - int voice = Integer.parseInt(parse.substring(0, sp)); - parse = parse.substring(sp + 1); - if (voice >= 0 && voice < 24) { - if (parse.startsWith("on")) { - if (voice < 16) { - addressSpace.write16(0x1f801d88, 1 << (voice)); - } else { - addressSpace.write16(0x1f801d8a, 1 << (voice - 16)); - } - System.out.println("voice " + voice + " on"); - } else if (parse.startsWith("off")) { - if (voice < 16) { - addressSpace.write16(0x1f801d8c, 1 << (voice)); - } else { - addressSpace.write16(0x1f801d8e, 1 << (voice - 16)); - } - System.out.println("voice " + voice + " off"); - } else if (parse.startsWith("freq")) { - int freq = MiscUtil.parseHex(parse.substring(5)); - addressSpace.write16(0x1f801c04 + (voice * 16), freq); - System.out.println("voice " + voice + " freq set to " + MiscUtil.toHex(freq, 4)); - } - } - } catch (Throwable t) { - } - } - break; - } - } - ; - } catch (Throwable t) { - t.printStackTrace(); - } - } - - public void showCurrentInstruction() { - if (skipShow) { - skipShow = false; - } else { - int pc = r3000.getPC(); - int ci = addressSpace.internalRead32(pc); - String dis = r3000.disassemble(pc, ci); - System.out.println(MiscUtil.toHex(pc, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); - lastDisAddress = pc + 4; - } - } - - public void dumpGTERegs() { - System.out.println("vxy0 " + MiscUtil.toHex(GTE.readRegister(0x00), 8) + " vz0 " + MiscUtil.toHex(GTE.readRegister(0x01), 8) + " vxy1 " + MiscUtil.toHex(GTE.readRegister(0x02), 8) + " vz1 " + MiscUtil.toHex(GTE.readRegister(0x03), 8)); - System.out.println("vxy2 " + MiscUtil.toHex(GTE.readRegister(0x04), 8) + " vz2 " + MiscUtil.toHex(GTE.readRegister(0x05), 8) + " rgb " + MiscUtil.toHex(GTE.readRegister(0x06), 8) + " otz " + MiscUtil.toHex(GTE.readRegister(0x07), 8)); - System.out.println("ir0 " + MiscUtil.toHex(GTE.readRegister(0x08), 8) + " ir1 " + MiscUtil.toHex(GTE.readRegister(0x09), 8) + " ir2 " + MiscUtil.toHex(GTE.readRegister(0x0a), 8) + " ir3 " + MiscUtil.toHex(GTE.readRegister(0x0b), 8)); - System.out.println("sxy0 " + MiscUtil.toHex(GTE.readRegister(0x0c), 8) + " sxy1 " + MiscUtil.toHex(GTE.readRegister(0x0d), 8) + " sxy2 " + MiscUtil.toHex(GTE.readRegister(0x0e), 8) + " sxyp " + MiscUtil.toHex(GTE.readRegister(0x0f), 8)); - System.out.println("sz0 " + MiscUtil.toHex(GTE.readRegister(0x10), 8) + " sz1 " + MiscUtil.toHex(GTE.readRegister(0x11), 8) + " sz2 " + MiscUtil.toHex(GTE.readRegister(0x12), 8) + " sz3 " + MiscUtil.toHex(GTE.readRegister(0x13), 8)); - System.out.println("rgb0 " + MiscUtil.toHex(GTE.readRegister(0x14), 8) + " rgb1 " + MiscUtil.toHex(GTE.readRegister(0x15), 8) + " rgb2 " + MiscUtil.toHex(GTE.readRegister(0x16), 8) + " res1 " + MiscUtil.toHex(GTE.readRegister(0x17), 8)); - System.out.println("mac0 " + MiscUtil.toHex(GTE.readRegister(0x18), 8) + " mac1 " + MiscUtil.toHex(GTE.readRegister(0x19), 8) + " mac2 " + MiscUtil.toHex(GTE.readRegister(0x1a), 8) + " mac3 " + MiscUtil.toHex(GTE.readRegister(0x1b), 8)); - System.out.println("irgb " + MiscUtil.toHex(GTE.readRegister(0x1c), 8) + " orgb " + MiscUtil.toHex(GTE.readRegister(0x1d), 8) + " lzcs " + MiscUtil.toHex(GTE.readRegister(0x1e), 8) + " lzcr " + MiscUtil.toHex(GTE.readRegister(0x1f), 8)); - System.out.println("r11r12 " + MiscUtil.toHex(GTE.readRegister(0x20), 8) + " r13r21 " + MiscUtil.toHex(GTE.readRegister(0x21), 8) + " r22r23 " + MiscUtil.toHex(GTE.readRegister(0x22), 8) + " r31r32 " + MiscUtil.toHex(GTE.readRegister(0x23), 8)); - System.out.println("r33 " + MiscUtil.toHex(GTE.readRegister(0x24), 8) + " trx " + MiscUtil.toHex(GTE.readRegister(0x25), 8) + " try " + MiscUtil.toHex(GTE.readRegister(0x26), 8) + " trz " + MiscUtil.toHex(GTE.readRegister(0x27), 8)); - System.out.println("l11r12 " + MiscUtil.toHex(GTE.readRegister(0x28), 8) + " l13r21 " + MiscUtil.toHex(GTE.readRegister(0x29), 8) + " l22r23 " + MiscUtil.toHex(GTE.readRegister(0x2a), 8) + " l31r32 " + MiscUtil.toHex(GTE.readRegister(0x2b), 8)); - System.out.println("l33 " + MiscUtil.toHex(GTE.readRegister(0x2c), 8) + " rbk " + MiscUtil.toHex(GTE.readRegister(0x2d), 8) + " gbk " + MiscUtil.toHex(GTE.readRegister(0x2e), 8) + " bbk " + MiscUtil.toHex(GTE.readRegister(0x2f), 8)); - System.out.println("lr1lr2 " + MiscUtil.toHex(GTE.readRegister(0x30), 8) + " lr3lg1 " + MiscUtil.toHex(GTE.readRegister(0x31), 8) + " lg2lg3 " + MiscUtil.toHex(GTE.readRegister(0x32), 8) + " lb1lb2 " + MiscUtil.toHex(GTE.readRegister(0x33), 8)); - System.out.println("lb3 " + MiscUtil.toHex(GTE.readRegister(0x34), 8) + " rfc " + MiscUtil.toHex(GTE.readRegister(0x35), 8) + " gfc " + MiscUtil.toHex(GTE.readRegister(0x36), 8) + " bfc " + MiscUtil.toHex(GTE.readRegister(0x37), 8)); - System.out.println("ofx " + MiscUtil.toHex(GTE.readRegister(0x38), 8) + " ofy " + MiscUtil.toHex(GTE.readRegister(0x39), 8) + " h " + MiscUtil.toHex(GTE.readRegister(0x3a), 8) + " dqa " + MiscUtil.toHex(GTE.readRegister(0x3b), 8)); - System.out.println("dqb " + MiscUtil.toHex(GTE.readRegister(0x3c), 8) + " zsf3 " + MiscUtil.toHex(GTE.readRegister(0x3d), 8) + " zsf4 " + MiscUtil.toHex(GTE.readRegister(0x3e), 8) + " flag " + MiscUtil.toHex(GTE.readRegister(0x3f), 8)); - } - - public void dumpMainRegs() { - System.out.println("r0 " + MiscUtil.toHex(r3000.getReg(0), 8) + " r1 " + MiscUtil.toHex(r3000.getReg(1), 8) + " r2 " + MiscUtil.toHex(r3000.getReg(2), 8) + " r3 " + MiscUtil.toHex(r3000.getReg(3), 8) + " pc " + MiscUtil.toHex(r3000.getPC(), 8)); - System.out.println("r4 " + MiscUtil.toHex(r3000.getReg(4), 8) + " r5 " + MiscUtil.toHex(r3000.getReg(5), 8) + " r6 " + MiscUtil.toHex(r3000.getReg(6), 8) + " r7 " + MiscUtil.toHex(r3000.getReg(7), 8) + " lo " + MiscUtil.toHex(r3000.getLO(), 8)); - System.out.println("r8 " + MiscUtil.toHex(r3000.getReg(8), 8) + " r9 " + MiscUtil.toHex(r3000.getReg(9), 8) + " r10 " + MiscUtil.toHex(r3000.getReg(10), 8) + " r11 " + MiscUtil.toHex(r3000.getReg(11), 8) + " hi " + MiscUtil.toHex(r3000.getHI(), 8)); - System.out.println("r12 " + MiscUtil.toHex(r3000.getReg(12), 8) + " r13 " + MiscUtil.toHex(r3000.getReg(13), 8) + " r14 " + MiscUtil.toHex(r3000.getReg(14), 8) + " r15 " + MiscUtil.toHex(r3000.getReg(15), 8)); - System.out.println("r16 " + MiscUtil.toHex(r3000.getReg(16), 8) + " r17 " + MiscUtil.toHex(r3000.getReg(17), 8) + " r18 " + MiscUtil.toHex(r3000.getReg(18), 8) + " r19 " + MiscUtil.toHex(r3000.getReg(19), 8)); - System.out.println("r20 " + MiscUtil.toHex(r3000.getReg(20), 8) + " r21 " + MiscUtil.toHex(r3000.getReg(21), 8) + " r22 " + MiscUtil.toHex(r3000.getReg(22), 8) + " r23 " + MiscUtil.toHex(r3000.getReg(23), 8)); - System.out.println("r24 " + MiscUtil.toHex(r3000.getReg(24), 8) + " r25 " + MiscUtil.toHex(r3000.getReg(25), 8) + " r26 " + MiscUtil.toHex(r3000.getReg(26), 8) + " r27 " + MiscUtil.toHex(r3000.getReg(27), 8)); - System.out.println("r28 " + MiscUtil.toHex(r3000.getReg(28), 8) + " r29 " + MiscUtil.toHex(r3000.getReg(29), 8) + " r30 " + MiscUtil.toHex(r3000.getReg(30), 8) + " r31 " + MiscUtil.toHex(r3000.getReg(31), 8)); - } - - public void cpuResumed() { - } - - public void cpuPaused() { - showCurrentInstruction(); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java b/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java deleted file mode 100644 index 2cb7064..0000000 --- a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.debugcomponents.emulator.disassemblers; - -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; -import org.jpsx.api.components.core.cpu.InstructionProvider; -import org.jpsx.api.components.core.cpu.InstructionRegistrar; -import org.jpsx.runtime.JPSXComponent; -import org.jpsx.runtime.components.core.CoreComponentConnections; - -public abstract class DisassemblerComponent extends JPSXComponent implements InstructionProvider { - protected DisassemblerComponent(String description) { - super(description); - } - - @Override - public void init() { - super.init(); - CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); - } - - protected static String padString(String s) { - return padString(s, 8); - } - - protected static String padString(String val, int chars) { - String rc = val + " "; - return rc.substring(0, chars); - } - - protected static class DIS implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()); - } - } - - public abstract void addInstructions(InstructionRegistrar registrar); -} diff --git a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java b/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java deleted file mode 100644 index 7e73e5d..0000000 --- a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.debugcomponents.emulator.disassemblers; - -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; -import org.jpsx.api.components.core.cpu.InstructionRegistrar; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.runtime.util.MiscUtil; - -public class GTEInstructionDisassembler extends DisassemblerComponent { - public GTEInstructionDisassembler() { - super("JPSX Disassembler for GTE Instructions"); - } - - public void addInstructions(InstructionRegistrar registrar) { - DIS dis = new DIS(); - registrar.setInstructionDisassembler("eret", dis); - registrar.setInstructionDisassembler("mtc2", new DIS_MTC2()); - registrar.setInstructionDisassembler("mfc2", new DIS_MFC2()); - registrar.setInstructionDisassembler("ctc2", new DIS_CTC2()); - registrar.setInstructionDisassembler("cfc2", new DIS_CFC2()); - registrar.setInstructionDisassembler("lwc2", new DIS_LWC2()); - registrar.setInstructionDisassembler("swc2", new DIS_SWC2()); - registrar.setInstructionDisassembler("rtpt", dis); - registrar.setInstructionDisassembler("rtps", dis); - registrar.setInstructionDisassembler("mvmva", dis); - registrar.setInstructionDisassembler("op", dis); - registrar.setInstructionDisassembler("avsz3", dis); - registrar.setInstructionDisassembler("avsz4", dis); - registrar.setInstructionDisassembler("nclip", dis); - registrar.setInstructionDisassembler("ncct", dis); - registrar.setInstructionDisassembler("gpf", dis); - registrar.setInstructionDisassembler("dcpl", dis); - registrar.setInstructionDisassembler("dpcs", dis); - registrar.setInstructionDisassembler("intpl", dis); - registrar.setInstructionDisassembler("sqr", dis); - registrar.setInstructionDisassembler("ncs", dis); - registrar.setInstructionDisassembler("nct", dis); - registrar.setInstructionDisassembler("ncds", dis); - registrar.setInstructionDisassembler("ncdt", dis); - registrar.setInstructionDisassembler("dpct", dis); - registrar.setInstructionDisassembler("nccs", dis); - registrar.setInstructionDisassembler("cdp", dis); - registrar.setInstructionDisassembler("cc", dis); - registrar.setInstructionDisassembler("gpl", dis); - } - - - private static final String gteNames[] = new String[]{ - "vxy0", "vz0", "vxy1", "vz1", "vxy2", "vz2", "rgb", "otz", - "ir0", "ir1", "ir2", "ir3", "sxy0", "sxy1", "sxy2", "sxyp", - "szx", "sz0", "sz1", "sz2", "rgb0", "rgb1", "rgb2", "res1", - "mac0", "mac1", "mac2", "mac3", "irgb", "orgb", "lzcs", "lzcr", - "r11r12", "r13r21", "r22r23", "r31r32", "r33", "trx", "try", "trz", - "l11l12", "l13l21", "l22l23", "l31l32", "l33", "rbk", "gbk", "bbk", - "lr1lr2", "lr3lg1", "lg2lg3", "lb1lb2", "lb3", "rfc", "gfc", "bfc", - "ofx", "ofy", "h", "dqa", "dqb", "zsf3", "zsf4", "flag" - }; - - private static class DIS_LWC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - return padString(inst.getName()) + " " + gteNames[R3000.Util.bits_rt(ci)] + ", r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "]"; - } - } - - private static class DIS_SWC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "], " + gteNames[R3000.Util.bits_rt(ci)]; - } - } - - private static class DIS_MTC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - return padString(inst.getName()) + " " + gteNames[rd] + ", r" + rt; - } - } - - private static class DIS_MFC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - return padString(inst.getName()) + " r" + rt + ", " + gteNames[rd]; - } - } - - private static class DIS_CTC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - return padString(inst.getName()) + " " + gteNames[rd + 32] + ", r" + rt; - } - } - - private static class DIS_CFC2 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - return padString(inst.getName()) + " r" + rt + ", " + gteNames[rd + 32]; - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java b/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java deleted file mode 100644 index 89885bf..0000000 --- a/src/runtime/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.debugcomponents.emulator.disassemblers; - -import org.jpsx.api.components.core.cpu.CPUInstruction; -import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; -import org.jpsx.api.components.core.cpu.InstructionRegistrar; -import org.jpsx.api.components.core.cpu.R3000; -import org.jpsx.runtime.util.MiscUtil; - -// TODO move setting of instructions elsewhere - -public class R3000InstructionDisassembler extends DisassemblerComponent { - public R3000InstructionDisassembler() { - super("JPSX Disassembler for R3000 Instructions"); - } - - public void addInstructions(InstructionRegistrar registrar) { - DIS_TSB disTSB = new DIS_TSB(); - DIS_SB disSB = new DIS_SB(); - DIS_TSI disTSI = new DIS_TSI(); - DIS_TSIU disTSIU = new DIS_TSIU(); - DIS_TIU disTIU = new DIS_TIU(); - DIS_TSA disTSA = new DIS_TSA(); - DIS_SAT disSAT = new DIS_SAT(); - DIS_ST disST = new DIS_ST(); - DIS_DTH disDTH = new DIS_DTH(); - DIS_DST disDST = new DIS_DST(); - DIS_DTS disDTS = new DIS_DTS(); - DIS_J disJ = new DIS_J(); - DIS_S disS = new DIS_S(); - DIS_D disD = new DIS_D(); - DIS_SD disSD = new DIS_SD(); - DIS_C disC = new DIS_C(); - DIS dis = new DIS(); - - registrar.setInstructionDisassembler("bne", disTSB); - registrar.setInstructionDisassembler("beq", disTSB); - registrar.setInstructionDisassembler("addi", disTSI); - registrar.setInstructionDisassembler("addiu", disTSI); - registrar.setInstructionDisassembler("slti", disTSI); - registrar.setInstructionDisassembler("sltiu", disTSI); - registrar.setInstructionDisassembler("andi", disTSIU); - registrar.setInstructionDisassembler("ori", disTSIU); - registrar.setInstructionDisassembler("xori", disTSIU); - registrar.setInstructionDisassembler("sll", disDTH); - registrar.setInstructionDisassembler("srl", disDTH); - registrar.setInstructionDisassembler("sra", disDTH); - registrar.setInstructionDisassembler("bltz", disSB); - registrar.setInstructionDisassembler("bgez", disSB); - registrar.setInstructionDisassembler("blez", disSB); - registrar.setInstructionDisassembler("bgtz", disSB); - registrar.setInstructionDisassembler("bltzal", disSB); - registrar.setInstructionDisassembler("bgezal", disSB); - registrar.setInstructionDisassembler("add", disDST); - registrar.setInstructionDisassembler("addu", disDST); - registrar.setInstructionDisassembler("sub", disDST); - registrar.setInstructionDisassembler("subu", disDST); - registrar.setInstructionDisassembler("and", disDST); - registrar.setInstructionDisassembler("or", disDST); - registrar.setInstructionDisassembler("xor", disDST); - registrar.setInstructionDisassembler("nor", disDST); - registrar.setInstructionDisassembler("slt", disDST); - registrar.setInstructionDisassembler("sltu", disDST); - registrar.setInstructionDisassembler("lb", disTSA); - registrar.setInstructionDisassembler("lh", disTSA); - registrar.setInstructionDisassembler("lwl", disTSA); - registrar.setInstructionDisassembler("lw", disTSA); - registrar.setInstructionDisassembler("lbu", disTSA); - registrar.setInstructionDisassembler("lhu", disTSA); - registrar.setInstructionDisassembler("lwr", disTSA); - registrar.setInstructionDisassembler("sb", disSAT); - registrar.setInstructionDisassembler("sh", disSAT); - registrar.setInstructionDisassembler("swl", disSAT); - registrar.setInstructionDisassembler("sw", disSAT); - registrar.setInstructionDisassembler("swr", disSAT); - registrar.setInstructionDisassembler("lui", disTIU); - registrar.setInstructionDisassembler("sllv", disDTS); - registrar.setInstructionDisassembler("srlv", disDTS); - registrar.setInstructionDisassembler("srav", disDTS); - registrar.setInstructionDisassembler("mult", disST); - registrar.setInstructionDisassembler("multu", disST); - registrar.setInstructionDisassembler("div", disST); - registrar.setInstructionDisassembler("divu", disST); - registrar.setInstructionDisassembler("j", disJ); - registrar.setInstructionDisassembler("jal", disJ); - registrar.setInstructionDisassembler("jr", disS); - registrar.setInstructionDisassembler("mthi", disS); - registrar.setInstructionDisassembler("mtlo", disS); - registrar.setInstructionDisassembler("mfhi", disD); - registrar.setInstructionDisassembler("mflo", disD); - registrar.setInstructionDisassembler("jalr", disSD); - - registrar.setInstructionDisassembler("syscall", disC); - registrar.setInstructionDisassembler("break", disC); - registrar.setInstructionDisassembler("eret", dis); - registrar.setInstructionDisassembler("mtc0", new DIS_MTC0()); - registrar.setInstructionDisassembler("mfc0", new DIS_MFC0()); - } - - public static class DIS_TSB implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + " 0x" + MiscUtil.toHex(address + 4 + R3000.Util.signed_branch_delta(ci), 8); - } - } - - public static class DIS_SB implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + " 0x" + MiscUtil.toHex(address + 4 + R3000.Util.signed_branch_delta(ci), 8); - } - } - - public static class DIS_TSI implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.sign_extend(ci); - String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + ", 0x" + MiscUtil.toHex(val, 4); - return padString(rc, 32) + " ;" + val; - } - } - - public static class DIS_TSIU implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + ", 0x" + MiscUtil.toHex(val, 4); - return padString(rc, 32) + " ;" + val; - } - } - - public static class DIS_TIU implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", 0x" + MiscUtil.toHex(val, 4); - return padString(rc, 32) + " ;" + val; - } - } - - public static class DIS_TSA implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - return padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "]"; - } - } - - public static class DIS_SAT implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int val = R3000.Util.lo(ci); - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "], r" + R3000.Util.bits_rt(ci); - } - } - - public static class DIS_ST implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rt(ci); - } - } - - public static class DIS_DTH implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - if (ci == 0) - return padString("nop"); - else - return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rt(ci) + ", " + R3000.Util.bits_sa(ci); - } - } - - public static class DIS_DST implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rt(ci); - } - } - - public static class DIS_DTS implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci); - } - } - - public static class DIS_J implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " 0x" + MiscUtil.toHex(((address + 4) & 0xf0000000) + ((ci & 0x3ffffff) << 2), 8); - } - } - - public static class DIS_S implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci); - } - } - - public static class DIS_D implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci); - } - } - - public static class DIS_C implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " 0x" + Integer.toHexString(R3000.Util.bits25_6(ci)); - } - } - - public static class DIS_SD implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rd(ci); - } - } - - protected static String getCOP0Name(int reg, int sel) { - - switch ((sel << 16) + reg) { - case 0: - return "index"; - case 1: - return "random"; - case 2: - return "entryLow0"; - case 3: - return "entryLow1"; - case 4: - return "context"; - case 5: - return "pageMask"; - case 6: - return "wired"; - case 8: - return "badVAddr"; - case 9: - return "count"; - case 10: - return "entryHi"; - case 11: - return "compare"; - case 12: - return "status"; - case 13: - return "cause"; - case 14: - return "epc"; - case 15: - return "progId"; - case 16: - return "config"; - case 0x10010: - return "config1"; - case 0x20010: - return "config2"; - case 0x30010: - return "config3"; - case 30: - return "errorEPC"; - default: - return reg + ":" + sel; - } - } - - protected static class DIS_MTC0 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int sel = ci & 0x7; - return padString(inst.getName()) + " " + getCOP0Name(rd, sel) + ", r" + rt; - } - } - - protected static class DIS_MFC0 implements CPUInstructionDisassembler { - public String disassemble(CPUInstruction inst, int address, int ci) { - int rt = R3000.Util.bits_rt(ci); - int rd = R3000.Util.bits_rd(ci); - int sel = ci & 0x7; - return padString(inst.getName()) + " r" + rt + ", " + getCOP0Name(rd, sel); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/util/ByteCodeUtil.java b/src/runtime/java/org/jpsx/runtime/util/ByteCodeUtil.java deleted file mode 100644 index 4544b8c..0000000 --- a/src/runtime/java/org/jpsx/runtime/util/ByteCodeUtil.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.util; - -import org.apache.bcel.generic.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.SortedMap; - -// todo client VM only - -public class ByteCodeUtil { - public static void emitSwitch(ConstantPoolGen cp, InstructionList il, int localIndex, SortedMap cases, int resolution, int lowBound, int highBound) { - if (cases.size() == 0) return; - if (true) { - emitBinaryTree(cp, il, localIndex, cases, resolution, lowBound, highBound); - } - } - - public static void emitBinaryTree(ConstantPoolGen cp, InstructionList il, int localIndex, SortedMap cases, int resolution, int lowBound, int highBound) { - List keys = new ArrayList(); - keys.addAll(cases.keySet()); - emitBinaryTree(cp, il, localIndex, keys, cases, resolution, lowBound, highBound, 0, keys.size() - 1); - } - - public static void emitBinaryTree(ConstantPoolGen cp, InstructionList il, int localIndex, List keys, SortedMap cases, int resolution, int lowBound, int highBound, int start, int end) { - if (start == end) { - IF_ICMPNE cmpne = null; - Integer key = keys.get(start); - boolean requireIf = key != lowBound || key != highBound; - if (requireIf) { - il.append(new ILOAD(localIndex)); - il.append(new PUSH(cp, key)); - cmpne = new IF_ICMPNE(null); - il.append(cmpne); - } - il.append(cases.get(key)); - if (requireIf) { - cmpne.setTarget(il.append(new NOP())); - } - } else { - int middle = (start + end + 1) / 2; - int middleValue = keys.get(middle); - - il.append(new ILOAD(localIndex)); - il.append(new PUSH(cp, middleValue)); - IF_ICMPGE cmpge = new IF_ICMPGE(null); - il.append(cmpge); - emitBinaryTree(cp, il, localIndex, keys, cases, resolution, lowBound, middleValue - resolution, start, middle - 1); - GOTO gt = new GOTO(null); - InstructionHandle gthandle = il.append(gt); - emitBinaryTree(cp, il, localIndex, keys, cases, resolution, middleValue, highBound, middle, end); - gt.setTarget(il.append(new NOP())); - cmpge.setTarget(gthandle.getNext()); - } - } -} diff --git a/src/runtime/java/org/jpsx/runtime/util/CDUtil.java b/src/runtime/java/org/jpsx/runtime/util/CDUtil.java deleted file mode 100644 index 895538f..0000000 --- a/src/runtime/java/org/jpsx/runtime/util/CDUtil.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.util; - -import org.jpsx.api.components.hardware.cd.CDMedia; -import org.jpsx.api.components.hardware.cd.MediaException; - -public class CDUtil { - // flags ORed together - public static final int MEDIA_PRESENT = 0x0001; - public static final int MEDIA_HAS_DATA = 0x0002; - public static final int MEDIA_HAS_AUDIO = 0x0004; - public static final int MEDIA_PLAYSTATION = 0x0008; - public static final int MEDIA_REGION_EUROPE = 0x0010; - public static final int MEDIA_REGION_USA = 0x0020; - public static final int MEDIA_REGION_JAPAN = 0x0040; - - public static int toBCD(int x) { - return (x % 10) + ((x / 10) << 4); - } - - public static int fromBCD(int x) { - return (x >> 4) * 10 + (x & 15); - } - - // todo fix up this method to return all types - public static int getMediaType(CDMedia media) { - int rc = 0; - if (media != null) { - rc |= MEDIA_PRESENT; - for (int i = media.getFirstTrack(); i <= media.getLastTrack(); i++) { - CDMedia.TrackType tt = media.getTrackType(i); - if (tt == CDMedia.TrackType.AUDIO) { - rc |= MEDIA_HAS_AUDIO; - } else if (tt == CDMedia.TrackType.MODE2_2352) { - rc |= MEDIA_HAS_DATA; - } - } - if (0 != (rc & MEDIA_HAS_DATA)) { - try { - int[] sector = new int[2352 / 4]; - media.readSector(4, sector); - int countryCode = (sector[0x15] & 0xff); - if (countryCode == 'E') { - rc |= MEDIA_REGION_EUROPE; - } else { - } - } catch (MediaException e) { - } - } - } - return rc; - } - - public static int toMSF(int m, int s, int f) { - return (toBCD(m) << 16) | (toBCD(s) << 8) | toBCD(f); - } - - public static int toSector(int m, int s, int f) { - return (m * 60 + s) * 75 + f - 150; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/util/ClassUtil.java b/src/runtime/java/org/jpsx/runtime/util/ClassUtil.java deleted file mode 100644 index 5756480..0000000 --- a/src/runtime/java/org/jpsx/runtime/util/ClassUtil.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.util; - -public class ClassUtil { - - public static String signatureOfClass(String clazz) { - return "L" + clazz.replace('.', '/') + ";"; - } - - public static String innerClassName(Class clazz, String innerClass) { - return clazz.getName() + "$" + innerClass; - } -} diff --git a/src/runtime/java/org/jpsx/runtime/util/MiscUtil.java b/src/runtime/java/org/jpsx/runtime/util/MiscUtil.java deleted file mode 100644 index c5624bb..0000000 --- a/src/runtime/java/org/jpsx/runtime/util/MiscUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.util; - -import org.jpsx.runtime.RuntimeConnections; -import org.jpsx.runtime.components.core.CoreComponentConnections; - -public class MiscUtil { - public static String toHex(int val, int digits) { - String rc = Integer.toHexString(val); - if (rc.length() != digits) { - rc = "0000000000000000" + rc; - rc = rc.substring(rc.length() - digits, rc.length()); - } - return rc; - } - - protected static String ALPHA = "0123456789abcdef"; - - public static int parseHex(String hex) { - int rc = 0; - hex = hex.trim().toLowerCase(); - for (int i = 0; i < hex.length(); i++) { - int val = ALPHA.indexOf(hex.charAt(i)); - if (val == -1) { - break; - } - rc = (rc << 4) + val; - } - return rc; - } - - private static int assertionCounter; - - /** - * Note the intention is not to pass a boolean flag here, since the check cannot be elided by the compiler - * if it is known to be false at the call site - * - * @param message - */ - public static void assertionMessage(String message) { - int pc = CoreComponentConnections.R3000.resolve().getPC(); - System.out.println(toHex(assertionCounter++, 8) + " " + toHex(pc, 8) + ": " + message); - - // we may want to have a version that pauses - note this now works correctly from execution thread. - //RuntimeConnections.CPU_CONTROL.resolve().pause(); - } -} diff --git a/src/runtime/java/org/jpsx/runtime/util/Timing.java b/src/runtime/java/org/jpsx/runtime/util/Timing.java deleted file mode 100644 index a9d73fc..0000000 --- a/src/runtime/java/org/jpsx/runtime/util/Timing.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2003, 2014 Graham Sanderson - * - * This file is part of JPSX. - * - * JPSX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * JPSX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with JPSX. If not, see . - */ -package org.jpsx.runtime.util; - -public class Timing { - public static final String CATEGORY = "Timing"; - - public static long nanos() { - return System.nanoTime(); - } -} - From 1a70a98661f0b9a1651ea03074bd2dd66f0c97c1 Mon Sep 17 00:00:00 2001 From: neoexpert Date: Fri, 10 Jul 2020 09:21:38 +0200 Subject: [PATCH 2/6] port to maven --- src/api/pom.xml | 33 + .../main/java/org/jpsx/api/CPUControl.java | 60 + .../main/java/org/jpsx/api/CPUListener.java | 35 + .../api/InvalidConfigurationException.java | 29 + .../core/ContinueExecutionException.java | 39 + .../core/ImmediateBreakoutException.java | 4 + .../core/ReturnFromExceptionException.java | 27 + .../core/addressspace/AddressSpace.java | 145 + .../addressspace/AddressSpaceListener.java | 23 + .../addressspace/AddressSpaceRegistrar.java | 43 + .../core/addressspace/MemoryMapped.java | 30 + .../core/addressspace/Pollable.java | 23 + .../components/core/cpu/CPUInstruction.java | 137 + .../core/cpu/CPUInstructionDisassembler.java | 39 + .../core/cpu/CompilationContext.java | 123 + .../core/cpu/InstructionProvider.java | 23 + .../core/cpu/InstructionRegistrar.java | 29 + .../components/core/cpu/NativeCompiler.java | 124 + .../core/cpu/PollBlockListener.java | 40 + .../jpsx/api/components/core/cpu/R3000.java | 137 + .../org/jpsx/api/components/core/cpu/SCP.java | 55 + .../components/core/dma/DMAChannelOwner.java | 33 + .../components/core/dma/DMAController.java | 34 + .../components/core/irq/IRQController.java | 44 + .../api/components/core/irq/IRQOwner.java | 33 + .../api/components/core/scheduler/Quartz.java | 67 + .../core/scheduler/ScheduledAction.java | 33 + .../components/core/scheduler/Scheduler.java | 94 + .../components/hardware/cd/CDAudioSink.java | 42 + .../api/components/hardware/cd/CDDrive.java | 36 + .../api/components/hardware/cd/CDMedia.java | 43 + .../hardware/cd/MediaException.java | 29 + .../api/components/hardware/gpu/Display.java | 36 + .../hardware/gpu/DisplayManager.java | 97 + .../components/hardware/sio/SerialDevice.java | 29 + .../components/hardware/sio/SerialPort.java | 25 + src/bootstrap/pom.xml | 44 + .../java/org/jpsx/bootstrap/JPSXLauncher.java | 110 + .../org/jpsx/bootstrap/JPSXLauncher2.java | 126 + .../jpsx/bootstrap/JPSXMachineLifecycle.java | 29 + .../bootstrap/classloader/ClassGenerator.java | 29 + .../bootstrap/classloader/ClassModifier.java | 27 + .../classloader/JPSXClassLoader.java | 234 + .../configuration/ComponentDefinition.java | 44 + .../configuration/MachineDefinition.java | 66 + .../XMLMachineDefinitionParser.java | 213 + .../jpsx/bootstrap/connection/Connection.java | 105 + .../connection/MultipleConnection.java | 100 + .../connection/SimpleConnection.java | 93 + .../bootstrap/util/CollectionsFactory.java | 43 + src/lwjgl/pom.xml | 56 + .../components/hardware/gpu/LWJGLDisplay.java | 453 + src/pom.xml | 34 + src/runtime/pom.xml | 49 + .../org/jpsx/runtime/EmulationException.java | 29 + .../jpsx/runtime/FinalComponentSettings.java | 56 + .../runtime/FinalResolvedConnectionCache.java | 28 + .../java/org/jpsx/runtime/JPSXComponent.java | 79 + .../java/org/jpsx/runtime/JPSXMachine.java | 36 + .../org/jpsx/runtime/JPSXMachineImpl.java | 153 + .../org/jpsx/runtime/RuntimeConnections.java | 36 + .../jpsx/runtime/SingletonJPSXComponent.java | 45 + .../components/core/AddressSpaceImpl.java | 1786 ++++ .../core/CoreComponentConnections.java | 53 + .../components/core/DMAChannelOwnerBase.java | 67 + .../components/core/DMAControllerImpl.java | 240 + .../components/core/DefaultQuartz.java | 73 + .../components/core/IRQControllerImpl.java | 144 + .../runtime/components/core/IRQOwnerBase.java | 61 + .../runtime/components/core/MTScheduler.java | 277 + .../runtime/components/core/R3000Impl.java | 1027 ++ .../jpsx/runtime/components/core/SCPImpl.java | 449 + .../emulator/compiler/CodeUnit.java | 258 + .../compiler/CompilerClassLoader.java | 59 + .../emulator/compiler/Executable.java | 23 + .../emulator/compiler/FlowAnalyzer.java | 419 + .../emulator/compiler/MultiStageCompiler.java | 896 ++ .../emulator/compiler/Stage1Generator.java | 1277 +++ .../emulator/compiler/Stage2Generator.java | 1255 +++ .../HardwareComponentConnections.java | 38 + .../components/hardware/bios/ImageBIOS.java | 82 + .../runtime/components/hardware/cd/CD.java | 1676 +++ .../components/hardware/cd/XADecoder.java | 322 + .../hardware/counters/Counters.java | 362 + .../components/hardware/gpu/AWTDisplay.java | 339 + .../hardware/gpu/DefaultDisplayManager.java | 445 + .../runtime/components/hardware/gpu/GPU.java | 9260 +++++++++++++++++ .../components/hardware/gpu/GPUGenerated.java | 5599 ++++++++++ .../runtime/components/hardware/gte/GTE.java | 3585 +++++++ .../components/hardware/mdec/IDCT.java | 141 + .../components/hardware/mdec/MDEC.java | 459 + .../hardware/media/CueBinImageDrive.java | 259 + .../hardware/r3000/R3000InstructionSet.java | 2947 ++++++ .../hardware/sio/AWTKeyboardController.java | 105 + .../components/hardware/sio/BasicPad.java | 73 + .../runtime/components/hardware/sio/SIO0.java | 265 + .../hardware/sio/StandardController.java | 71 + .../components/hardware/spu/NullSPU.java | 289 + .../runtime/components/hardware/spu/SPU.java | 1287 +++ .../core/DebugAddressSpaceImpl.java | 386 + .../emulator/console/Console.java | 419 + .../disassemblers/DisassemblerComponent.java | 55 + .../GTEInstructionDisassembler.java | 122 + .../R3000InstructionDisassembler.java | 289 + .../org/jpsx/runtime/util/ByteCodeUtil.java | 74 + .../java/org/jpsx/runtime/util/CDUtil.java | 78 + .../java/org/jpsx/runtime/util/ClassUtil.java | 30 + .../java/org/jpsx/runtime/util/MiscUtil.java | 64 + .../java/org/jpsx/runtime/util/Timing.java | 28 + 109 files changed, 41703 insertions(+) create mode 100644 src/api/pom.xml create mode 100644 src/api/src/main/java/org/jpsx/api/CPUControl.java create mode 100644 src/api/src/main/java/org/jpsx/api/CPUListener.java create mode 100644 src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java create mode 100644 src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java create mode 100644 src/bootstrap/pom.xml create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java create mode 100644 src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java create mode 100644 src/lwjgl/pom.xml create mode 100644 src/lwjgl/src/main/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java create mode 100644 src/pom.xml create mode 100644 src/runtime/pom.xml create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/EmulationException.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/FinalComponentSettings.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/FinalResolvedConnectionCache.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/JPSXComponent.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/JPSXMachine.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/JPSXMachineImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/RuntimeConnections.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/SingletonJPSXComponent.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/CoreComponentConnections.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAControllerImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/DefaultQuartz.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQControllerImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQOwnerBase.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/MTScheduler.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/R3000Impl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/core/SCPImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Executable.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/CD.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/counters/Counters.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPU.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gte/GTE.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/SIO0.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/StandardController.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/SPU.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/util/ByteCodeUtil.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/util/CDUtil.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/util/ClassUtil.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/util/MiscUtil.java create mode 100644 src/runtime/src/main/java/org/jpsx/runtime/util/Timing.java diff --git a/src/api/pom.xml b/src/api/pom.xml new file mode 100644 index 0000000..4e1dc1f --- /dev/null +++ b/src/api/pom.xml @@ -0,0 +1,33 @@ + + + UTF-8 + 1.8 + 1.8 + + 4.0.0 + org.jpsx + api + jar + 1.0-SNAPSHOT + jpsx-api + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + + org.apache.bcel + bcel + 5.2 + + + + + jpsx-api + + diff --git a/src/api/src/main/java/org/jpsx/api/CPUControl.java b/src/api/src/main/java/org/jpsx/api/CPUControl.java new file mode 100644 index 0000000..8a72745 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/CPUControl.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api; + +/** + * This interface is used to control (asynchronously) the thread which processes R3000 instructions + */ +public interface CPUControl { + /** + * Cause the CPU to run until a breakpoint is hit, or {@link #step()} or {@link #pause()} are called + */ + void go(); + + /** + * Execute one CPU instruction and then pause + */ + void step(); + + /** + * Stop executing CPU instructions, until {@link #go()} or {@link #step()} are called + */ + void pause(); + + /** + * Add a breakpoint at the specified address in the PSX address space + * + * @param address + */ + void addBreakpoint(int address); + + /** + * Remove a breakpoint at the specified address in the PSX address space + * + * @param address + */ + void removeBreakpoint(int address); + + /** + * Return all the currently defined breakpoint addresses + * + * @return + */ + int[] getBreakpoints(); +} diff --git a/src/api/src/main/java/org/jpsx/api/CPUListener.java b/src/api/src/main/java/org/jpsx/api/CPUListener.java new file mode 100644 index 0000000..388d9ce --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/CPUListener.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api; + +/** + * Connection interface to be implemented by any component which cares when the CPU is paused or resumed in response + * to requests via the {@link CPUControl} interface. + */ +public interface CPUListener { + /** + * The CPU is starting to run again + */ + void cpuResumed(); + + /** + * The CPU has stopped running + */ + void cpuPaused(); +} diff --git a/src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java b/src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java new file mode 100644 index 0000000..33efc72 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api; + +public class InvalidConfigurationException extends RuntimeException { + public InvalidConfigurationException(String message) { + super(message); + } + + public InvalidConfigurationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java b/src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java new file mode 100644 index 0000000..c944e7f --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core; + +public class ContinueExecutionException extends RuntimeException { + private boolean skipCurrentInstruction; + + // static members used since exception creation is costly, and we don't care about stack traces in this case + public static final ContinueExecutionException SKIP_CURRENT = new ContinueExecutionException(true); + public static final ContinueExecutionException DONT_SKIP_CURRENT = new ContinueExecutionException(false); + + public ContinueExecutionException() { + this(false); + } + + public ContinueExecutionException(boolean skipCurrentInstruction) { + this.skipCurrentInstruction = skipCurrentInstruction; + } + + public boolean skipCurrentInstruction() { + return skipCurrentInstruction; + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java b/src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java new file mode 100644 index 0000000..a705aad --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java @@ -0,0 +1,4 @@ +package org.jpsx.api.components.core; + +public class ImmediateBreakoutException extends RuntimeException { +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java b/src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java new file mode 100644 index 0000000..5a7ad5d --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core; + +public final class ReturnFromExceptionException extends RuntimeException { + // static singleton used since exception creation is costly, and we don't care about stack traces in this case + public static final ReturnFromExceptionException INSTANCE = new ReturnFromExceptionException(); + + private ReturnFromExceptionException() { + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java new file mode 100644 index 0000000..07970f7 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.addressspace; + + +public interface AddressSpace { + // we use this when determining addresses as the offset from the prefix (top 16 bits)... + // this is because the 2M of ram should be repeated 4 times... since no other offsets are close to 2M big, this should be AOK + int OFFSET_MASK = 0x0f9fffff; + int RAM_AND = 0x5fffffff & OFFSET_MASK; // value to and main ram address with to make it map to array index*4 (or invalid) + + int SCRATCH_XOR = 0x1f800000; // value to xor scratch address with to make it map to array index*4 (or invalid) + int BIOS_XOR = 0xbfc00000; // value to xor bios address with to make it map to array index*4 (or invalid) + + int RAM_SIZE = 2 * 1024 * 1024; + + int SCRATCH_BASE = 0x1f800000; + int SCRATCH_SIZE = 0x1000; + int SCRATCH_END = SCRATCH_BASE + SCRATCH_SIZE; + + int PAR_BASE = 0x1f000000; + int PAR_SIZE = 0x10000; + int PAR_END = PAR_BASE + PAR_SIZE; + + int HW_BASE = 0x1f801000; + int HW_SIZE = 0x2000; + int HW_END = HW_BASE + HW_SIZE; + + int BIOS_BASE = 0xBFC00000; + int BIOS_SIZE = 0x80000; + int BIOS_END = BIOS_BASE + BIOS_SIZE; + + // Markers for the type of RAM access that an instruction at a particular addresses does + byte TAG_RAM = 0x01; + byte TAG_SCRATCH = 0x02; + byte TAG_HW = 0x04; + byte TAG_BIOS = 0x08; + byte TAG_PAR = 0x10; + byte TAG_POLL = 0x20; // polling detected at this address + byte TAG_RESERVED_FOR_COMPILER = 0x40; // our compiler happens to need a bit + byte TAG_RESERVED_FOR_COMPILER_2 = -0x80; // our compiler happens to need a bit + + public static class Util { + public static boolean isBIOS(int address) { + return address >= BIOS_BASE && address < BIOS_END; + } + } + + // read or write from RAM without any side effects (e.g. hardware IO) + int internalRead32(int address); + void internalWrite32(int address, int value); + + int read8(int address); + int read16(int address); + int read32(int address); + + void write8(int address, int value); + void write16(int address, int value); + void write32(int address, int value); + + /** + * Called by the SCP to enable/disable writing to RAM + * @param enable + */ + void enableMemoryWrite(boolean enable); + + byte getTag(int pc); + + void orTag(int pc, byte val); + + /** + * Return the array and index in a ResolveResult based on a given address + * @param address + * @param result the resolved address information or null if the address is not backed + */ + void resolve(int address, ResolveResult result); + + /** + * Return the array and index in a ResolveResult based on a given address, + * ensuring that both the address & address + size fall within the same memory + * region + * @param address base address + * @param size size in bytes + * @param write true if this is for write access, false for read + * @param result the resolved address information or null if the full address range is not backed + */ + void resolve(int address, int size, boolean write, ResolveResult result); + + /** + * todo we should allow the address space to return null here if it doesn't want to allow direct access + * @return the main RAM array to allow for direct access by other components + */ + int[] getMainRAM(); + + void tagAddressAccessWrite(int pc, int address); + + void tagAddressAccessRead8(int pc, int address); + + void tagAddressAccessRead16(int pc, int address); + + void tagAddressAccessRead32(int pc, int address); + + void tagClearPollCounters(); + + /** + * Private interface of static methods for use by compiler are on this class... this is not a full level + * abstraction, but makes it easier to replace the AddressSpaceImpl with a subclass + * + * This can return null if none is provided, though the MultiStageCompiler currently requires it + */ + public String getMainStaticInterfaceClassName(); + + + /** + * Private interface of static methods for use by compiler are on this class... this is not a full level + * abstraction, but makes it easier to replace the AddressSpaceImpl with a subclass + * + * This can return null if none is provided, though the MultiStageCompiler currently requires it + */ + public String getHardwareStaticInterfaceClassName(); + + static class ResolveResult { + public int address; // the original address + public int[] mem; + public int offset; + public int low2; + public byte tag; + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java new file mode 100644 index 0000000..e7f946c --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.addressspace; + +public interface AddressSpaceListener { + public void cacheCleared(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java new file mode 100644 index 0000000..f6d19bb --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.addressspace; + +public interface AddressSpaceRegistrar { + void registerRead8Callback(int address, Class clazz, String methodName); + + void registerRead16Callback(int address, Class clazz, String methodName); + + void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead); + + void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead); + + void registerRead32Callback(int address, Class clazz, String methodName); + + void registerWrite8Callback(int address, Class clazz, String methodName); + + void registerWrite16Callback(int address, Class clazz, String methodName); + + void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite); + + void registerWrite32Callback(int address, Class clazz, String methodName); + + void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite); + + void registerPoll32Callback(int address, Pollable pollable); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java new file mode 100644 index 0000000..d0542a3 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.addressspace; + +import org.jpsx.api.InvalidConfigurationException; + +public interface MemoryMapped { + /** + * Method invoked by the address space during initialization. + *

+ * A memory mapped implementation should register its addresses with the address space at this time + */ + public void registerAddresses(AddressSpaceRegistrar registrar) throws InvalidConfigurationException; +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java new file mode 100644 index 0000000..27b71df --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.addressspace; + +public interface Pollable { + public void poll(int address, int size); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java new file mode 100644 index 0000000..12c7cd3 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +import org.apache.bcel.generic.InstructionList; + +public class CPUInstruction { + /** + * any branch instruction + */ + public static final int FLAG_BRANCH = 0x00000001; + + /** + * for use if a branch is always taken + */ + public static final int FLAG_UNCONDITIONAL = 0x00000002; + /** + * for branch with an immediate relative offset + */ + public static final int FLAG_IMM_NEAR_TARGET = 0x00000004; + /** + * for branch with an immediate absolute offset + */ + public static final int FLAG_IMM_FAR_TARGET = 0x00000008; + /** + * for branch which links return address in R31 + */ + public static final int FLAG_LINK = 0x00000010; + + /** + * instruction is depdendent only on immediate value and input register values, + * and the only side effect (other than exception) is a register value change. + *

+ * This is useful in compiler because if it can prove the input values are + * known at compile time, then it can invoke the {@link #simulate} method for the + * input to calculate the constant output. + */ + public static final int FLAG_SIMULATABLE = 0x00000020; + + /** + * what the instruction references + */ + public static final int FLAG_READS_RS = 0x00000100; + public static final int FLAG_READS_RT = 0x00000200; + public static final int FLAG_WRITES_RT = 0x00000400; + public static final int FLAG_WRITES_RD = 0x00000800; + + // all addresses are assumed to be of the form rs[offset] + public static final int FLAG_MEM8 = 0x00002000; + public static final int FLAG_MEM16 = 0x00004000; + public static final int FLAG_MEM32 = 0x00008000; + public static final int FLAG_MEM = (FLAG_MEM8 | FLAG_MEM16 | FLAG_MEM32); + + // the instruction may make use of reg_pc + public static final int FLAG_REFERENCES_PC = 0x00010000; + + // implicitly references pc + public static final int FLAG_MAY_RESTORE_INTERPRETER_STATE = 0x00020000; + public static final int FLAG_MAY_SIGNAL_EXCEPTION = FLAG_MAY_RESTORE_INTERPRETER_STATE; + + /** + * Applies only to the interpreted version of the function + */ + public static final int FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE = 0x00040000; + + public static final int FLAG_INVALID = 0x00080000; + + public static final int BRANCH_NEVER = 0; + public static final int BRANCH_SOMETIMES = 1; + public static final int BRANCH_ALWAYS = 2; + + private String name; + private Class interpreterClass; + private int flags; + + public CPUInstruction(String name, Class interpreterClass, int exceptions, int flags) { + this.interpreterClass = interpreterClass; + this.name = name; + this.flags = flags; + } + + public int getBranchType(int ci) { + if (0 != (flags & FLAG_BRANCH)) { + if (0 != (flags & FLAG_UNCONDITIONAL)) + return BRANCH_ALWAYS; + return BRANCH_SOMETIMES; + } + return BRANCH_NEVER; + } + + public String getName() { + return name; + } + + public Class getInterpreterClass() { + return interpreterClass; + } + + public CPUInstruction subDecode(int ci) { + return this; + } + + public final int getFlags() { + return flags; + } + + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + if (0 != (getFlags() & FLAG_BRANCH)) { + throw new IllegalStateException("default compiler may not be used for branch instructions: " + getName()); + } + context.emitInterpretedInstruction(il, ci, interpreterClass.getName(), getInterpretMethodName()); + } + + public boolean simulate(int ci, int[] regs) { + return false; + } + + public String getInterpretMethodName() { + return "interpret_" + getName(); + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java new file mode 100644 index 0000000..1ec55c1 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +/** + * A {@link CPUInstructionDisassembler} is capable of providing a string representation of an opcode + * for the purpose of disassembly. + *

+ * Implementors of this interface are registered during registration via + * {@link InstructionRegistrar#setInstructionDisassembler(String,CPUInstructionDisassembler)} + */ +public interface CPUInstructionDisassembler { + /** + * Return a string representing the disassembly of the instruction + * + * @param inst the decoded instruction resulting from the opcode ci + * @param address the address of the instruction + * @param ci the 32 bit opcode itself + * @return The String representation of the opcode, which by convention has the instruction name padded with spaces to 8 characters + * followed by any instruction arguments + */ + public String disassemble(CPUInstruction inst, int address, int ci); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java new file mode 100644 index 0000000..cc91226 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.InstructionHandle; +import org.apache.bcel.generic.InstructionList; + +public interface CompilationContext { + public int getRegValue(int reg); + + public int getConstantRegs(); + + public int getWritesReg(); + + public int getReadsReg(); + + public ConstantPoolGen getConstantPoolGen(); + + /** + * Call into the interpreted version of the instruction... the compiler + * is responsible for any marshalling of state on entry/exit + */ + public void emitInterpretedInstruction(InstructionList il, int ci, String clazz, String method); + + public void emitGetReg(InstructionList il, int reg); + + public void emitSetReg(InstructionList il, int reg); + + public void emitCall(InstructionList il, int address, int expectedReturnAddress); + + public void emitCall(InstructionList il, int expectedReturnAddress); + + public void emitJump(InstructionList il); + + public void emitJump(InstructionList il, int address); + + /** + * read from specified constant address + */ + public void emitReadMem8(InstructionList il, int address, boolean signed); + + /** + * read from base reg + offset + */ + public void emitReadMem8(InstructionList il, int reg, int offset); + + /** + * read from specified constant address + */ + public void emitReadMem16(InstructionList il, int address, boolean signed); + + /** + * read from base reg + offset + */ + public void emitReadMem16(InstructionList il, int reg, int offset); + + /** + * read from specified constant address + */ + public void emitReadMem32(InstructionList il, int address, boolean forceAlign); + + /** + * read from base reg + offset + */ + public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign); + + /** + * write value from stack(0) to specified address + */ + public void emitWriteMem8(InstructionList il, int address, InstructionList valueList); + + /** + * write value from stack(0) to base reg + offset + */ + public void emitWriteMem8(InstructionList il, int reg, int offset); + + /** + * write value from stack(0) to specified address + */ + public void emitWriteMem16(InstructionList il, int address, InstructionList valueList); + + /** + * write value from stack(0) to base reg + offset + */ + public void emitWriteMem16(InstructionList il, int reg, int offset); + + /** + * write value from stack(0) from address at stack(1) + */ + public void emitWriteMem32(InstructionList il, int address, InstructionList valueList, boolean forceAlign); + + /** + * write value from stack(0) to base reg + offset + */ + public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList valueList, boolean forceAlign); + + /** + * if this is a branch instruction then this would be the instructions + * for the delay slot + */ + public void emitDelaySlot(InstructionList il); + + public int getTempLocal(int index); + + public InstructionHandle getBranchTarget(int address); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java new file mode 100644 index 0000000..f410f5e --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +public interface InstructionProvider { + public void addInstructions(InstructionRegistrar registrar); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java new file mode 100644 index 0000000..56ba2b9 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +public interface InstructionRegistrar { + void setInstruction(int index, CPUInstruction inst); + + void setSPECIALInstruction(int index, CPUInstruction inst); + + void setREGIMMInstruction(int index, CPUInstruction inst); + + void setInstructionDisassembler(String name, CPUInstructionDisassembler disassembler); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java new file mode 100644 index 0000000..e062ece --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +/** + * Interface to be implemented by an instruction compiler. + *

+ * The compiler's job is to provide faster execution of R3000 + * code than is possible by simple instruction by instruction + * interpretation. + */ +public interface NativeCompiler { + + /** + * Enter compiler. + *

+ * This method is called by the interpreter for every interpreted JAL after + * the delay slot has been executed. i.e. address is the JAL target. + *

+ * The compiler may continue execution from this point if it is able to, or + * may ask the interpreter to continue (e.g. if methods are only compiled + * after a certain number of invocations). + *

+ * The compiler, if it decides to enter compiled code, should continue executing + * until the corresponding JR to the specified return address (i.e. return), or may throw a ContinueExecutionException + * if it needs to return execution flow to the interpreter for any other reason. + *

+ * Note, that the compiler may be entered recursively; e.g. once for main + * execution flow, and then later for an interrupt. + * + * @return true - if the compiler execute code until the "return" + * false - if the compiler did not execute any code. + * @throws org.jpsx.api.components.core.ContinueExecutionException + * if the compiler wishes the interpeter to take over execution + */ + public boolean jumpAndLink(int address, int returnAddress); + + /** + * Method called whenever the R3000 instruction cache is flushed. + * The compiler should assume that any instructions in RAM may have been + * modified + */ + public void clearCache(); + + /** + * Determine if a thrown exception is OK; some compilers + * may allow some exceptions e.g. NullPointerException in the normal + * course of operation, and use them when they occur to update compiled + * code. + *

+ * Note the compiler is responsible for restoring the interpreter state + * in either case. Note this method is also called for ReturnFromExceptionException + * and ContinueExecutionException to allow the compiler to know + * that it has been "thrown out of". + * + * @return true + * if the exception was handled by the compiler, and emulation should continue + * in the interpreter + */ + public boolean exceptionInCompiler(Throwable t); + + /** + * Called by the JPSX system if there is some interruption to execution + * flow that requires the compiler to return control temporarily. This + * includes, but is not limited to R3000 interrupts. + *

+ * The compiler should call {@link R3000#compilerInterrupted} from the execution + * thread as soon as possible. + *

+ * Note, this method is generally not called from the execution thread, though + * in some circumstances it could be. + *

+ * On return from {@link R3000#compilerInterrupted}, the compiler should be + * aware that clearCache() or restoreInterpreterState() may + * have been called in the meanwhile. + */ + public void interrupt(); + + /** + * Adds a breakpoint at the specified address. + *

+ * If the compiler is able to handle breakpoints it should make sure that the + * execution returns to the interpreter on or before this address + *

+ * The simplest implementation of this function would be to perform no + * compiled execution while there are any breakpoints set. + * + * @return true + * if the compiler will be able to handle the breakpoint + */ + public boolean addBreakpoint(int address); + + /** + * Removes the breakpoint from the specified address + */ + public void removeBreakpoint(int address); + + /** + * If the compiler is keeping any local copies + * of registers etc., it should restore them + * in response to this call + */ + public void restoreInterpreterState(); + + public int getReg(int index); + + public void setReg(int index, int value ); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java new file mode 100644 index 0000000..48aafbb --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +/** + * Connection interface to be implemented by components which care about poll-blocking + *

+ * Much PSX code sits in busy-wait loops waiting for memory or memory mapped IO locations to change + * as a result of asynchronous (perhaps interrupt) events.

+ *

+ * The core implementation of the emulator detects these busy waits, and will block instead on a java + * monitor.

+ *

+ * This interface enables components to know when this is about to happen + */ +public interface PollBlockListener { + /** + * Called when CPU busy-wait has been detected, and the processing thread is about to block. + *

+ * This is an indication that the CPU is effectively idle, and the component may choose + * to perform some idle processing. + */ + public void aboutToBlock(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java new file mode 100644 index 0000000..001f0f4 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +// not thread safe + +public interface R3000 { + /** + * Stack pointer register constant + */ + public static final int R_SP = 29; + /** + * Return address register constant + */ + public static final int R_RETADDR = 31; + + // todo document what it means to read a compiler reg here + int getReg(int index); + + // todo document what it means to write a compiler register here + void setReg(int index, int value); + + int getPC(); + + int getLO(); + + int getHI(); + + void setPC(int pc); + + void setLO(int lo); + + void setHI(int hi); + + /** + * Decode the given opcode into an emulator instruction instance + * + * @param ci the 32 bit opcode + * @return the instruction specified by the opcode. If the op code is invalid, then this method returns an instruction representing + * and invalid instruction rather than null + */ + CPUInstruction decodeInstruction(int ci); + + String disassemble(int address, int ci); + + /** + * Determine if the current thread is the CPU execution thread + */ + boolean isExecutionThread(); + + /** + * Called from a non execution thread to request a controlled break out to the main interpreter/control loop as soon as possible. + * Currently used for R3000 interrupt handling and external pausing/stepping etc. of the CPU + */ + void requestBreakout(); + + /** + * Called from the execution thread to request an immediate return to the interpreter/control loop - this can be called mid + * instruction and may have undesirable side effects (i.e. half executed instruction) + */ + void immediateBreakout(); + + void restoreInterpreterState(); + + void interpreterBranch(int relativeToDelay); + + void interpreterJump(int relativeToDelay, int target); + + void interpreterJumpAndLink(int relativeToDelay, int target, int retAddr); + + // todo should this be elsewhere + void compilerInterrupted(); + + /** + * @return the array of registers used during intrepreted code execution; this value should be immutable + */ + int[] getInterpreterRegs(); + + CPUInstruction getInvalidInstruction(); + + void executeFromPC(); + + public static class Util { + + public static int bits_rs(final int ci) { + return (ci >> 21) & 0x1f; + } + + public static int bits_rt(final int ci) { + return (ci >> 16) & 0x1f; + } + + public static int bits_rd(final int ci) { + return (ci >> 11) & 0x1f; + } + + public static int bits_sa(final int ci) { + return (ci >> 6) & 0x1f; + } + + public static int bits25_6(int x) { + return (x >> 6) & 0xfffff; + } + + public static int sign_extend(int x) { + return ((x) << 16) >> 16; + } + + public static int signed_branch_delta(int x) { + return sign_extend(x) << 2; + } + + public static int lo(int x) { + return x & 0xffff; + } + + public static long longFromUnsigned(int x) { + return ((long) x) & 0xffffffffL; + } + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java b/src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java new file mode 100644 index 0000000..ffdf553 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.cpu; + +/** + * Interface used by the core implementation to represent actions against the System Control Processor + */ +public interface SCP { + // R3000 exception constants; very few are actually used currently + public static final int EXCEPT_INTERRUPT = 0; + public static final int EXCEPT_TLB_MOD = 1; + public static final int EXCEPT_TLB_REFILL_L = 2; + public static final int EXCEPT_TLB_REFILL_S = 3; + public static final int EXCEPT_ADDRESS_ERROR_L = 4; // load/fetch + public static final int EXCEPT_ADDRESS_ERROR_S = 5; // store + public static final int EXCEPT_BUS_ERROR_I = 6; + public static final int EXCEPT_BUS_ERROR_D = 7; + public static final int EXCEPT_SYSCALL = 8; + public static final int EXCEPT_BREAKPOINT = 9; + public static final int EXCEPT_RESERVED_INSTRUCTION = 10; + public static final int EXCEPT_COPROCESSOR_UNUSABLE = 11; + public static final int EXCEPT_OVERFLOW = 12; + + void setInterruptLine(int line, boolean raised); + + void signalReservedInstructionException(); + + void signalIntegerOverflowException(); + + void signalBreakException(); + + void signalSyscallException(); + + void signalInterruptException(); + + boolean shouldInterrupt(); + + int currentExceptionType(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java b/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java new file mode 100644 index 0000000..f54ca27 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.dma; + +public interface DMAChannelOwner { + void register(DMAController controller); + + String getName(); + + int getDMAChannel(); + + void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl); + + void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl); + + void cancelDMATransfer(int ctrl); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java b/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java new file mode 100644 index 0000000..d8cd206 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.dma; + +public interface DMAController { + public static final int DMA_MDEC_IN = 0; + public static final int DMA_MDEC_OUT = 1; + public static final int DMA_GPU = 2; + public static final int DMA_CD = 3; + public static final int DMA_SPU = 4; + public static final int DMA_GPU_OTC = 6; + + void registerDMAChannel(DMAChannelOwner owner); + + void dmaChannelTransferComplete(DMAChannelOwner owner); + + void dmaChannelTransferComplete(DMAChannelOwner owner, boolean interrupt); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java b/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java new file mode 100644 index 0000000..c45f694 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.irq; + +public interface IRQController { + public static final int IRQ_VSYNC = 0; + public static final int IRQ_GPU = 1; + public static final int IRQ_CD = 2; + public static final int IRQ_DMA = 3; + public static final int IRQ_COUNTER0 = 4; + public static final int IRQ_COUNTER1 = 5; + public static final int IRQ_COUNTER2 = 6; + public static final int IRQ_SIO0 = 7; + + void registerIRQOwner(IRQOwner owner); + + // todo allow queue (some sort of delivery guarantee) + /** + * Raise the given IRQ; this method may be called from any thread + * + * @param irq + */ + void raiseIRQ(int irq); + + int getIRQRequest(); + + int getIRQMask(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java b/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java new file mode 100644 index 0000000..8622e8d --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.irq; + +public interface IRQOwner { + void register(IRQController controller); + + int getIRQ(); + + String getName(); + + void raiseIRQ(); + + void irqSet(); + + void irqCleared(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java new file mode 100644 index 0000000..88ecf1f --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.scheduler; + +/** + * A Quartz implementation is the basic internal timer in the JPSX system. + *

+ * Different implementations of {@link Quartz} may provide different granularities. Various + * components may require a certain level of granularity. + *

+ * This interface contains the methods not only to determine the current time value, but for components + * to negociate granularity, or indeed fail if the {@link Quartz} implementation does not provide + * the required level of granularity + */ +public interface Quartz { + /** + * The number of nano-seconds in a second + */ + public static final long SEC = 1000000000L; + /** + * The number of nano-seconds in a millisecond + */ + public static final long MSEC = 1000000L; + + /** + * Return the current value a nano counter which counts up from 0 when the machine starts (but only while the machine is not paused) + *

+ * The resolution of the nano time is undefined but should be accurate +/- the value from {@link #bestGranularity()} + */ + long nanoTime(); + + /** + * @return the estimated granularity of the time changes visible via {@link #nanoTime()} + */ + long bestGranularity(); + + /** + * Return the current value an arbitrary nano counter which counts up from 0 when the machine starts (but only while the machine is not paused) + *

+ * The resolution of the nano time should be accurate +/- the specified granularity value. + *

+ * The passed granularity should be greater than the value returned from {@link #bestGranularity()} + *

+ * This method is provided for use by callers who don't need insane accuracy in the hope that the implementation + * may be able to perform a less costly time calculation + * + * @param granularity the requested granularity + * @throw IllegalArgumentException if the granularity is more fine than that returned by {@link #bestGranularity} + */ + long nanoTime(long granularity); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java new file mode 100644 index 0000000..206c8af --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.scheduler; + +/** + * A scheduled action is registered with the {@link Scheduler} to be called back at a certain time. + *

+ * All implementors must be thread-safe since they may be called from any thread, and potentially simultaneously + * if the action is registered multiple times. + */ +public interface ScheduledAction { + /** + * @param currentTime + * @return the next time the action should be scheduled or 0 for no automatic re-scheduling + */ + long run(long currentTime); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java new file mode 100644 index 0000000..9cf59ab --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.core.scheduler; + +/** + * The scheduler is responsible for all real-time activity within the emulator. + *

+ * The actual implementation is also largely responsible for the threading mechanism used. + */ +public interface Scheduler { + /** + * Schedule an action to happen as soon as possible after the given time. For this method the definition of + * "as soon as possible" is left to the scheduler, but in general most implementations will probably not try + * to schedule with greater than 1ms accuracy.

+ *

+ * No actual guarantees are made about how soon the action will be called, so periodic actions that would + * usually re-schedule themselves every X nanoseconds, may want to take corrective action if they detect + * that they have been called back mutch later than expected.

+ *

+ * Actions scheduled in this manner should be as concise as possible, as all actions may be performed on + * one thread, and indeed that thread may be (but won't necessarily be) the R3000 cpu thread.

+ *

+ * If an action has long lasting work that it needs to do, it should delegate it to other worker threads + * + * @param time the time in nanoseconds since the start of the machine + * @param action the action to perform + */ + void schedule(long time, ScheduledAction action); + + /** + * Schedule an action to happen as soon as possible after the given time. For this method the definition of + * "as soon as possible" is specified to mean try your very best to get to schedule the action to happen between time + * and time+jitter. This method is useful if you really require very high frequency callbacks.

+ *

+ * No actual guarantees are made about how soon the action will be called, so periodic actions that would + * usually re-schedule themselves every X nanoseconds, may want to take corrective action if they detect + * that they have been called back mutch later than expected.

+ *

+ * Actions scheduled in this manner should be as concise as possible, as all actions may be performed on + * one thread, and indeed that thread may be (but won't necessarily be) the R3000 cpu thread.

+ *

+ * If an action has long lasting work that it needs to do, it should delegate it to other worker threads + * + * @param time the time in nanoseconds since the start of the machine + * @param action the action to perform + */ + void schedule(long time, long jitter, ScheduledAction action); + + /** + * Checks whether the action is currently scheduled. + *

+ * In this case scheduled means is either scheduled one or more times in the future, or is currently being called + * back. This latter behavior is useful if you have a repeating action which is only used some of the time. + * External (to the action) code can safely use this method to determine whether it should schedule the action itself + * + * @param action + * @return + */ + boolean isScheduled(ScheduledAction action); + + /** + * This method may be called by the cpu thread to indicate that it is in a busy-wait loop, and has no further useful + * work to do in the absence of some external force. + *

+ * This method will not return until {@link #cpuThreadNotify} is called. + *

+ * Note this is not necessarily implemented via Java monitors since the particular scheduler may be single-threaded + */ + void cpuThreadWait(); + + /** + * This method is generally called by {@link ScheduledAction scheduled actions} to indicate that they have performed + * some work which may potentially un-block the R3000 cpu thread. + *

+ * Note this is not necessarily implemented via Java monitors since the particular scheduler may be single-threaded + */ + void cpuThreadNotify(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java new file mode 100644 index 0000000..067f8a5 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.cd; + +public interface CDAudioSink { + + public int getCDAudioLatency(); + + public void setCDAudioRate(int hz); + + public void newCDAudio(); + + /** + * Handle CD Audio data in 2 channel 16 bit sigend little endian format + * + * @param data + * @return true if the audio is now playing + */ + public boolean cdAudioData(byte[] data, int offset, int length); + + public void setExternalCDAudioVolumeLeft(int vol); + + public void setExternalCDAudioVolumeRight(int vol); + + public boolean isCDAudible(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java new file mode 100644 index 0000000..3bd60ce --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.cd; + +/** + * TODO FIX THIS UP - also, read game title etc. media changed etc... + * support "changing" media + */ +public interface CDDrive { + + /** + * @return the current CDMedia or null if there is none present + */ + public CDMedia getCurrentMedia(); + + public void refreshMedia(); + + public boolean isDriveOpen(); +} + diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java new file mode 100644 index 0000000..4550b22 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.cd; + +public interface CDMedia { + public enum TrackType { + UNKNOWN, MODE2_2352, AUDIO + } + + int getFirstTrack(); + + int getLastTrack(); + + int getTrackMSF(int track); + + TrackType getTrackType(int track); + + void readSector(int sectorNumber, byte[] buffer) throws MediaException; + + /** + * @param num + * @param buffer + * @throws MediaException + * @deprecated just for use of old cd stuff + */ + void readSector(int num, int[] buffer) throws MediaException; +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java new file mode 100644 index 0000000..b305c9a --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.cd; + +public class MediaException extends Exception { + public MediaException(String message) { + super(message); + } + + public MediaException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java b/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java new file mode 100644 index 0000000..293d69e --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.gpu; + +public interface Display { + /** + * initialize the display + */ + public void initDisplay(); + + // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU); + public int[] acquireDisplayBuffer(); + + public void releaseDisplayBuffer(); + + public void refresh(); +} + + + diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java b/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java new file mode 100644 index 0000000..415b5a1 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.gpu; + +public interface DisplayManager { + boolean getInterlaceField(); + + boolean getNTSC(); + + boolean getInterlaced(); + + boolean getDoubleY(); + + boolean getRGB24(); + + boolean getBlanked(); + + int getDefaultPixelWidth(); + + int getDefaultPixelHeight(); + + int getPixelWidth(); + + int getPixelHeight(); + + int getXOrigin(); + + int getYOrigin(); + + int getLeftMarginPixels(); + + int getRightMarginPixels(); + + int getTopMarginPixels(); + + int getBottomMarginPixels(); + + void preAsync(); + + // called if a vsync has passed to make sure display is updated if necessary + // (e.g. drawing to display)... usually this does nothing, because setOrigin + // updates display if necessary + void vsync(); + + void setOrigin(int x, int y); + + void toggleInterlaceField();// mark a display area as changed... if it intersects the next + + // display region, then we will get an update at the next vsync, or + // display origin change + void dirtyRectangle(int x, int y, int w, int h); + + void setPixelDivider(int divider); + + void setNTSC(boolean NTSC); + + void setInterlaced(boolean interlaced); + + void setDoubleY(boolean doubleY); + + void setRGB24(boolean rgb24); + + void setBlanked(boolean blanked); + + void setHorizontalTiming(int hStart, int hEnd); + + void setVerticalTiming(int vStart, int vEnd); + + int getDefaultTimingWidth(); + + int getDefaultTimingHeight(); + + int getLeftMargin(); + + int getRightMargin(); + + int getTopMargin(); + + int getBottomMargin(); + +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java b/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java new file mode 100644 index 0000000..6bbf590 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.sio; + +public interface SerialDevice { + public void prepareForTransfer(); + + public void send(int data); + + public int receive(); + + public String getDescription(); +} diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java b/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java new file mode 100644 index 0000000..ade6403 --- /dev/null +++ b/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.api.components.hardware.sio; + +public interface SerialPort { + public void connect(SerialDevice device); + + public void disconnect(); +} diff --git a/src/bootstrap/pom.xml b/src/bootstrap/pom.xml new file mode 100644 index 0000000..37f1130 --- /dev/null +++ b/src/bootstrap/pom.xml @@ -0,0 +1,44 @@ + + + UTF-8 + 1.8 + 1.8 + + 4.0.0 + org.jpsx + bootstrap + jar + 1.0-SNAPSHOT + jpsx-bootstrap + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + org.jpsx + api + 1.0-SNAPSHOT + + + + log4j + log4j + 1.2.13 + + + + org.apache.bcel + bcel + 5.2 + + + + + + + diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java new file mode 100644 index 0000000..c48d789 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ + +package org.jpsx.bootstrap; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.classloader.JPSXClassLoader; +import org.jpsx.bootstrap.configuration.MachineDefinition; +import org.jpsx.bootstrap.configuration.XMLMachineDefinitionParser; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.awt.*; + +/** + * Bootstrap for JPSX - simply runs JPSXSystem in the {@link JPSXClassLoader} + */ +public class JPSXLauncher { + private static final Logger log = Logger.getLogger("Bootstrap"); + + public static void main(String args[]) { + // fix for Mac OSX which requires that we load AWT in the main classloader + new Frame(); + + Properties vars = new Properties(); + String configFile = "jpsx.xml"; + String machineId = "default"; + String log4jFile = "log4j.properties"; + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-config")) { + if (i == args.length - 1) { + usage(); + return; + } + configFile = args[++i]; + } else if (args[i].equals("-log")) { + if (i == args.length - 1) { + usage(); + return; + } + log4jFile = args[++i]; + } else if (args[i].indexOf("=") > 0) { + int split = args[i].indexOf("="); + vars.put(args[i].substring(0, split), args[i].substring(split + 1)); + } else if (args[i].equals("-?")) { + usage(); + return; + } else { + machineId = args[i]; + } + } + + // init log4j + PropertyConfigurator.configure(log4jFile); + + log.info("configFile=" + configFile + " machineId=" + machineId); + Element config; + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + config = builder.parse(new File(configFile)).getDocumentElement(); + } catch (IOException e) { + log.error("Cannot open/read '" + configFile + "'", e); + return; + } catch (Exception e) { + log.error("Cannot parse '" + configFile + "'", e); + return; + } + + try { + MachineDefinition machineDefinition = new XMLMachineDefinitionParser().parse(config, machineId, vars); + JPSXMachineLifecycle machine = JPSXClassLoader.newMachine(JPSXLauncher.class.getClassLoader(), machineDefinition); + machine.start(); + } catch (InvalidConfigurationException e) { + log.error("Invalid Configuration", e); + } catch (Throwable t) { + log.error("Unexpected error", t); + } + } + + private static void usage() { + System.err.println("Usage: JPSXLauncher (-log ) (-config ) () (var=value)*\n" + + " The default log4j properties file is 'log4j.properties'\n" + + " The default xmlfile is 'jpsx.xml'\n" + + " The default machineId is 'default'"); + } +} + diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java new file mode 100644 index 0000000..086ccc2 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.classloader.JPSXClassLoader; +import org.jpsx.bootstrap.configuration.MachineDefinition; +import org.jpsx.bootstrap.configuration.XMLMachineDefinitionParser; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.awt.*; + +/** + * Bootstrap for JPSX - simply runs JPSXSystem in the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} + * + * THIS IS JUST A TEST CLASS THAT RUNS 3 GAMES IN THE SAME VM ON MY MACHINE!!! + */ +public class JPSXLauncher2 { + private static final Logger log = Logger.getLogger("Bootstrap"); + + private static final String JPSX_MACHINE_CLASS = "org.jpsx.runtime.JPSXMachineImpl"; + + public static void main(String args[]) { + // fix for Mac OSX which requires that we load AWT in the main classloader + new Frame(); + + final Properties vars = new Properties(); + String configFile = "jpsx.xml"; + String machineId = "default"; + String log4jFile = "log4j.properties"; + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-config")) { + if (i == args.length - 1) { + usage(); + return; + } + configFile = args[++i]; + } else if (args[i].equals("-log")) { + if (i == args.length - 1) { + usage(); + return; + } + log4jFile = args[++i]; + } else if (args[i].indexOf("=") > 0) { + int split = args[i].indexOf("="); + vars.put(args[i].substring(0, split), args[i].substring(split + 1)); + } else if (args[i].equals("-?")) { + usage(); + return; + } else { + machineId = args[i]; + } + } + + // init log4j + PropertyConfigurator.configure(log4jFile); + + new Thread(new Runnable() { + public void run() { + runMachine("jpsx.xml", "abe", new Properties(vars)); + } + }).start(); + new Thread(new Runnable() { + public void run() { + runMachine("jpsx.xml", "bandicoot", new Properties(vars)); + } + }).start(); + runMachine(configFile, machineId, vars); + } + + private static void runMachine(String configFile, String machineId, Properties vars) { + log.info("configFile=" + configFile + " machineId=" + machineId); + Element config; + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + config = builder.parse(new File(configFile)).getDocumentElement(); + } catch (IOException e) { + log.error("Cannot open/read '" + configFile + "'", e); + return; + } catch (Exception e) { + log.error("Cannot parse '" + configFile + "'", e); + return; + } + + try { + MachineDefinition machineDefinition = new XMLMachineDefinitionParser().parse(config, machineId, vars); + JPSXMachineLifecycle machine = JPSXClassLoader.newMachine(JPSXLauncher2.class.getClassLoader(), machineDefinition); + machine.start(); + } catch (InvalidConfigurationException e) { + log.error("Invalid Configuration", e); + } catch (Throwable t) { + log.error("Unexpected error", t); + } + } + + private static void usage() { + System.err.println("Usage: JPSXLauncher (-log ) (-config ) () (var=value)*\n" + + " The default log4j properties file is 'log4j.properties'\n" + + " The default xmlfile is 'jpsx.xml'\n" + + " The default machineId is 'default'"); + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java new file mode 100644 index 0000000..0f6965f --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap; + +import org.jpsx.bootstrap.configuration.MachineDefinition; + +public interface JPSXMachineLifecycle { + void initialize(MachineDefinition definition); + + void start(); + + void close(); +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java new file mode 100644 index 0000000..f562850 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.classloader; + +import org.apache.bcel.generic.ClassGen; + +public interface ClassGenerator { + /** + * @param classname the full classname of the class being loaded + * @return the generated version of the class + */ + public ClassGen generateClass(String classname ); +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java new file mode 100644 index 0000000..f30094d --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.classloader; + +import org.apache.bcel.generic.ClassGen; + +public interface ClassModifier { + /** + */ + public ClassGen modifyClass(String classname, ClassGen original); +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java new file mode 100644 index 0000000..3443b47 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.classloader; + +import org.apache.bcel.classfile.ClassParser; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.ClassGen; +import org.apache.bcel.generic.InstructionList; +import org.apache.bcel.generic.MethodGen; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.JPSXMachineLifecycle; +import org.jpsx.bootstrap.configuration.MachineDefinition; +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +// todo wildcard rather than prefix for modifiers/generators +// todo class modifiers + +/** + * JPSX ClassLoader. + *

+ * This classloader relies on its parent classloader + * for getting RAW .class data, but it does not + * necessarily follow the Java 2 delegation model. + *

+ * All JPSX classes should be loaded by this classloader + * instead, since they mey reference other classes which + * need to be modified before they are defined. + *

+ * Therefore this class recognizes certain package + * prefixes as JPSX classes + */ + +// todo multiple modifiers? + +public class JPSXClassLoader extends ClassLoader { + public static final boolean dumpClasses = false; + private static final String JPSX_MACHINE_CLASS = "org.jpsx.runtime.JPSXMachineImpl"; + + private static int BUFFER_SIZE = 8192; + + private final List generatorClassnamePrefixes = CollectionsFactory.newArrayList(); + private final List generators = CollectionsFactory.newArrayList(); + private final List modifierClassnamePrefixes = CollectionsFactory.newArrayList(); + private final List modifiers = CollectionsFactory.newArrayList(); + private final Set jpsxClassnamePrefixes = CollectionsFactory.newHashSet(); + + private JPSXClassLoader(ClassLoader parent, MachineDefinition machineDefinition) { + super(parent); + jpsxClassnamePrefixes.add("org.jpsx.runtime"); + jpsxClassnamePrefixes.addAll(machineDefinition.getClassNamePrefixes()); + } + + public static JPSXMachineLifecycle newMachine(ClassLoader parent, MachineDefinition machineDefinition) throws InvalidConfigurationException { + // each machine needs to have its own classloader instance + JPSXClassLoader loader = new JPSXClassLoader(parent, machineDefinition); + try { + Class clazz = Class.forName(JPSX_MACHINE_CLASS, true, loader); + JPSXMachineLifecycle rc = (JPSXMachineLifecycle) clazz.newInstance(); + rc.initialize(machineDefinition); + return rc; + } catch (Exception e) { + throw new InvalidConfigurationException("Failed to create machine instance", e); + } + } + + private int prefixIndex(Collection prefixes, String name) { + int i = 0; + for (String prefix : prefixes) { + if (name.startsWith(prefix)) { + return i; + } + i++; + } + return -1; + } + + public static void registerClassGenerator(String classnamePrefix, ClassGenerator generator) { + JPSXClassLoader instance = getLoaderInstance(generator); + instance.generatorClassnamePrefixes.add(classnamePrefix); + instance.generators.add(generator); + } + + public static void registerClassModifier(String classnamePrefix, ClassModifier modifier) { + JPSXClassLoader instance = getLoaderInstance(modifier); + instance.modifierClassnamePrefixes.add(classnamePrefix); + instance.modifiers.add(modifier); + } + + private static JPSXClassLoader getLoaderInstance(Object obj) { + ClassLoader loader = obj.getClass().getClassLoader(); + assert (loader != null && (loader instanceof JPSXClassLoader)) : obj + " was not loaded by JPSXClassLoader"; + return (JPSXClassLoader) loader; + } + + /** + * Utility method to define a class from a stream of bytes + * + * @param stream the stream containing the binary class data + * @param classname the class name for the class + */ + private Class getClassFromStream(InputStream stream, String classname) + throws IOException { + // read the stream into a byte array + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[BUFFER_SIZE]; + + int bytesRead; + while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) { + baos.write(buffer, 0, bytesRead); + } + + byte[] classData = baos.toByteArray(); + + // and define the class using our protection domain + return defineClass(classname, classData, 0, classData.length, null); + } + + /** + * Override of the standard loadClass method to allow for class duplication. + *

+ * If we determine that we should duplicate the class then we do so, otherwise + * we invoke the superclasses' method which follows the standard Java 2 delegation + * model + */ + public synchronized Class loadClass(final String name, boolean resolve) throws ClassNotFoundException { + // make sure we haven't defined it already + Class c = findLoadedClass(name); + if (c == null) { + //System.out.println( "load class "+name); + if (-1 != prefixIndex(jpsxClassnamePrefixes, name)) { + c = makeClass(name); + } else { + return super.loadClass(name, resolve); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + + private Class makeClass(final String name) throws ClassNotFoundException { + ClassGen cgen = null; + + int genIndex = prefixIndex(generatorClassnamePrefixes, name); + int modIndex = prefixIndex(modifierClassnamePrefixes, name); + + if (genIndex != -1) { + //System.out.println("generating class "+name); + cgen = generators.get(genIndex).generateClass(name); + } else { + // make the ClassGen from the raw data from our parent loader + final URL url = getResource(getClassFilename(name)); + if (url != null) { + try { + InputStream stream = url.openStream(); + if (modIndex == -1) { + //System.out.println("copying parent class "+name); + return getClassFromStream(stream, name); + } else { + cgen = new ClassGen((new ClassParser(stream, getClassFilename(name))).parse()); + } + } catch (IOException e) { + // will cause a class not found exception later + } + } + } + if (cgen != null && modIndex != -1) { + //System.out.println("modifying class "+name); + // modify the class if needed + cgen = modifiers.get(modIndex).modifyClass(name, cgen); + } + + if (cgen == null) { + throw new ClassNotFoundException(name); + } + + JavaClass jclass = cgen.getJavaClass(); + + if (dumpClasses) { + try { + jclass.dump("modified_" + name + ".class"); + } catch (IOException e) { + } + } + + byte[] classData = jclass.getBytes(); + return defineClass(name, classData, 0, classData.length, null); + } + + public static MethodGen emptyMethod(ClassGen cgen, Method m) { + MethodGen mg = new MethodGen(m, cgen.getClassName(), cgen.getConstantPool()); + return new MethodGen(mg.getAccessFlags(), + mg.getReturnType(), + mg.getArgumentTypes(), + mg.getArgumentNames(), + mg.getName(), + mg.getClassName(), + new InstructionList(), + mg.getConstantPool()); + } + + /** + * Utility method to convert class name to filename + */ + public static String getClassFilename(String classname) { + return classname.replace('.', '/') + ".class"; + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java new file mode 100644 index 0000000..03f0caf --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.configuration; + +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.util.Map; + +public class ComponentDefinition { + private final String className; + private final Map properties = CollectionsFactory.newHashMap(); + + public ComponentDefinition(String className) { + this.className = className; + } + + public void setProperty(String property, String value) { + properties.put(property, value); + } + + public String getClassName() { + return className; + } + + public Map getProperties() { + return properties; + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java new file mode 100644 index 0000000..52b8683 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.configuration; + +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.util.Collections; +import java.util.List; + +/** + * A machine definition is just the in memory representation of the ordered + * list of component that make up the machine. + * + * Each component is described by a {@link ComponentDefinition}

+ * + * An instance of this class is the raw input used by the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} to construct a new machine, + * however instances of this class may be built from another source (e.g. {@link XMLMachineDefinitionParser})

+ * + * In addition to defining the components, the machine definition also includes the class name prefixes that the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} + * should consider to be part of machine runtime. All runtime classes should be loaded by the {@link org.jpsx.bootstrap.classloader.JPSXClassLoader} instead of the + * usual class loader, such that code modification/generation and multiple machine instances work correctly. + */ +public class MachineDefinition { + private final List components = CollectionsFactory.newArrayList(); + private final List classNamePrefixes = CollectionsFactory.newArrayList(); + + public void addComponent(ComponentDefinition definition) { + components.add(definition); + } + + public void removeComponent(ComponentDefinition definition) { + components.remove(definition); + } + + public List getComponents() { + return Collections.unmodifiableList(components); + } + + /** + * Add a class prefix to the list of prefixes of classes which are part of the machine runtime + * @param classPrefix A string which is compared with fully qualified classname, so "com.fo" would be a prefix match "com.foo.Foo" + */ + public void addClassPrefix(String classPrefix) { + classNamePrefixes.add(classPrefix); + } + + public List getClassNamePrefixes() { + return Collections.unmodifiableList(classNamePrefixes); + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java new file mode 100644 index 0000000..1271d63 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.configuration; + +import org.apache.log4j.Logger; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.util.Map; +import java.util.Properties; + +public class XMLMachineDefinitionParser { + public static final String CATEGORY = "XML-Config"; + private static Logger log = Logger.getLogger(CATEGORY); + + public static final String ROOT_ELEMENT = "jpsx"; + public static final String MACHINE_ELEMENT = "machine"; + public static final String MACHINE_ID_ATTRIBUTE = "id"; + public static final String COMPONENT_ELEMENT = "component"; + public static final String COMPONENT_ID_ATTRIBUTE = "id"; + public static final String COMPONENT_CLASS_NAME_ATTRIBUTE = "classname"; + public static final String COMPONENT_SET_ELEMENT = "components"; + public static final String COMPONENT_SET_ID_ATTRIBUTE = "id"; + public static final String INCLUDE_ELEMENT = "include"; + public static final String INCLUDE_REF_ID_ATTRIBUTE = "refid"; + public static final String VAR_ELEMENT = "var"; + public static final String VAR_NAME_ATTRIBUTE = "name"; + public static final String VAR_VALUE_ATTRIBUTE = "value"; + public static final String PROPERTY_ELEMENT = "property"; + public static final String PROPERTY_NAME_ATTRIBUTE = "name"; + public static final String PROPERTY_VALUE_ATTRIBUTE = "value"; + + private Properties vars; + /** + * Map from id to component for those components which have ids. + */ + private Map componentsById; + private XPath xPath = XPathFactory.newInstance().newXPath(); + private Element rootElement; + + public MachineDefinition parse(Element element, String machineId, Properties vars) throws InvalidConfigurationException { + MachineDefinition rc = new MachineDefinition(); + + componentsById = CollectionsFactory.newHashMap(); + rootElement = getUniqueElement(element, "/" + ROOT_ELEMENT, "root element"); + this.vars = vars; + + Element machineElement = getUniqueElement(rootElement, MACHINE_ELEMENT + "[@" + MACHINE_ID_ATTRIBUTE + "='" + machineId + "']", "machine with id " + machineId); + parseComponents(rc, machineElement); + return rc; + } + + private void parseComponents(MachineDefinition machine, Element containerElement) { + NodeList nodes = containerElement.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node instanceof Element) { + Element element = (Element) nodes.item(i); + if (element.getTagName().equals(COMPONENT_ELEMENT)) { + parseComponentElement(machine, element); + } else if (element.getTagName().equals(INCLUDE_ELEMENT)) { + String id = element.getAttribute(INCLUDE_REF_ID_ATTRIBUTE); + id = resolveVariables(id); + Element refElement = getUniqueElement( + rootElement, + COMPONENT_ELEMENT + "[@" + COMPONENT_ID_ATTRIBUTE + "='" + id + "']|" + COMPONENT_SET_ELEMENT + "[@" + COMPONENT_SET_ID_ATTRIBUTE + "='" + id + "']", + "referenced component/nodes with id " + id); + if (refElement.getTagName().equals(COMPONENT_ELEMENT)) { + parseComponentElement(machine, refElement); + } else { + parseComponents(machine, refElement); + } + } else if (element.getTagName().equals(VAR_ELEMENT)) { + String name = element.getAttribute(VAR_NAME_ATTRIBUTE); + String value = element.getAttribute(VAR_VALUE_ATTRIBUTE); + if (!name.equals("")) { + value = resolveVariables(value); + if (value.equals("")) vars.remove(name); + else vars.setProperty(name, value); + } + } else { + throw new InvalidConfigurationException("Unexpected element " + element.getTagName()); + } + } + } + } + + private void parseComponentElement(MachineDefinition machine, Element componentElement) { + String id = componentElement.hasAttribute(COMPONENT_ID_ATTRIBUTE) ? componentElement.getAttribute(COMPONENT_ID_ATTRIBUTE) : null; + String className = componentElement.getAttribute(COMPONENT_CLASS_NAME_ATTRIBUTE); + + if (className.equals("")) { + throw new InvalidConfigurationException("Machine has component (id=" + id + ") with no className"); + } + + ComponentDefinition component = addComponent(machine, id, componentElement.getAttribute(COMPONENT_CLASS_NAME_ATTRIBUTE)); + parseConfiguration(component, componentElement); + } + + /** + * Handle xml configuration for this component; note this should not have actual + * side effects other than recording the information. This method is called before init + *

+ * This implementation looks for <property name="" value=""/> elements and adds + * them to the properties collection. + *

+ * Subclasses may override this method to parse other configuration data + * + * @param element + */ + private void parseConfiguration(ComponentDefinition component, Element element) { + NodeList nodes = element.getElementsByTagName(PROPERTY_ELEMENT); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node instanceof Element) { + Element prop = (Element) node; + if (prop.hasAttribute(PROPERTY_NAME_ATTRIBUTE) && prop.hasAttribute(PROPERTY_VALUE_ATTRIBUTE)) { + String value = prop.getAttribute(PROPERTY_VALUE_ATTRIBUTE); + value = resolveVariables(value); + if (!value.equals("")) { + component.setProperty(prop.getAttribute(PROPERTY_NAME_ATTRIBUTE), value); + } + } + } + } + } + + private Element getUniqueElement(Element context, String path, String description) { + NodeList nodes; + try { + nodes = (NodeList) xPath.evaluate(path, context, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + throw new InvalidConfigurationException("XPath Error", e); + } + if (nodes == null || nodes.getLength() == 0) { + throw new InvalidConfigurationException("Can't find: " + description); + } + if (nodes.getLength() > 1) { + log.warn("More than one node found for search: " + description); + } + Node node = nodes.item(0); + if (node instanceof Element) { + return (Element) node; + } + throw new InvalidConfigurationException("Match for '" + description + "' was not an element"); + } + + /** + * Substitutes any variables for ${varname} + * + * @param value + * @return the value with substitutions + */ + public String resolveVariables(String value) { + StringBuffer rc = new StringBuffer(); + int index = 0; + while (true) { + int start = value.indexOf("${", index); + if (start == -1) break; + int end = value.indexOf("}"); + if (end == -1) break; + rc.append(value.substring(index, start)); + String varName = value.substring(start + 2, end); + String varValue = getVariable(varName); + if (varValue != null) { + rc.append(varValue); + } + index = end + 1; + } + rc.append(value.substring(index)); + return rc.toString(); + } + + public String getVariable(String name) { + return vars.getProperty(name); + } + + public ComponentDefinition addComponent(MachineDefinition machine, String id, String className) { + ComponentDefinition component = new ComponentDefinition(className); + if (id != null) { + ComponentDefinition oldComponent = componentsById.get(id); + if (oldComponent != null) { + machine.removeComponent(oldComponent); + } + componentsById.put(id, component); + } + machine.addComponent(component); + return component; + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java new file mode 100644 index 0000000..141ffec --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ + +package org.jpsx.bootstrap.connection; + +import java.util.Set; + +/** + * A {@link Connection} object provides a lazily bound connection to one or more implementors + * of a particular interface.

+ *

+ * The client need not know who is on the other end of the connection; indeed the various sub-classes + * of this class, provide the targets with a way to register themselves with a particular connection instance.

+ *

+ * The client can connect to the target(s) by calling {@link #resolve()} which returns an implementor of the parametric type which + * connects to the targets. Note this method will throw an exception if there is no target.

+ *

+ * The connection also has an open flag, which indicates whether the connection is open. It should not be + * possible to use the the connection (via the implementation returned by {@link #resolve()}) when the connection is closed;

+ *

+ * The typical usage pattern is to place an instance of a connection in a class shareable by two otherwise unrelated classes, + * and one class can become the target of the connection and the other the client without them knowing anything else about eachother. + * + * @see SimpleConnection + * @see MultipleConnection + */ +public abstract class Connection { + /** + * Flags for the base connection or any well known subclasses + */ + enum Flags { + InitiallyClosed + } + + /** + * Name of the connection + */ + private final String name; + + /** + * the callbable interface implemented by the return value from {@link #resolve()} + */ + private final Class ifc; + + /** + * true if the connection accepts calls + */ + private boolean open; + + // the dispatcher object should cease to work if the connection is closed + // this is useful for connections which should only work at certain phases. + + protected Connection(String name, Class ifc, Set flags) { + if (!ifc.isInterface()) throw new IllegalArgumentException("ifc must be an interface"); + this.name = name; + this.ifc = ifc; + if (!flags.contains(Flags.InitiallyClosed)) { + open = true; + } + } + + public String getName() { + return name; + } + + public final Class getInterface() { + return ifc; + } + + public final boolean isOpen() { + return open; + } + + public void open() { + assert !this.open; + this.open = true; + } + + // todo flag for only open once + public void close() { + assert open; + open = false; + } + + /** + * Return an implementation which acts as the conduit between caller and callees + */ + public abstract I resolve(); +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java new file mode 100644 index 0000000..3fd313d --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.connection; + +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.EnumSet; +import java.util.List; + +/** + * A {@link MultipleConnection} represent a connection to zero or more instances of a particular interface. + *

+ * The typical usage pattern might be for a set of listeners:
+ *

+ * The listeners register themselves with the connection, and the client calls {@link #resolve} on the connection + * to get an implementation of the interface which takes care of looping over all the instances and calling each + * registered listener.

+ *

+ * This saves the listeners from needing to know about the caller, and the caller having to keep track of lists of listeners + */ +public class MultipleConnection extends Connection { + private final List targets = CollectionsFactory.newArrayList(); + private I dispatcher; + + public MultipleConnection(String name, Class ifc, EnumSet flags) { + super(name, ifc, flags); + } + + public void add(I target) { + assert target != null; + // todo remove this restriction, allowing for rewrite of dispatcher + assert dispatcher == null : "targets may not be added to connection after first dispatch"; + targets.add(target); + } + + public void remove(I target) { + // todo remove this restriction, allowing for rewrite of dispatcher + assert dispatcher == null : "targets may not be removed from connection after first dispatch"; + targets.remove(target); + } + + @Override + public I resolve() { + if (dispatcher == null) { + if (targets.size() == 1) { + dispatcher = targets.iterator().next(); + } else { + // todo optimize this if compiled by factorying a better class than the reflection proxy + dispatcher = getInterface().cast(Proxy.newProxyInstance(getInterface().getClassLoader(), new Class[]{getInterface()}, new Invoker())); + } + } + return dispatcher; + } + + protected class Invoker implements InvocationHandler { + protected Invoker() { + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + assert isOpen() : "Connection " + getName() + " used when not open"; + Object rc = null; + for (I target : targets) { + try { + rc = method.invoke(target, args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + return rc; + } + } + + public static MultipleConnection create(String name, Class clazz) { + return new MultipleConnection(name, clazz, EnumSet.noneOf(Flags.class)); + } + + public static MultipleConnection create(String name, Class clazz, EnumSet flags) { + return new MultipleConnection(name, clazz, flags); + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java new file mode 100644 index 0000000..bb2ca62 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.connection; + +import org.jpsx.api.InvalidConfigurationException; + +import java.util.EnumSet; + +/** + * A {@link SimpleConnection} represents a connection to a single implementation object. + *

+ * This type of connection is useful when you want to be able to connect to a single implementor + * of an interface for some specific purpose but do not want to be involved with the details of + * how that implementor is constructed.

+ *

+ * The target of the connection calls {@link #set} to initialize itself as the target.

+ *

+ * The client of the connection calls {@link #resolve} as usual, or {@link #peek} if it wants null returned + * if there is no implementor. + */ +public class SimpleConnection extends Connection { + private I target; + + public SimpleConnection(String name, Class ifc, EnumSet flags) { + super(name, ifc, flags); + } + + public void set(I target) { + if (target == null) + throw new IllegalStateException("Target for simple connection '" + getName() + "' may only be set once"); + this.target = target; + } + + /** + * @return the target of the connection + * @throws org.jpsx.api.InvalidConfigurationException + * if there is no target + */ + @Override + public I resolve() { + if (target == null) + throw new InvalidConfigurationException("No target for simple connection '" + getName() + "'"); + // todo we need a wrapper which respects open/closed + return target; + } + + /** + * @return the target of the connection or null if there is one + */ + public I peek() { + return target; + } + + /** + * Factory method to create a simple connection to an implementor of a given interface + * + * @param name + * @param clazz + * @return + */ + public static SimpleConnection create(String name, Class clazz) { + return new SimpleConnection(name, clazz, EnumSet.noneOf(Flags.class)); + } + + /** + * Factory method to create a simple connection to an implementor of a given interface, specifying + * specifc flags for the connection + * + * @param name + * @param clazz + * @param flags + * @return + */ + public static SimpleConnection create(String name, Class clazz, EnumSet flags) { + return new SimpleConnection(name, clazz, flags); + } +} diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java b/src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java new file mode 100644 index 0000000..483be61 --- /dev/null +++ b/src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.bootstrap.util; + +import java.util.*; + +public class CollectionsFactory { + public static Set newHashSet() { + return new HashSet(); + } + + public static Map newHashMap() { + return new HashMap(); + } + + public static Map newTreeMap() { + return new TreeMap(); + } + + public static Map newTreeMap(Comparator c) { + return new TreeMap(c); + } + + public static List newArrayList() { + return new ArrayList(); + } +} diff --git a/src/lwjgl/pom.xml b/src/lwjgl/pom.xml new file mode 100644 index 0000000..d23616f --- /dev/null +++ b/src/lwjgl/pom.xml @@ -0,0 +1,56 @@ + + + UTF-8 + 1.8 + 1.8 + + 4.0.0 + org.jpsx + lwjgl + jar + 1.0-SNAPSHOT + jpsx-bootstrap + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + org.jpsx + api + 1.0-SNAPSHOT + + + org.jpsx + runtime + 1.0-SNAPSHOT + + + + log4j + log4j + 1.2.13 + + + + org.apache.bcel + bcel + 5.2 + + + + org.lwjgl.lwjgl + lwjgl + 2.9.1 + + + + + + + + diff --git a/src/lwjgl/src/main/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java b/src/lwjgl/src/main/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java new file mode 100644 index 0000000..34ede3e --- /dev/null +++ b/src/lwjgl/src/main/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.gpu; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.hardware.gpu.Display; +import org.jpsx.api.components.hardware.gpu.DisplayManager; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.util.Timing; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.lwjgl.opengl.AWTGLCanvas; +import org.lwjgl.opengl.PixelFormat; +import org.lwjgl.opengl.GL11; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL12.*; +import org.lwjgl.LWJGLException; + +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.image.*; +import java.nio.IntBuffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class LWJGLDisplay extends JPSXComponent implements Display, KeyListener { + private static final Logger log = Logger.getLogger("Display"); + + public static final String LOCATION_X_PROPERTY = "x"; + public static final String LOCATION_Y_PROPERTY = "y"; + + private Frame frame; + + // todo see if this is slower - we can fix GPU instead! + private static final int SOURCE_FORMAT = GL_BGRA; + /** + * Used to transfer pixel data to open GL texture + */ + private ByteBuffer transferBuffer; + /** + * Used to copy int[] pixel data into the transfer buffer + */ + private IntBuffer transferBufferIntView; + + private boolean blanked = true; + + private int[] ram; // video RAM + private DisplayManager displayManager; + + /** + * protected data + */ + private int sourceWidth, sourceHeight; // the size of the source to be stretched to be displayed + + private boolean showBlitTime; + private boolean antiAlias; + + private boolean displayVRAM; + + private boolean funkyfudge; + + private int MAX_X = 960; + private int MAX_Y = 512; + + private final int xres[] = new int[]{320, 640, 800, 960, 1024, 1280}; + private final int yres[] = new int[]{256, 512, 600, 768, 768, 1024}; + + private static final int BLIT_TIME_COUNT = 100; + private long blitTimeTotal; + private int blitTimeCount; + private long refreshTimeTotal; + private int refreshTimeCount; +// private boolean noStretch; + private int textureHandle; + + private AWTGLCanvas canvas; + int resindex = 1; + + + public LWJGLDisplay() { + super("JPSX LWJGL AWT Display"); + } + + @Override + public void init() { + super.init(); + HardwareComponentConnections.DISPLAY.set(this); + RuntimeConnections.KEY_LISTENERS.add(this); + transferBuffer = ByteBuffer.allocateDirect(4*1024*512+1); // todo check + 1, we may need to be one off for BGRA, but we should + // just force the GPU to render in the correct format + // don't want any conversions going on + transferBuffer.order(ByteOrder.nativeOrder()); + transferBufferIntView = transferBuffer.asIntBuffer(); + + showBlitTime = Boolean.valueOf(getProperty("showBlitTime","true")); + antiAlias = Boolean.valueOf(getProperty("antiAlias","true")); +// noStretch = Boolean.valueOf(getProperty("noStretch","false")); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + displayManager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); + } + + public static IntBuffer allocInts(int howmany) { + return ByteBuffer.allocateDirect(howmany * 4).order(ByteOrder.nativeOrder()).asIntBuffer(); + } + + public void initDisplay() { + + // todo, make a new initialization state for this + frame = new Frame("JPSX"); + + try { + canvas = new AWTGLCanvas(new PixelFormat()) { + protected void initGL() { + IntBuffer textureHandleB = allocInts(1); + GL11.glGenTextures(textureHandleB); + textureHandle = textureHandleB.get(0); + // 'select' the new texture by it's handle + GL11.glDisable(GL_LIGHTING); + GL11.glDisable(GL_DEPTH_TEST); + GL11.glEnable(GL_TEXTURE_2D); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureHandle); + // set texture parameters + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, antiAlias?GL11.GL_LINEAR:GL11.GL_NEAREST); //GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); //GL11.GL_NEAREST); + + // Create the texture from pixels + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 1024, 512, 0, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); + } + + protected void paintGL() { + stretchBlit(); + try { + swapBuffers(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }; + + frame.setLayout(new LayoutManager() { + public void addLayoutComponent(String name, Component comp) { + } + + public void removeLayoutComponent(Component comp) { + } + + public Dimension preferredLayoutSize(Container parent) { + Insets insets = parent.getInsets(); + Dimension dim = getContentSize(); + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + return dim; + } + + public Dimension minimumLayoutSize(Container parent) { + return preferredLayoutSize(parent); + } + + public void layoutContainer(Container parent) { + Dimension dim = getContentSize(); + Insets insets = parent.getInsets(); + for(Component component : parent.getComponents()) { + component.setBounds(insets.left, insets.top, dim.width, dim.height); + } + } + }); + frame.add(canvas); + canvas.repaint(); + } catch (LWJGLException e) { + throw new InvalidConfigurationException("Failed to initialize lwjgl", e); + } +// DirectColorModel model = new DirectColorModel( 24, 0x0000ff, 0x00ff00, 0xff0000); + DirectColorModel model = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); + WritableRaster raster = model.createCompatibleWritableRaster(1024, 513); + DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); + ram = db.getData(); + int w = getIntProperty(LOCATION_X_PROPERTY, -1); + int h = getIntProperty(LOCATION_Y_PROPERTY, -1); + if (w != -1 && h != -1) frame.setLocation(w, h); + frame.setResizable(false); + frame.show(); + sizeframe(); + canvas.addKeyListener(RuntimeConnections.KEY_LISTENERS.resolve()); + frame.addWindowListener(new Closer()); + frame.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + frame.doLayout(); + } + }); + } + + protected void sizeframe() { + if (displayVRAM) + frame.setSize(new Dimension(1024 + frame.getInsets().left + frame.getInsets().right, 512 + frame.getInsets().top + frame.getInsets().bottom)); + else + frame.setSize(new Dimension(xres[resindex] + frame.getInsets().left + frame.getInsets().right, yres[resindex] + frame.getInsets().top + frame.getInsets().bottom)); + } + + // todo cache these + protected Dimension getContentSize() { + if (displayVRAM) + return new Dimension(1024, 512); + else + return new Dimension(xres[resindex], yres[resindex]); + } + + protected void switchsize() { + resindex++; + if (resindex == xres.length) resindex = 0; + sizeframe(); + } + + // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU). + public int[] acquireDisplayBuffer() { + return ram; + } + + public void releaseDisplayBuffer() { + } + + /** + * needs to protect drawing state + */ + private Object stateLock = new Object(); + + protected void stretchBlit() { + int l = frame.getInsets().left; + int t = frame.getInsets().top; + long timeBasis = 0; + if (showBlitTime) { + timeBasis = Timing.nanos(); + } + // todo don't recreate + Dimension dim = getContentSize(); + GL11.glViewport(0,0,dim.width, dim.height); + GL11.glMatrixMode(GL_PROJECTION); + GL11.glLoadIdentity(); + GL11.glOrtho(0,dim.width,0,dim.height,-1,1); + GL11.glMatrixMode(GL_MODELVIEW); + GL11.glLoadIdentity(); + // todo sync on that too + if (displayVRAM) { + synchronized (stateLock) { + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 1024, 512, 0, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); + } + GL11.glBegin(GL_QUADS); + GL11.glTexCoord2f(0f,1f); + GL11.glVertex2f(0f,0f); + GL11.glTexCoord2f(1f,1f); + GL11.glVertex2f(1024f,0f); + GL11.glTexCoord2f(1f,0f); + GL11.glVertex2f(1024f,512f); + GL11.glTexCoord2f(0f,0f); + GL11.glVertex2f(0f,512f); + GL11.glEnd(); + } else { + if (blanked) { + GL11.glClear(GL_COLOR_BUFFER_BIT); + } else { + float tw, th; + synchronized (stateLock) { + GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, sourceWidth, sourceHeight, SOURCE_FORMAT, GL11.GL_UNSIGNED_BYTE, transferBuffer); + // todo coords are wrong because of blanking - refactor along with other stuff + tw = sourceWidth/1024f; + th = sourceHeight/512f; + } + GL11.glBegin(GL_QUADS); + GL11.glTexCoord2f(0f,0f); + GL11.glVertex2f(0f,0f); + GL11.glTexCoord2f(tw,0f); + GL11.glVertex2f(dim.width,0f); + GL11.glTexCoord2f(tw,th); + GL11.glVertex2f(dim.width,dim.height); + GL11.glTexCoord2f(0f,th); + GL11.glVertex2f(0f,dim.height); + GL11.glEnd(); +// g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], +// 0, 0, sourceWidth, sourceHeight, null); + + } +// if (volatileImage != null && !volatileImage.contentsLost()) { +// if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); +// if (noStretch) { +// g.drawImage(volatileImage, l, t, l + sourceWidth, t + sourceHeight, +// 0, 0, sourceWidth, sourceHeight, null); +// } else { +// g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], +// 0, 0, sourceWidth, sourceHeight, null); +// } +// } + } + if (showBlitTime) { + blitTimeTotal += Timing.nanos()-timeBasis; + if (BLIT_TIME_COUNT == ++blitTimeCount) { + String refreshString = ""; + if (refreshTimeCount!=0) { + refreshString = " refresh="+((refreshTimeTotal/(refreshTimeCount*100000))/10.0)+"ms"; + refreshTimeTotal = refreshTimeCount = 0; + } + double blitTimeMSRounded = (blitTimeTotal/(BLIT_TIME_COUNT*100000))/10.0; + frame.setTitle("JPSX lwjgl - " + ((blitTimeMSRounded >= 1) ? "!SLOW! blit=" : "blit=") + blitTimeMSRounded + "ms" + refreshString); + blitTimeCount = 0; + blitTimeTotal = 0; + } + } + } + + // todo fix sync + public void refresh() { + boolean rgb24 = displayManager.getRGB24(); + if (funkyfudge) { + GPU.setVRAMFormat(!rgb24); + funkyfudge = false; + } + GPU.setVRAMFormat(rgb24); + // for now we use default display size + long timeBasis = 0; + if (showBlitTime) { + timeBasis = Timing.nanos(); + } + synchronized (stateLock) { + if (displayManager.getBlanked()) { + blanked = true; + } else { + blanked = false; + if (displayVRAM) { + // copy all of vram + transferBufferIntView.clear(); + transferBufferIntView.put(ram, 0, 1024*512); + transferBufferIntView.flip(); + } else { + sourceWidth = displayManager.getDefaultPixelWidth(); + if (rgb24) sourceWidth = (sourceWidth * 3) / 2; + sourceHeight = displayManager.getDefaultPixelHeight(); + int marginLeft = displayManager.getLeftMarginPixels(); + if (rgb24) marginLeft = (marginLeft * 3) / 2; + int marginTop = displayManager.getTopMarginPixels(); + int pixelWidth = displayManager.getPixelWidth(); + if (rgb24) pixelWidth = (pixelWidth * 3) / 2; + int pixelHeight = displayManager.getPixelHeight(); + int marginRight = sourceWidth - pixelWidth - marginLeft; + int marginBottom = sourceHeight - pixelHeight - marginTop; + if (pixelWidth > 0 && pixelHeight > 0) { + transferBufferIntView.clear(); + // from left-right and bottom to top, we copy the pixels into our transfer buffer + int offset = displayManager.getXOrigin() + (displayManager.getYOrigin() + pixelHeight - 1) * 1024; + for(int i=0; i 0) { +// // fill left +// g2.fillRect(0, 0, marginLeft, sourceHeight); +// } +// if (marginRight > 0) { +// // fill left +// g2.fillRect(sourceWidth - marginRight, 0, marginRight, sourceHeight); +// } +// if (marginTop > 0) { +// // fill top +// g2.fillRect(0, 0, sourceWidth, marginTop); +// } +// if (marginBottom > 0) { +// // fill top +// g2.fillRect(0, sourceHeight - marginBottom, sourceWidth, marginBottom); +// } + } + } + } + if (showBlitTime) { + refreshTimeTotal += Timing.nanos()-timeBasis; + refreshTimeCount++; + } + canvas.repaint(); + //stretchBlit(graphics); + } + + public void keyTyped(KeyEvent e) { + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_F12) { + switchsize(); + } + if (e.getKeyCode() == KeyEvent.VK_F11) { + refresh(); + } + if (e.getKeyCode() == KeyEvent.VK_F10) { + funkyfudge = true; + } + if (e.getKeyCode() == KeyEvent.VK_F9) { + displayVRAM = !displayVRAM; + sizeframe(); + refresh(); + } + if (e.getKeyCode() == KeyEvent.VK_F8) { + for (int i = 0; i < 1024 * 512; i++) { + ram[i] = ram[i] & 0x01ffffff; + } + } + if (e.getKeyCode() == KeyEvent.VK_F7) { + for (int i = 0; i < 1024 * 512; i++) { + ram[i] = ram[i] | 0xfe000000; + } + } + } + + public void keyReleased(KeyEvent e) { + } + + private static class Closer extends WindowAdapter { + public void windowClosing(WindowEvent e) { + RuntimeConnections.MACHINE.resolve().close(); + } + } +} diff --git a/src/pom.xml b/src/pom.xml new file mode 100644 index 0000000..1579d76 --- /dev/null +++ b/src/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.neoexpert + root + 1.0-SNAPSHOT + pom + + jvm-root + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.11 + test + + + + + api + bootstrap + lwjgl + runtime + + diff --git a/src/runtime/pom.xml b/src/runtime/pom.xml new file mode 100644 index 0000000..d0a8a11 --- /dev/null +++ b/src/runtime/pom.xml @@ -0,0 +1,49 @@ + + + UTF-8 + 1.8 + 1.8 + + 4.0.0 + org.jpsx + runtime + jar + 1.0-SNAPSHOT + jpsx-bootstrap + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + org.jpsx + api + 1.0-SNAPSHOT + + + org.jpsx + bootstrap + 1.0-SNAPSHOT + + + + log4j + log4j + 1.2.13 + + + + org.apache.bcel + bcel + 5.2 + + + + + + + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/EmulationException.java b/src/runtime/src/main/java/org/jpsx/runtime/EmulationException.java new file mode 100644 index 0000000..52c8ef7 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/EmulationException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +public class EmulationException extends RuntimeException { + public EmulationException(String message) { + super(message); + } + + public EmulationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/FinalComponentSettings.java b/src/runtime/src/main/java/org/jpsx/runtime/FinalComponentSettings.java new file mode 100644 index 0000000..f05e7c4 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/FinalComponentSettings.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import org.jpsx.api.InvalidConfigurationException; + +/** + * Components which wish to cache static final variables based on component settings + * should place those settings inside another (presumably inner class) such that + * they can easily check that the inner class is not referenced in the wrong order + *

+ * A sample usage is shown below + *

+ * public class Foo extends JPSXComponent {
+ *    @Override void init() {
+ *       MySettings.setComponent(this);
+ *    }
+ * 

+ * private static class Settings extends FinalComponentSettings { + * public static final boolean someFlag = getComponent().getBooleanProperty("someFlag",true) + * } + * } + *

+ */ +public class FinalComponentSettings { + private static JPSXComponent component; + + public static JPSXComponent getComponent() { + if (component == null) { + throw new InvalidConfigurationException("Attempted to access cached component settings before component initialization"); + } + return component; + } + + public static void setComponent(JPSXComponent component) { + if (FinalComponentSettings.component != null) + throw new InvalidConfigurationException("Attempted to set component more than once"); + FinalComponentSettings.component = component; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/FinalResolvedConnectionCache.java b/src/runtime/src/main/java/org/jpsx/runtime/FinalResolvedConnectionCache.java new file mode 100644 index 0000000..1e45b33 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/FinalResolvedConnectionCache.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import org.jpsx.bootstrap.connection.Connection; + +public class FinalResolvedConnectionCache { + public static I resolve(Connection connection) { + // todo throw an exception if it is too early in the cycle + return connection.resolve(); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/JPSXComponent.java b/src/runtime/src/main/java/org/jpsx/runtime/JPSXComponent.java new file mode 100644 index 0000000..976da54 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/JPSXComponent.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import java.util.Properties; + +public abstract class JPSXComponent { + private Properties properties = new Properties(); + private String description; + + protected JPSXComponent(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public void init() { + } + + /** + * Called during machine initialization to connect the components together + *

+ * Subclasses should override this to + */ + public void resolveConnections() { + } + + public void begin() { + } + + public void setProperty(String name, String value) { + properties.put(name, value); + } + + public String getProperty(String name, String defaultValue) { + return properties.getProperty(name, defaultValue); + } + + public boolean getBooleanProperty(String name, boolean defaultValue) { + String val = properties.getProperty(name, String.valueOf(defaultValue)); + return Boolean.valueOf(val); + } + + public int getIntProperty(String name, int defaultValue) { + int rc = defaultValue; + String val = properties.getProperty(name); + if (val != null) { + try { + rc = Integer.parseInt(val); + } catch (NumberFormatException e) { + + } + } + return rc; + } + + protected Properties getProperties() { + return properties; + } +} + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachine.java b/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachine.java new file mode 100644 index 0000000..249e5db --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachine.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +public interface JPSXMachine { + + // initializer priorities; higher happens earliest + + int PRIORITY_RESOLVE_CONNECTIONS = 90000; + int PRIORITY_ADD_INSTRUCTIONS = 50000; + int PRIORITY_DMA_CONTROLLER = 40000; + int PRIORITY_IRQ_CONTROLLER = 35000; + int PRIORITY_REGISTER_ADDRESSES = 30000; + int PRIORITY_POPULATE_MEMORY = 10000; + int PRIORITY_FREEZE_SETTINGS = 5000; + + void addInitializer(int priority, Runnable initializer); + + void close(); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachineImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachineImpl.java new file mode 100644 index 0000000..fb14103 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/JPSXMachineImpl.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import org.apache.log4j.Logger; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.JPSXMachineLifecycle; +import org.jpsx.bootstrap.configuration.ComponentDefinition; +import org.jpsx.bootstrap.configuration.MachineDefinition; +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * This class is responsible for creating the components and initializing them + */ +public class JPSXMachineImpl implements JPSXMachine, JPSXMachineLifecycle { + public static final String CATEGORY = "Machine"; + private static Logger log = Logger.getLogger(CATEGORY); + + /** + * List of all components + */ + private List components = CollectionsFactory.newArrayList(); + + /** + * Ordered set of initializers to be run before execution begins + */ + private Map> initializers = CollectionsFactory.newTreeMap(Collections.reverseOrder()); + + private boolean settingsFrozen; + + public void initialize(MachineDefinition machine) { + RuntimeConnections.MACHINE.set(this); + addMachineElements(machine); + + // add our initializers + addInitializer(PRIORITY_RESOLVE_CONNECTIONS, new Runnable() { + public void run() { + log.info("Resolving connections..."); + for (JPSXComponent component : components) { + component.resolveConnections(); + } + } + }); + + addInitializer(PRIORITY_FREEZE_SETTINGS, new Runnable() { + public void run() { + settingsFrozen = false; + } + }); + + log.info("Pre-initializing components..."); + for (JPSXComponent component : components) { + component.init(); + } + + // perform ordered initialization + runInitializers(); + } + + public void start() { + for (JPSXComponent component : components) { + component.begin(); + } + + Runnable entryPoint = RuntimeConnections.MAIN.peek(); + if (entryPoint != null) { + entryPoint.run(); + } else { + // default implementation is just to run cpu + RuntimeConnections.CPU_CONTROL.resolve().go(); + + while (true) { + try { + Thread.sleep(Integer.MAX_VALUE); + } catch (InterruptedException e) { + break; + } + } + } + + close(); + } + + public void addInitializer(int priority, Runnable initializer) { + List list = initializers.get(priority); + if (list == null) { + list = CollectionsFactory.newArrayList(); + initializers.put(priority, list); + } + list.add(initializer); + } + + protected void addMachineElements(MachineDefinition machineDef) { + for (ComponentDefinition componentDef : machineDef.getComponents()) { + JPSXComponent component = createComponent(componentDef.getClassName()); + for (Map.Entry entry : componentDef.getProperties().entrySet()) { + component.setProperty(entry.getKey(), entry.getValue()); + } + log.info("Adding component " + component.getDescription()); + components.add(component); + } + } + + public JPSXComponent createComponent(String className) { + + try { + Class clazz = Class.forName(className); + return (JPSXComponent) clazz.newInstance(); + } catch (ClassCastException e) { + throw new InvalidConfigurationException("Class " + className + " does not extend JPSXComponent"); + } catch (Throwable e) { + throw new InvalidConfigurationException("Can't create instance of class " + className, e); + } + } + + private void runInitializers() { + for (List list : initializers.values()) { + for (Runnable initializer : list) { + initializer.run(); + } + } + } + + public void close() { + log.info("Closing...\n"); + // todo something other than this! + System.exit(0); + } + + public boolean settingsFrozen() { + return settingsFrozen; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/RuntimeConnections.java b/src/runtime/src/main/java/org/jpsx/runtime/RuntimeConnections.java new file mode 100644 index 0000000..f7f3b6f --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/RuntimeConnections.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import org.jpsx.api.CPUControl; +import org.jpsx.bootstrap.connection.MultipleConnection; +import org.jpsx.bootstrap.connection.SimpleConnection; + +import java.awt.event.KeyListener; + +public class RuntimeConnections { + /** + * This connections is always available + */ + public static final SimpleConnection MACHINE = SimpleConnection.create("JPSX Machine", JPSXMachine.class); + + public static final SimpleConnection CPU_CONTROL = SimpleConnection.create("CPU Control", CPUControl.class); + public static final MultipleConnection KEY_LISTENERS = MultipleConnection.create("Key Listeners", KeyListener.class); + public static final SimpleConnection MAIN = SimpleConnection.create("JPSX Main", Runnable.class); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/SingletonJPSXComponent.java b/src/runtime/src/main/java/org/jpsx/runtime/SingletonJPSXComponent.java new file mode 100644 index 0000000..4534ccd --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/SingletonJPSXComponent.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime; + +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.bootstrap.util.CollectionsFactory; + +import java.util.Set; + +/** + * Only one instance of a specific subclass may be created; this + * does not stop you from creating two different classes which represent + * the same piece of hardware + */ +public abstract class SingletonJPSXComponent extends JPSXComponent { + private static final Set usedClasses = CollectionsFactory.newHashSet(); + + protected SingletonJPSXComponent(String description) { + super(description); + } + + @Override + public void init() { + super.init(); + if (!usedClasses.add(getClass().getName())) { + throw new InvalidConfigurationException("Attempted to create multiple instances of " + getClass().getName()); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java new file mode 100644 index 0000000..18a755e --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java @@ -0,0 +1,1786 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.bcel.generic.*; +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceListener; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.Pollable; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.bootstrap.classloader.ClassModifier; +import org.jpsx.bootstrap.classloader.JPSXClassLoader; +import org.jpsx.bootstrap.connection.SimpleConnection; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.JPSXMachine; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.util.ByteCodeUtil; +import org.jpsx.runtime.util.ClassUtil; +import org.jpsx.runtime.util.MiscUtil; + +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +// todo disallow multiple reg at the same address +public final class AddressSpaceImpl extends SingletonJPSXComponent implements ClassModifier, AddressSpace, AddressSpaceRegistrar { + private static final Logger log = Logger.getLogger("AddressSpace"); + private static final Logger logPoll = Logger.getLogger("AddressSpace.poll"); + private static final Logger logUnknown = Logger.getLogger("AddressSpace.unknown"); + + private static final String HARDWARE_CLASS = ClassUtil.innerClassName(AddressSpaceImpl.class, "Hardware"); + + private static final boolean logUnknownDebug = logUnknown.isDebugEnabled(); + private static final boolean logPollDebug = logPoll.isDebugEnabled(); + private static final boolean logPollTrace = logPoll.isTraceEnabled(); + + public static class Settings { + public static final boolean tagAddressAccess = true; + public static final boolean checkAlignment = false; + public static final boolean debugPoll = false; + public static final boolean assertOnUnknownAddress = true; + public static final boolean checkHWOverlap = false; + } + + public static final int[] ram; + public static int[] ramD; + public static final int[] scratch; + public static final int[] bios; + public static final int[] hw; + public static final int[] par; + + private static int[] ramDummy; + private static byte[] ramTags; + private static byte[] biosTags; + private static int lastPoll32Address = 0; + private static int lastPoll32Count = 0; + private static boolean writeEnabled = true; + + private static final int SCRATCH_MASK = SCRATCH_SIZE - 1; + private static final int PAR_MASK = PAR_SIZE - 1; + private static final int BIOS_MASK = BIOS_SIZE - 1; + private static final int HW_MASK = HW_SIZE - 1; + + private static int readPC0; + private static int readPC1; + private static int readPC2; + private static int readPCHW; // PC of last hw read + private static int readAddress0; + private static int readAddress1; + private static int readAddress2; + private static int readAddressHW; + private static int readsSinceHW; // count of reads since last hw read + private static final int MAX_READS_SINCE_HW = 16; + + private static AddressSpaceListener addressSpaceListeners; + private static Scheduler scheduler; + + static { + ram = new int[RAM_SIZE >> 2]; + // not much writing usually done when ram writing disabled + ramDummy = new int[0x1000 >> 2]; + ramD = ram; + ramTags = new byte[RAM_SIZE >> 2]; + biosTags = new byte[BIOS_SIZE >> 2]; + scratch = new int[SCRATCH_SIZE >> 2]; + bios = new int[BIOS_SIZE >> 2]; + hw = new int[HW_SIZE >> 2]; + par = new int[PAR_SIZE >> 2]; + } + + public AddressSpaceImpl() { + super("JPSX Address Space"); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpaceListeners = CoreComponentConnections.ADDRESS_SPACE_LISTENERS.resolve(); +// r3000 = CoreComponentConnections.R3000.resolve(); + scheduler = CoreComponentConnections.SCHEDULER.resolve(); + } + + public void init() { + super.init(); + JPSXClassLoader.registerClassModifier(HARDWARE_CLASS, this); + JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); + CoreComponentConnections.ADDRESS_SPACE.set(this); + machine.addInitializer(JPSXMachine.PRIORITY_REGISTER_ADDRESSES, new Runnable() { + public void run() { + log.info("Registering memory mapped addresses..."); + + // make a connection wrapper around the registrar, so that we can close it afterwards + SimpleConnection connection = SimpleConnection.create("AddressSpaceRegistrar", AddressSpaceRegistrar.class); + connection.set(AddressSpaceImpl.this); + CoreComponentConnections.ALL_MEMORY_MAPPED.resolve().registerAddresses(connection.resolve()); + CoreComponentConnections.ALL_MEMORY_MAPPED.close(); + connection.close(); + } + }); + machine.addInitializer(JPSXMachine.PRIORITY_POPULATE_MEMORY, new Runnable() { + public void run() { + log.info("Populating memory..."); + CoreComponentConnections.ALL_POPULATORS.resolve().run(); + CoreComponentConnections.ALL_POPULATORS.close(); + } + }); + } + + private void rewriteHWMethod(ClassGen cgen, String name, String signature, SortedMap cases, InstructionList suffix, int resolution) { + ConstantPoolGen cp = cgen.getConstantPool(); + org.apache.bcel.classfile.Method m = cgen.containsMethod(name, signature); + MethodGen mg = JPSXClassLoader.emptyMethod(cgen, m); + InstructionList il = mg.getInstructionList(); + + ByteCodeUtil.emitSwitch(cp, il, 0, cases, resolution, HW_BASE, HW_END - resolution); + il.append(suffix); + + mg.setMaxLocals(); + mg.setMaxStack(); + cgen.replaceMethod(m, mg.getMethod()); + il.dispose(); + } + + public ClassGen modifyClass(String classname, ClassGen cgen) { + ConstantPoolGen cp = cgen.getConstantPool(); + InstructionList suffix = new InstructionList(); + InstructionList il = new InstructionList(); + TreeMap cases; + Iterator addresses; + Integer address; + Method m; + + // read 32 + cases = new TreeMap(); + for (addresses = read32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) read32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new IRETURN()); + cases.put(address, il); + } + for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subRead32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new IRETURN()); + cases.put(address, il); + } + suffix.append(new ILOAD(0)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead32", "(I)I"))); + suffix.append(new IRETURN()); + rewriteHWMethod(cgen, "read32", "(I)I", cases, suffix, 4); + + // write 32 + cases.clear(); + for (addresses = write32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) write32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); + il.append(new RETURN()); + cases.put(address, il); + } + for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, -1)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(address, il); + } + suffix.append(new ILOAD(0)); + suffix.append(new ILOAD(1)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite32", "(II)V"))); + suffix.append(new RETURN()); + rewriteHWMethod(cgen, "write32", "(II)V", cases, suffix, 4); + + // read 16 + cases.clear(); + for (addresses = read16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) read16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + } + for (addresses = subRead16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subRead16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + } + for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~3; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subRead32Callbacks.get(address); + + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new IRETURN()); + cases.put(iAddress + 2, il); + } + + suffix.append(new ILOAD(0)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead16", "(I)I"))); + suffix.append(new IRETURN()); + rewriteHWMethod(cgen, "read16", "(I)I", cases, suffix, 2); + + // write 16 + cases.clear(); + for (addresses = write16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) write16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); + il.append(new RETURN()); + cases.put(address, il); + } + for (addresses = subWrite16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subWrite16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xffff)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(address, il); + } + for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~3; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUSH(cp, 0xffff)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(address, il); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 0xffff0000)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(iAddress + 2, il); + } + suffix.append(new ILOAD(0)); + suffix.append(new ILOAD(1)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite16", "(II)V"))); + suffix.append(new RETURN()); + rewriteHWMethod(cgen, "write16", "(II)V", cases, suffix, 2); + + // read 8 + cases.clear(); + for (addresses = read8Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) read8Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + } + for (addresses = subRead16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~1; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subRead16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 8)); + il.append(new ISHR()); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(iAddress + 1, il); + } + for (addresses = subRead32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~3; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subRead32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(address, il); + + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 8)); + il.append(new ISHR()); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(iAddress + 1, il); + + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new IRETURN()); + cases.put(iAddress + 2, il); + + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(I)I"))); + il.append(new PUSH(cp, 24)); + il.append(new ISHR()); + il.append(new IRETURN()); + cases.put(iAddress + 3, il); + } + + suffix.append(new ILOAD(0)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultRead8", "(I)I"))); + suffix.append(new IRETURN()); + rewriteHWMethod(cgen, "read8", "(I)I", cases, suffix, 1); + + // write 8 + cases.clear(); + for (addresses = write8Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + m = (Method) write8Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(II)V"))); + il.append(new RETURN()); + cases.put(address, il); + } + for (addresses = subWrite16Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~1; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subWrite16Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new PUSH(cp, 0xff)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(address, il); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 8)); + il.append(new ISHL()); + il.append(new PUSH(cp, 0xff00)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(iAddress + 1, il); + } + for (addresses = subWrite32Callbacks.keySet().iterator(); addresses.hasNext();) { + address = (Integer) addresses.next(); + int iAddress = address.intValue() & ~3; + assert null == cases.get(address) : MiscUtil.toHex(address.intValue(), 8); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new PUSH(cp, 0xff)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(address, il); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new PUSH(cp, 8)); + il.append(new ISHL()); + il.append(new PUSH(cp, 0x0000ff00)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(iAddress + 1, il); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 0xff)); + il.append(new IAND()); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 0x00ff0000)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(iAddress + 2, il); + + m = (Method) subWrite32Callbacks.get(address); + il = new InstructionList(); + il.append(new PUSH(cp, iAddress)); + il.append(new ILOAD(1)); + il.append(new PUSH(cp, 24)); + il.append(new ISHL()); + il.append(new PUSH(cp, 0xff000000)); + il.append(new INVOKESTATIC(cp.addMethodref(m.getDeclaringClass().getName(), m.getName(), "(III)V"))); + il.append(new RETURN()); + cases.put(iAddress + 3, il); + } + + suffix.append(new ILOAD(0)); + suffix.append(new ILOAD(1)); + suffix.append(new INVOKESTATIC(cp.addMethodref(classname, "defaultWrite8", "(II)V"))); + suffix.append(new RETURN()); + rewriteHWMethod(cgen, "write8", "(II)V", cases, suffix, 1); + + return cgen; + } + + + public void tagClearPollCounters() { + _tagClearPollCounters(); + } + + public static void _tagClearPollCounters() { + readPC0 = readPC1 = readPC2 = -1; + } + + + public void tagAddressAccessRead8(int pc, int address) { + _tagAddressAccessRead8(pc, address); + } + + /** + * Note this method requires that pc falls either in RAM or + * BIOS + */ + public static void _tagAddressAccessRead8(final int pc, final int address) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + + int value; + byte tag = 0;//TAG_INVALID; ?? todo why was this here + if (Settings.tagAddressAccess) { + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + tag = TAG_SCRATCH; + } else if (prefix == 0 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (prefix == -6 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < HW_END && address >= HW_BASE) { + tag = TAG_HW; + } else if (address < PAR_END && address >= PAR_BASE) { + tag = TAG_PAR; + } else if (address >= BIOS_BASE && address < BIOS_END) { + tag = TAG_BIOS; + } + } + + int index = (pc & 0x1fffff) >> 2; + int oldTag = tags[index]; + if (0 != (oldTag & TAG_POLL)) { + _checkPoll8(address); + } else { + if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible poll at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible HW specific poll8 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } + } + readPC0 = readPC1; + readPC1 = readPC2; + readPC2 = pc; + readAddress0 = readAddress1; + readAddress1 = readAddress2; + readAddress2 = address; + if (address < HW_END && address >= HW_BASE) { + readAddressHW = address; + readPCHW = pc; + readsSinceHW = 0; + } else { + readsSinceHW++; + } + + tags[index] |= tag; + } + + public void tagAddressAccessRead16(final int pc, final int address) { + _tagAddressAccessRead16(pc, address); + } + + /** + * Note this method requires that pc falls either in RAM or + * BIOS + */ + public static void _tagAddressAccessRead16(final int pc, final int address) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + + byte tag = 0;//TAG_INVALID; ?? todo why was this here + if (Settings.tagAddressAccess) { + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + tag = TAG_SCRATCH; + } else if (prefix == 0 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (prefix == -6 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < HW_END && address >= HW_BASE) { + tag = TAG_HW; + } else if (address < PAR_END && address >= PAR_BASE) { + tag = TAG_PAR; + } else if (address >= BIOS_BASE && address < BIOS_END) { + tag = TAG_BIOS; + } + } + + int index = (pc & 0x1fffff) >> 2; + int oldTag = tags[index]; + if (0 != (oldTag & TAG_POLL)) { + _checkPoll16(address); + } else { + if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible poll at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible HW specific poll16 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } + } + readPC0 = readPC1; + readPC1 = readPC2; + readPC2 = pc; + readAddress0 = readAddress1; + readAddress1 = readAddress2; + readAddress2 = address; + if (address < HW_END && address >= HW_BASE) { + readAddressHW = address; + readPCHW = pc; + readsSinceHW = 0; + } else { + readsSinceHW++; + } + tags[index] |= tag; + } + + public void tagAddressAccessRead32(int pc, int address) { + _tagAddressAccessRead32(pc, address); + } + + /** + * Note this method requires that pc falls either in RAM or + * BIOS + */ + public static void _tagAddressAccessRead32(final int pc, final int address) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + + byte tag = 0;//TAG_INVALID; ?? todo why was this here + + if (Settings.tagAddressAccess) { + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + tag = TAG_SCRATCH; + } else if (prefix == 0 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (prefix == -6 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < HW_END && address >= HW_BASE) { + tag = TAG_HW; + } else if (address < PAR_END && address >= PAR_BASE) { + tag = TAG_PAR; + } else if (address >= BIOS_BASE && address < BIOS_END) { + tag = TAG_BIOS; + } + } + + int index = (pc & 0x1fffff) >> 2; + int oldTag = tags[index]; + if (0 != (oldTag & TAG_POLL)) { + _checkPoll32(address); + } else { + // Simple check of last 3 reads + if ((pc == readPC0 && address == readAddress0) || (pc == readPC1 && address == readAddress1) || (pc == readPC2 && address == readAddress2)) { + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible poll32 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } else if (pc == readPCHW && address == readAddressHW && readsSinceHW < MAX_READS_SINCE_HW) { + // Tony Hawk fails to catch poll of 0x1f801814 for vsync in interlaced mode, because the polling is spread + // across several functions... in this hardware read case, lets look back a little further + tag |= TAG_POLL; + if (logPollDebug) { + logPoll.debug("possible HW specific poll32 at " + MiscUtil.toHex(pc, 8) + " of " + MiscUtil.toHex(address, 8)); + } + } + } + readPC0 = readPC1; + readPC1 = readPC2; + readPC2 = pc; + readAddress0 = readAddress1; + readAddress1 = readAddress2; + readAddress2 = address; + if (address < HW_END && address >= HW_BASE) { + readAddressHW = address; + readPCHW = pc; + readsSinceHW = 0; + } else { + readsSinceHW++; + } + tags[index] |= tag; + } + + public void tagAddressAccessWrite(final int pc, final int address) { + _tagAddressAccessWrite(pc, address); + } + + /** + * Note this method requires that pc falls either in RAM or + * BIOS + */ + public static void _tagAddressAccessWrite(final int pc, final int address) { + if (Settings.tagAddressAccess) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + byte tag = 0; // why is this there? TAG_INVALID; + if (prefix == -8 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + tag = TAG_SCRATCH; + } else if (prefix == 0 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (prefix == -6 && offset < RAM_SIZE) { + tag = TAG_RAM; + } else if (address < HW_END && address >= HW_BASE) { + tag = TAG_HW; + } else if (address < PAR_END && address >= PAR_BASE) { + tag = TAG_PAR; + } else if (address >= BIOS_BASE && address < BIOS_END) { +// System.out.println("------------ "+MiscUtil.toHex( pc, 8)+" : "+MiscUtil.toHex( address, 8)); + tag = TAG_BIOS; + } + + tags[(pc & 0x1fffff) >> 2] |= tag; + } + } + + public byte getTag(int pc) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + int index = (pc & 0x1fffff) >> 2; + return tags[index]; + } + + public void orTag(final int pc, byte val) { + byte[] tags; + if (pc < BIOS_BASE || pc >= BIOS_END) { + tags = ramTags; + } else { + tags = biosTags; + } + int index = (pc & 0x1fffff) >> 2; + tags[index] |= val; + } + + public int read8(int address) { + return _read8(address); + } + + public static int _read8(final int address) { + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + int value; + if (prefix == -8 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + value = scratch[(offset & SCRATCH_MASK) >> 2]; + } else if (prefix == 0 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (prefix == -6 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (address < HW_END && address >= HW_BASE) { + return Hardware.read8(address); + } else if (address < PAR_END && address >= PAR_BASE) { + return _parRead8(address); + } else if (address >= BIOS_BASE && address < BIOS_END) { + value = bios[(offset & BIOS_MASK) >> 2]; + } else { + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + value = 0; + } + switch (address & 3) { + case 3: + return (value >> 24) & 0xff; + case 2: + return (value >> 16) & 0xff; + case 1: + return (value >> 8) & 0xff; + default: + return value & 0xff; + } + } + + public static int _read8Ram(final int address) { + int value = ramD[(address & RAM_AND) >> 2]; + + switch (address & 3) { + case 3: + return (value >> 24) & 0xff; + case 2: + return (value >> 16) & 0xff; + case 1: + return (value >> 8) & 0xff; + default: + return value & 0xff; + } + } + + public static int _read8Scratch(final int address) { + int value = scratch[(address ^ SCRATCH_XOR) >> 2]; + + switch (address & 3) { + case 3: + return (value >> 24) & 0xff; + case 2: + return (value >> 16) & 0xff; + case 1: + return (value >> 8) & 0xff; + default: + return value & 0xff; + } + } + + public static int _read8Bios(final int address) { + int value = bios[(address ^ BIOS_XOR) >> 2]; + + switch (address & 3) { + case 3: + return (value >> 24) & 0xff; + case 2: + return (value >> 16) & 0xff; + case 1: + return (value >> 8) & 0xff; + default: + return value & 0xff; + } + } + + public static void _write8Bios(final int address, int value) { + int dummy = bios[(address ^ BIOS_XOR) >> 2]; + } + + public static void _write16Bios(final int address, int value) { + int dummy = bios[(address ^ BIOS_XOR) >> 2]; + } + + public static void _write32Bios(final int address, int value) { + int dummy = bios[(address ^ BIOS_XOR) >> 2]; + } + + public int read16(int address) { + return _read16(address); + } + + public static int _read16(final int address) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + int value; + if (prefix == -8 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + value = scratch[(offset & SCRATCH_MASK) >> 2]; + } else if (prefix == 0 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (prefix == -6 && offset < RAM_SIZE) { + value = ramD[offset >> 2]; + } else if (address < HW_END && address >= HW_BASE) { + return Hardware.read16(address); + } else if (address < PAR_END && address >= PAR_BASE) { + return _parRead16(address); + } else if (address >= BIOS_BASE && address < BIOS_END) { + value = bios[(offset & BIOS_MASK) >> 2]; + } else { + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + value = 0; + } + switch (address & 2) { + case 2: + return (value >> 16) & 0xffff; + default: + return value & 0xffff; + } + } + + public static int _read16Ram(final int address) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int value = ramD[(address & RAM_AND) >> 2]; + switch (address & 2) { + case 2: + return (value >> 16) & 0xffff; + default: + return value & 0xffff; + } + } + + public static int _read16Scratch(final int address) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int value = scratch[(address ^ SCRATCH_XOR) >> 2]; + switch (address & 2) { + case 2: + return (value >> 16) & 0xffff; + default: + return value & 0xffff; + } + } + + public static int _read16Bios(final int address) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int value = bios[(address ^ BIOS_XOR) >> 2]; + switch (address & 2) { + case 2: + return (value >> 16) & 0xffff; + default: + return value & 0xffff; + } + } + + public int read32(int address) { + return _read32(address); + } + + public static int _read32(final int address) { + if (Settings.checkAlignment) { + if ((address & 3) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + return ramD[offset >> 2]; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + return scratch[(offset & SCRATCH_MASK) >> 2]; + } else if (prefix == -6 && offset < RAM_SIZE) { + return ramD[offset >> 2]; + } else if (prefix == 0 && offset < RAM_SIZE) { + return ramD[offset >> 2]; + } else if (address < HW_END && address >= HW_BASE) { + return Hardware.read32(address); + } else if (address < PAR_END && address >= PAR_BASE) { + return _parRead32(address); + } else if (address >= BIOS_BASE && address < BIOS_END) { + return bios[(offset & BIOS_MASK) >> 2]; + } + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + return 0; + } + + + public void write8(int address, int value) { + _write8(address, value); + } + + public static void _write8(final int address, final int value) { + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffffff00; + nvalue = (value & 0xff); + break; + case 1: + mask = 0xffff00ff; + nvalue = (value & 0xff) << 8; + break; + case 2: + mask = 0xff00ffff; + nvalue = (value & 0xff) << 16; + break; + default: + mask = 0x00ffffff; + nvalue = value << 24; + break; + } + if (prefix == -8 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + scratch[(offset & SCRATCH_MASK) >> 2] = (scratch[(offset & SCRATCH_MASK) >> 2] & mask) | nvalue; + } else if (prefix == 0 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (prefix == -6 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (address < HW_END && address >= HW_BASE) { + Hardware.write8(address, value); + } else if (address < PAR_END && address >= PAR_BASE) { + if (!_parWrite8(address, value)) { + //System.out.println("write8 HW "+MiscUtil.toHex( address, 8)); + par[(offset & PAR_MASK) >> 2] = (par[(offset & PAR_MASK) >> 2] & mask) | nvalue; + } + } else if (address >= BIOS_BASE && address < BIOS_END) { + } else { + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + } + return; + } + + public static void _write8Ram(int address, final int value) { + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffffff00; + nvalue = (value & 0xff); + break; + case 1: + mask = 0xffff00ff; + nvalue = (value & 0xff) << 8; + break; + case 2: + mask = 0xff00ffff; + nvalue = (value & 0xff) << 16; + break; + default: + mask = 0x00ffffff; + nvalue = value << 24; + break; + } + address = (address & RAM_AND) >> 2; + ramD[address] = (ramD[address] & mask) | nvalue; + return; + } + + public static void _write8Scratch(int address, final int value) { + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffffff00; + nvalue = (value & 0xff); + break; + case 1: + mask = 0xffff00ff; + nvalue = (value & 0xff) << 8; + break; + case 2: + mask = 0xff00ffff; + nvalue = (value & 0xff) << 16; + break; + default: + mask = 0x00ffffff; + nvalue = value << 24; + break; + } + address = (address ^ SCRATCH_XOR) >> 2; + scratch[address] = (scratch[address] & mask) | nvalue; + return; + } + + public void write16(int address, int value) { + _write16(address, value); + } + + public static void _write16(final int address, final int value) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + + // todo reverse sense of mask + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffff0000; + nvalue = (value & 0xffff); + break; + default: + mask = 0x0000ffff; + nvalue = value << 16; + } + if (prefix == -8 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + scratch[(offset & SCRATCH_MASK) >> 2] = (scratch[(offset & SCRATCH_MASK) >> 2] & mask) | nvalue; + } else if (prefix == 0 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (prefix == -6 && offset < RAM_SIZE) { + ramD[offset >> 2] = (ramD[offset >> 2] & mask) | nvalue; + } else if (address < HW_END && address >= HW_BASE) { + Hardware.write16(address, value); + } else if (address < PAR_END && address >= PAR_BASE) { + if (!_parWrite16(address, value)) { + par[(offset & PAR_MASK) >> 2] = (par[(offset & PAR_MASK) >> 2] & mask) | nvalue; + } + } else if (address >= BIOS_BASE && address < BIOS_END) { + } else { + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + } + return; + } + + public static void _write16Ram(int address, final int value) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffff0000; + nvalue = (value & 0xffff); + break; + default: + mask = 0x0000ffff; + nvalue = value << 16; + } + address = (address & RAM_AND) >> 2; + ramD[address] = (ramD[address] & mask) | nvalue; + return; + } + + public static void _write16Scratch(int address, final int value) { + if (Settings.checkAlignment) { + if ((address & 1) != 0) { + throw new IllegalStateException("misaligned"); + } + } + + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffff0000; + nvalue = (value & 0xffff); + break; + default: + mask = 0x0000ffff; + nvalue = value << 16; + } + address = (address ^ SCRATCH_XOR) >> 2; + scratch[address] = (scratch[address] & mask) | nvalue; + return; + } + + public void write32(int address, int value) { + _write32(address, value); + } + + public static void _write32(final int address, final int value) { + if (Settings.checkAlignment) { + if ((address & 3) != 0) { + throw new IllegalStateException("misaligned"); + } + } + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + ramD[offset >> 2] = value; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + scratch[(offset & SCRATCH_MASK) >> 2] = value; + } else if (prefix == 0 && offset < RAM_SIZE) { + ramD[offset >> 2] = value; + } else if (prefix == -6 && offset < RAM_SIZE) { + ramD[offset >> 2] = value; + } else if (address < HW_END && address >= HW_BASE) { + Hardware.write32(address, value); + } else if (address < PAR_END && address >= PAR_BASE) { + if (!_parWrite32(address, value)) { + par[(offset & PAR_MASK) >> 2] = value; + } + } else if (address >= BIOS_BASE && address < BIOS_END) { + } else if (address == 0xfffe0130) { + // System.out.println( "write 0xfffe0130 "+MiscUtil.toHex( value, 8)); + } else { + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + } + } + + public int internalRead32(final int address) { + return _internalRead32(address); + } + + public static int _internalRead32(final int address) { + // todo check misaligned address? + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + return ram[offset >> 2]; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + return scratch[(offset & SCRATCH_MASK) >> 2]; + } else if (address >= BIOS_BASE && address < BIOS_END) { + return bios[(offset & BIOS_MASK) >> 2]; + } else if (address < HW_END && address >= HW_BASE) { + return hw[(offset & HW_MASK) >> 2]; + } else if (address < PAR_END && address >= PAR_BASE) { + return par[(offset & PAR_MASK) >> 2]; + } else if (prefix == 0 && offset < RAM_SIZE) { + return ram[offset >> 2]; + } else if (prefix == -6 && offset < RAM_SIZE) { + return ram[offset >> 2]; + } + + if (Settings.assertOnUnknownAddress) + throw new IllegalStateException("ACK unknown address " + MiscUtil.toHex(address, 8)); + return 0; + } + + public void internalWrite32(int address, int value) { + _internalWrite32(address, value); + } + + public static void _internalWrite32(final int address, final int value) { + // todo check misaligned address? + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if (prefix == -8 && offset < RAM_SIZE) { + ram[offset >> 2] = value; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + scratch[(offset & SCRATCH_MASK) >> 2] = value; + } else if (address < HW_END && address >= HW_BASE) { + hw[(offset & HW_MASK) >> 2] = value; + } else if (address < PAR_END && address >= PAR_BASE) { + par[(offset & PAR_MASK) >> 2] = value; + } else if (address >= BIOS_BASE && address < BIOS_END) { + bios[(offset & BIOS_MASK) >> 2] = value; + } else if (prefix == 0 && offset < RAM_SIZE) { + ram[offset >> 2] = value; + } else if (prefix == -6 && offset < RAM_SIZE) { + ram[offset >> 2] = value; + } + } + + private static Map read8Callbacks = CollectionsFactory.newHashMap(); + private static Map read16Callbacks = CollectionsFactory.newHashMap(); + private static Map subRead16Callbacks = CollectionsFactory.newHashMap(); + private static Map read32Callbacks = CollectionsFactory.newHashMap(); + private static Map subRead32Callbacks = CollectionsFactory.newHashMap(); + private static Map write8Callbacks = CollectionsFactory.newHashMap(); + private static Map write16Callbacks = CollectionsFactory.newHashMap(); + private static Map subWrite16Callbacks = CollectionsFactory.newHashMap(); + private static Map write32Callbacks = CollectionsFactory.newHashMap(); + private static Map subWrite32Callbacks = CollectionsFactory.newHashMap(); + + private static Map poll8Callbacks = CollectionsFactory.newHashMap(); + private static Map poll16Callbacks = CollectionsFactory.newHashMap(); + private static Map poll32Callbacks = CollectionsFactory.newHashMap(); + + private static final Class[] READ_CALLBACK_PARAMS = new Class[]{int.class}; + private static final Class[] WRITE_CALLBACK_PARAMS = new Class[]{int.class, int.class}; + private static final Class[] SUBWRITE_CALLBACK_PARAMS = new Class[]{int.class, int.class, int.class}; + + private void registerCallback(Map map, int address, Class clazz, String methodName, Class[] params) { + //System.out.println(" register address "+MiscUtil.toHex( address, 8)); + try { + Method m = clazz.getMethod(methodName, params); + map.put(address, m); + } catch (Throwable t) { + StringBuilder desc = new StringBuilder(); + desc.append("Cannot find method "); + desc.append(clazz.getName()); + desc.append("."); + desc.append(methodName); + desc.append("("); + for (int i = 0; i < params.length; i++) { + if (i != 0) desc.append(","); + desc.append(params[i].getName()); + } + desc.append(")"); + throw new IllegalStateException(desc.toString()); + } + } + + public void registerRead8Callback(int address, Class clazz, String methodName) { + registerCallback(read8Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); + } + + public void registerRead16Callback(int address, Class clazz, String methodName) { + registerRead16Callback(address, clazz, methodName, false); + } + + public void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead) { + assert 0 == (address & 1); + if (allowSubRead) { + registerCallback(subRead16Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); + } else { + registerCallback(read16Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); + } + } + + public void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead) { + assert 0 == (address & 3); + if (allowSubRead) { + registerCallback(subRead32Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); + } else { + registerCallback(read32Callbacks, address, clazz, methodName, READ_CALLBACK_PARAMS); + } + } + + public void registerPoll32Callback(int address, Pollable pollable) { + poll32Callbacks.put(address, pollable); + } + + public void registerRead32Callback(int address, Class clazz, String methodName) { + registerRead32Callback(address, clazz, methodName, false); + } + + public void registerWrite8Callback(int address, Class clazz, String methodName) { + registerCallback(write8Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); + } + + public void registerWrite16Callback(int address, Class clazz, String methodName) { + registerWrite16Callback(address, clazz, methodName, false); + } + + public void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { + assert 0 == (address & 1); + if (allowSubWrite) { + registerCallback(subWrite16Callbacks, address, clazz, methodName, SUBWRITE_CALLBACK_PARAMS); + } else { + registerCallback(write16Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); + } + } + + public void registerWrite32Callback(int address, Class clazz, String methodName) { + registerWrite32Callback(address, clazz, methodName, false); + } + + public void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { + assert 0 == (address & 3); + if (allowSubWrite) { + registerCallback(subWrite32Callbacks, address, clazz, methodName, SUBWRITE_CALLBACK_PARAMS); + } else { + registerCallback(write32Callbacks, address, clazz, methodName, WRITE_CALLBACK_PARAMS); + } + } + + public void resolve(int address, ResolveResult result) { + result.address = address; + result.low2 = address & 3; + + int prefix = address >> 28; + int offset = address & OFFSET_MASK; + if ((prefix == 0 || prefix == -8 || prefix == -6) && offset < RAM_SIZE) { + result.mem = ram; + result.offset = offset >> 2; + result.tag = TAG_RAM; + return; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE) { + result.mem = scratch; + result.offset = (offset & SCRATCH_MASK) >> 2; + result.tag = TAG_SCRATCH; + return; + } else if (address < HW_END && address >= HW_BASE) { + result.mem = hw; + result.offset = (offset & HW_MASK) >> 2; + result.tag = TAG_HW; + return; + } else if (address >= BIOS_BASE && address < BIOS_END) { + result.mem = bios; + result.offset = (offset & BIOS_MASK) >> 2; + result.tag = TAG_BIOS; + return; + } + result.mem = null; + //result.tag = TAG_INVALID; + return; + } + + public void resolve(int address, int size, boolean write, ResolveResult result) { + result.address = address; + result.low2 = address & 3; + + // assert end>=address + + int end = size == 0 ? address : (address + size - 1); + int prefix = address >> 28; + int prefix2 = end >> 28; + if (prefix == prefix2) { + int offset = address & OFFSET_MASK; + int offset2 = end & OFFSET_MASK; + if ((prefix == 0 || prefix == -8 || prefix == -6) && offset < RAM_SIZE && offset2 < RAM_SIZE) { + result.mem = ram; + result.offset = offset >> 2; + result.tag = TAG_RAM; + return; + } else if (address < SCRATCH_END && address >= SCRATCH_BASE && end < SCRATCH_END) { + result.mem = scratch; + result.offset = (offset & SCRATCH_MASK) >> 2; + result.tag = TAG_SCRATCH; + return; + } else if (address < HW_END && address >= HW_BASE && end < HW_END) { + result.mem = hw; + result.offset = (offset & HW_MASK) >> 2; + result.tag = TAG_HW; + return; + } else if (address >= BIOS_BASE && address < BIOS_END && end < BIOS_END) { + result.mem = bios; + result.offset = (offset & BIOS_MASK) >> 2; + result.tag = TAG_BIOS; + return; + } + } + result.mem = null; + //result.tag = TAG_INVALID; + } + + public static int _parRead8(final int address) { + //System.out.println( "PAR READ 8: " + MiscUtil.toHex( address, 8 ) ); + return 0; + } + + public static int _parRead16(final int address) { + //System.out.println( "PAR READ 16: " + MiscUtil.toHex( address, 8 ) ); + return 0; + } + + public static int _parRead32(final int address) { + //System.out.println( "PAR READ 32: " + MiscUtil.toHex( address, 8 ) ); + return 0; + } + + public static boolean _parWrite8(final int address, int value) { + //System.out.println( "PAR WRITE 8: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 2 ) ); + return false; + } + + public static boolean _parWrite16(final int address, int value) { + //System.out.println( "PAR WRITE 16: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 4 ) ); + return false; + } + + public static boolean _parWrite32(final int address, int value) { + //System.out.println( "PAR WRITE 32: " + MiscUtil.toHex( address, 8 ) + " " + MiscUtil.toHex( value, 8 ) ); + return false; + } + + public void enableMemoryWrite(boolean enableWrite) { + ramD = enableWrite ? ram : ramDummy; + if (!enableWrite && writeEnabled) { + // clear all the tags + for (int i = 0; i < RAM_SIZE / 4; i++) { + ramTags[i] = 0; + } + addressSpaceListeners.cacheCleared(); + } + writeEnabled = enableWrite; + } + + public static void _checkPoll8(int address) { + if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) + System.out.println("Checking poll8: " + MiscUtil.toHex(address, 8)); + //+" "+MiscUtil.toHex( AddressSpaceImpl.read8( address), 2)); + } + + public static void _checkPoll16(int address) { + // todo check this! + if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) + System.out.println("Checking poll16: " + MiscUtil.toHex(address, 8)); + //+" "+MiscUtil.toHex( AddressSpaceImpl.read16( address), 4)); + } + + // todo make this an N-stack + public static void _checkPoll32(int address) { + if (Settings.debugPoll && ((address & 0x50000000) == 0x00000000)) + System.out.println("Checking poll32: " + MiscUtil.toHex(address, 8)); + if (address == lastPoll32Address) { + lastPoll32Count++; + if (lastPoll32Count == 256) { + if (logPollTrace) { + logPoll.trace("Poll of " + MiscUtil.toHex(address, 8)); + } + + if ((address & 0x50000000) == 0x00000000) { + // we assume that poll of RAM is broken out of by interrupt + scheduler.cpuThreadWait(); + } else { + Pollable p = poll32Callbacks.get(address); + if (p != null) + p.poll(address, 4); + } + lastPoll32Count = 0; + } + } else { + lastPoll32Address = address; + lastPoll32Count = 0; + } + } + + public static class Hardware { + public static void write8(int address, int value) { + // should be rewritten; + assert false; + } + + public static void write16(int address, int value) { + // should be rewritten; + assert false; + } + + public static void write32(int address, int value) { + // should be rewritten; + assert false; + } + + public static int read8(int address) { + // should be rewritten; + assert false; + return 0; + } + + public static int read16(int address) { + // should be rewritten; + assert false; + return 0; + } + + public static int read32(int address) { + // should be rewritten; + assert false; + return 0; + } + + public static int defaultRead32(int address) { + if (Settings.checkHWOverlap) { + if (null != read8Callbacks.get(address)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (null != read8Callbacks.get(address + 1)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (null != read8Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (null != read8Callbacks.get(address + 3)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (null != read16Callbacks.get(address)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (null != subRead16Callbacks.get(address)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (null != read16Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (null != subRead16Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + } + int rc = hw[(address & HW_MASK) >> 2]; + if (logUnknownDebug) { + logUnknown.debug("unknown hwRead32 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 8)); + } + return rc; + } + + public static void defaultWrite32(int address, int value) { + if (Settings.checkHWOverlap && null != write8Callbacks.get(address)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 1)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 3)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != write16Callbacks.get(address)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (Settings.checkHWOverlap && null != subWrite16Callbacks.get(address)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (Settings.checkHWOverlap && null != write16Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (Settings.checkHWOverlap && null != subWrite16Callbacks.get(address + 2)) { + throw new AssertionError("32 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (logUnknownDebug) { + logUnknown.debug("unknown hwWrite32 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 8)); + } + hw[(address & HW_MASK) >> 2] = value; + } + + public static int defaultRead16(int address) { + if (Settings.checkHWOverlap && null != read32Callbacks.get(address & ~3)) { + throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); + } + if (Settings.checkHWOverlap && null != read8Callbacks.get(address)) { + throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != read8Callbacks.get(address + 1)) { + throw new AssertionError("16 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + int rc = hw[(address & HW_MASK) >> 2]; + if (logUnknownDebug) { + logUnknown.debug("unknown hwRead16 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 4)); + } + if (0 != (address & 2)) { + rc >>= 16; + } + return rc & 0xffff; + } + + public static void defaultWrite16(final int address, int value) { + if (Settings.checkHWOverlap && null != write32Callbacks.get(address & ~3)) { + throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); + } + if (Settings.checkHWOverlap && null != write8Callbacks.get(address)) { + throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + if (Settings.checkHWOverlap && null != write8Callbacks.get(address + 1)) { + throw new AssertionError("16 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 8 bit hw"); + } + int mask; + int nvalue; + switch (address & 2) { + case 0: + mask = 0xffff0000; + nvalue = (value & 0xffff); + break; + default: + mask = 0x0000ffff; + nvalue = value << 16; + } + if (logUnknownDebug) { + logUnknown.debug("unknown hwWrite16 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 4)); + } + hw[(address & HW_MASK) >> 2] = (hw[(address & HW_MASK) >> 2] & mask) | nvalue; + } + + public static int defaultRead8(int address) { + if (Settings.checkHWOverlap && null != read16Callbacks.get(address & ~1)) { + throw new AssertionError("8 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (Settings.checkHWOverlap && null != read32Callbacks.get(address & ~3)) { + throw new AssertionError("8 bit hw read at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); + } + int rc = hw[(address & HW_MASK) >> 2]; + if (logUnknownDebug) { + logUnknown.debug("unknown hwRead8 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(rc, 2)); + } + rc >>= ((address & 3) << 3); + return rc & 0xff; + } + + public static void defaultWrite8(final int address, int value) { + if (Settings.checkHWOverlap && null != write16Callbacks.get(address & ~1)) { + throw new AssertionError("8 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 16 bit hw"); + } + if (Settings.checkHWOverlap && null != write32Callbacks.get(address & ~3)) { + throw new AssertionError("8 bit hw write at " + MiscUtil.toHex(address, 8) + " overlaps 32 bit hw"); + } + int mask; + int nvalue; + switch (address & 3) { + case 0: + mask = 0xffffff00; + nvalue = (value & 0xff); + break; + case 1: + mask = 0xffff00ff; + nvalue = (value & 0xff) << 8; + break; + case 2: + mask = 0xff00ffff; + nvalue = (value & 0xff) << 16; + break; + default: + mask = 0x00ffffff; + nvalue = value << 24; + break; + } + if (logUnknownDebug) { + logUnknown.debug("unknown hwWrite8 " + MiscUtil.toHex(address, 8) + " " + MiscUtil.toHex(value, 8)); + } + hw[(address & HW_MASK) >> 2] = (hw[(address & HW_MASK) >> 2] & mask) | nvalue; + } + } + + public int[] getMainRAM() { + return ram; + } + + @Override + public String getMainStaticInterfaceClassName() { + // Defaults to name of us, so override to push static methods to subclass + return AddressSpaceImpl.class.getName(); + } + + @Override + public String getHardwareStaticInterfaceClassName() { + // Defaults to name of us, so override to push static methods to subclass + // Note we don't dereference the class since it is generated (potentially later) + return HARDWARE_CLASS; + } +} \ No newline at end of file diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/CoreComponentConnections.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/CoreComponentConnections.java new file mode 100644 index 0000000..c9b13cc --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/CoreComponentConnections.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.jpsx.api.CPUListener; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceListener; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.cpu.*; +import org.jpsx.api.components.core.dma.DMAChannelOwner; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.irq.IRQOwner; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.bootstrap.connection.MultipleConnection; +import org.jpsx.bootstrap.connection.SimpleConnection; + +public class CoreComponentConnections { + public static final SimpleConnection R3000 = SimpleConnection.create("R3000", R3000.class); + public static final SimpleConnection SCP = SimpleConnection.create("SCP", SCP.class); + public static final SimpleConnection QUARTZ = SimpleConnection.create("QUARTZ", Quartz.class); + public static final SimpleConnection SCHEDULER = SimpleConnection.create("Scheduler", Scheduler.class); + public static final SimpleConnection ADDRESS_SPACE = SimpleConnection.create("Address Space", AddressSpace.class); + public static final SimpleConnection IRQ_CONTROLLER = SimpleConnection.create("IRQ Controller", IRQController.class); + public static final SimpleConnection DMA_CONTROLLER = SimpleConnection.create("DMA Controller", DMAController.class); + public static final SimpleConnection NATIVE_COMPILER = SimpleConnection.create("Native Compiler", NativeCompiler.class); + + public static final MultipleConnection CPU_LISTENERS = MultipleConnection.create("CPU Listeners", CPUListener.class); + public static final MultipleConnection INSTRUCTION_PROVIDERS = MultipleConnection.create("Instruction Providers", InstructionProvider.class); + public static final MultipleConnection ADDRESS_SPACE_LISTENERS = MultipleConnection.create("Address Space Listeners", AddressSpaceListener.class); + public static final MultipleConnection IRQ_OWNERS = MultipleConnection.create("IRQ Owners", IRQOwner.class); + public static final MultipleConnection DMA_CHANNEL_OWNERS = MultipleConnection.create("DMA Channel Owners", DMAChannelOwner.class); + public static final MultipleConnection ALL_MEMORY_MAPPED = MultipleConnection.create("Memory Mapped", MemoryMapped.class); + public static final MultipleConnection ALL_POPULATORS = MultipleConnection.create("Memory Populators", Runnable.class); + public static final MultipleConnection POLL_BLOCK_LISTENERS = MultipleConnection.create("Poll Block Listeners", PollBlockListener.class); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java new file mode 100644 index 0000000..c480dd9 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.dma.DMAChannelOwner; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.runtime.util.MiscUtil; + +public abstract class DMAChannelOwnerBase implements DMAChannelOwner { + public static final Logger log = Logger.getLogger(DMAControllerImpl.CATEGORY); + private DMAController dmaController; + + public abstract int getDMAChannel(); + + + public void register(DMAController controller) { + log.info("Registering channel " + getName()); + dmaController = controller; + controller.registerDMAChannel(this); + } + + public String getName() { + return "DMA device " + getDMAChannel(); + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + if (DMAControllerImpl.debugDMA) + System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + signalTransferComplete(); + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if (DMAControllerImpl.debugDMA) + System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + signalTransferComplete(); + } + + public void cancelDMATransfer(int ctrl) { + if (DMAControllerImpl.debugDMA) System.out.println("cancel " + getName() + " DMA transfer"); + } + + public final void signalTransferComplete() { + dmaController.dmaChannelTransferComplete(this); + } + + public final void signalTransferComplete(boolean interrupt) { + dmaController.dmaChannelTransferComplete(this, interrupt); +// Console.println( getName()+" transfer complete"); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAControllerImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAControllerImpl.java new file mode 100644 index 0000000..dbdede0 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/DMAControllerImpl.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.dma.DMAChannelOwner; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.runtime.JPSXMachine; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.util.MiscUtil; + +// todo synch of DMA address control +// + +// TODO check DMA_ICR - what is bit 23? - what are low bits? + +public class DMAControllerImpl extends SingletonJPSXComponent implements DMAController, MemoryMapped { + protected static final String CATEGORY = "DMA"; + private static final Logger log = Logger.getLogger(CATEGORY); +//$1f801080 DMA channel 0 MDECin +//$1f801090 DMA channel 1 MDECout +//$1f8010a0 DMA channel 2 GPU (lists + image data) +//$1f8010b0 DMA channel 3 CDrom +//$1f8010c0 DMA channel 4 SPU +//$1f8010d0 DMA channel 5 PIO +//$1f8010e0 DMA channel 6 OTC (reverse clear OT) + + protected static final String CLASS = DMAControllerImpl.class.getName(); + + // todo settings + public static final boolean debugDMA = false; + private static AddressSpace addressSpace; + + private static final int ADDR_DMA_PCR = 0x1f8010f0; + private static final int ADDR_DMA_ICR = 0x1f8010f4; + private static final int CHANNEL_COUNT = 7; + private static final int DMA_CTRL_TO_DEVICE = 0x00000001; + private static final int DMA_CTRL_BUSY = 0x01000000; + + private static final int ADDR_DMA0_ADDR = 0x1f801080; + private static final int ADDR_DMA0_SIZE = 0x1f801084; + private static final int ADDR_DMA0_CTRL = 0x1f801088; + + private static final DMAChannelOwner[] dmaChannelOwners = new DMAChannelOwner[CHANNEL_COUNT]; + + private static int pcr; + private static int icr; + + private static IRQ irq; + + + public DMAControllerImpl() { + super("JPSX DMA Controller"); + } + + private static class IRQ extends IRQOwnerBase { + public IRQ() { + super(IRQController.IRQ_DMA, "DMA"); + } + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.DMA_CONTROLLER.set(this); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); + machine.addInitializer(JPSXMachine.PRIORITY_DMA_CONTROLLER, new Runnable() { + public void run() { + log.info("Initializing DMA channels..."); + // get all DMAChannels to register + CoreComponentConnections.DMA_CHANNEL_OWNERS.resolve().register(DMAControllerImpl.this); + } + }); + irq = new IRQ(); + CoreComponentConnections.IRQ_OWNERS.add(irq); + } + + public void registerAddresses(AddressSpaceRegistrar registrar) { + registrar.registerWrite32Callback(ADDR_DMA_ICR, DMAControllerImpl.class, "dmaICRWrite32", true); + registrar.registerWrite32Callback(ADDR_DMA_PCR, DMAControllerImpl.class, "dmaPCRWrite32"); + registrar.registerRead32Callback(ADDR_DMA_ICR, DMAControllerImpl.class, "dmaICRRead32", true); + registrar.registerRead32Callback(ADDR_DMA_PCR, DMAControllerImpl.class, "dmaPCRRead32", true); + for (int i = 0; i < CHANNEL_COUNT; i++) { + if (dmaChannelOwners[i] != null) { + registrar.registerWrite32Callback(ADDR_DMA0_CTRL + i * 0x10, DMAControllerImpl.class, "dmaChannelCtrlWrite32"); + } + } + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + } + + public void registerDMAChannel(DMAChannelOwner owner) { + int channel = owner.getDMAChannel(); + dmaChannelOwners[channel] = owner; + } + + public static void dmaICRWrite32(int address, int value, int mask) { + assert address == ADDR_DMA_ICR; + + int oldICR = icr; + // mask off dma channels' interrupt pending bits + int newICR = ((icr & ~value) & 0xff000000) | (value & 0xffffff); + // only affect the bits which were actually written by the cpu + newICR = (oldICR & ~mask) | (newICR & mask); + + // todo what does bit 31 mean - i've seen *value = (*value & 0x00ffffff)|0x88000000; + if (debugDMA) { + if ((oldICR & 0xffff) != (newICR & 0xffff)) { + log.warn("??? DMA ICR: low bits changed from " + MiscUtil.toHex(oldICR & 0xffff, 4) + " to " + MiscUtil.toHex(newICR & 0xffff, 4)); + } + int changed = newICR ^ oldICR; + for (int i = 0; i < 8; i++) { + if (0 != (changed & (1 << (16 + i)))) { + if (0 != (newICR & (1 << (16 + i)))) { + System.out.println("DMA ICR: Enabling DMA IRQ for channel " + i); + } else { + System.out.println("DMA ICR: Disabling DMA IRQ for channel " + i); + } + } + } + } + icr = newICR; + } + + public static int dmaICRRead32(int address) { + return icr; + } + + public static int dmaPCRRead32(int address) { + return pcr; + } + + public static void dmaPCRWrite32(int address, int value) { + // todo is this true, perhaps bit3 per channel + // is whether to have any effect on that channel + if (debugDMA) { + int changed = pcr ^ value; + System.out.println("DMA PCR " + MiscUtil.toHex(value, 8)); + for (int i = 0; i < 8; i++) { + if (0 != (changed & (1 << (3 + i * 4)))) { + if (0 != (value & (1 << (3 + i * 4)))) { + System.out.println("DMA PCR: Enabling DMA channel " + i); + } else { + System.out.println("DMA PCR: Disabling DMA channel " + i); + } + } + } + } + pcr = value; + } + + public static void dmaChannelCtrlWrite32(int address, int ctrl) { + int channel = (address - ADDR_DMA0_CTRL) / 0x10; + //ASSERT( INVALID_PARAMETER, channel>=0, ""); + //ASSERT( INVALID_PARAMETER, channel> 16) & 0xffff; + ; + if ((ctrl & DMA_CTRL_TO_DEVICE) != 0) { + dmaChannelOwners[channel].beginDMATransferToDevice(base, blocks, blockSize, ctrl); + } else { + dmaChannelOwners[channel].beginDMATransferFromDevice(base, blocks, blockSize, ctrl); + } + } else { + dmaChannelOwners[channel].cancelDMATransfer(ctrl); + } + } else { + if ((ctrl & DMA_CTRL_BUSY) != 0) { + if ((ctrl & DMA_CTRL_TO_DEVICE) != 0) { + System.out.println("DMA to Unknown channel " + channel); + } else { + System.out.println("DMA from Unknown channel " + channel); + } + } else { + System.out.println("DMA cancel Unknown channel " + channel); + } + } + } + + public void dmaChannelTransferComplete(DMAChannelOwner owner) { + dmaChannelTransferComplete(owner, true); + } + + public void dmaChannelTransferComplete(DMAChannelOwner owner, boolean interrupt) { + int channel = owner.getDMAChannel(); + //ASSERT( INVALID_PARAMETER, channel>=0, ""); + //ASSERT( INVALID_PARAMETER, channel. + */ +package org.jpsx.runtime.components.core; + +import org.jpsx.api.CPUListener; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.runtime.JPSXComponent; + +/** + * Simple JDK5 nanotime quartz + */ +public class DefaultQuartz extends JPSXComponent implements Quartz, CPUListener { + private long base; + private long stoppedAt; + + public void init() { + super.init(); + base = System.nanoTime(); + cpuPaused(); + CoreComponentConnections.QUARTZ.set(this); + CoreComponentConnections.CPU_LISTENERS.add(this); + } + + public DefaultQuartz() { + super("JPSX System.nanoTime() Quartz"); + } + + public synchronized long nanoTime() { + if (stoppedAt != 0L) return stoppedAt - base; + return System.nanoTime() - base; + } + + public long bestGranularity() { + // todo we need to verify this on different platforms + return 1L; + } + + public long nanoTime(long granularity) { + // for now + return nanoTime(); + } + + public synchronized void cpuResumed() { + if (stoppedAt != 0L) { + base += System.nanoTime() - stoppedAt; + stoppedAt = 0L; + } + } + + public synchronized void cpuPaused() { + if (stoppedAt == 0L) { + stoppedAt = System.nanoTime(); + // would be VERY unlucky! + if (stoppedAt == 0L) stoppedAt = 1L; + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQControllerImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQControllerImpl.java new file mode 100644 index 0000000..67d290f --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQControllerImpl.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.cpu.SCP; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.irq.IRQOwner; +import org.jpsx.runtime.JPSXMachine; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.SingletonJPSXComponent; + +// todo threading +public class IRQControllerImpl extends SingletonJPSXComponent implements MemoryMapped, IRQController { + static final String CATEGORY = "IRQ"; + private static final Logger log = Logger.getLogger(CATEGORY); + + private static int IRQ_COUNT = 8; + private static IRQOwner[] owners = new IRQOwner[IRQ_COUNT]; + + private static final int ALL_INTERRUPTS = 0xff; + + private static final int ADDR_IRQ_REQUEST = 0x1f801070; + private static final int ADDR_IRQ_MASK = 0x1f801074; + + private static int irqRequest; + private static int irqMask; + private static SCP scp; + + public IRQControllerImpl() { + super("JPSX IRQ Controller"); + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.IRQ_CONTROLLER.set(this); + JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); + machine.addInitializer(JPSXMachine.PRIORITY_IRQ_CONTROLLER, new Runnable() { + public void run() { + log.info("Initializing IRQ owners..."); + // get all IRQOwners to register + CoreComponentConnections.IRQ_OWNERS.resolve().register(IRQControllerImpl.this); + } + }); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + scp = CoreComponentConnections.SCP.resolve(); + } + + public void registerAddresses(AddressSpaceRegistrar registrar) { + registrar.registerWrite32Callback(ADDR_IRQ_REQUEST, IRQControllerImpl.class, "irqRequestWrite32", true); + registrar.registerRead32Callback(ADDR_IRQ_REQUEST, IRQControllerImpl.class, "irqRequestRead32", true); + + registrar.registerWrite32Callback(ADDR_IRQ_MASK, IRQControllerImpl.class, "irqMaskWrite32", true); + registrar.registerRead32Callback(ADDR_IRQ_MASK, IRQControllerImpl.class, "irqMaskRead32", true); + } + + public void registerIRQOwner(IRQOwner owner) { + int irq = owner.getIRQ(); + owners[irq] = owner; + } + + public static synchronized void irqRequestWrite32(int addr, int value, int mask) { + irqRequest &= (~mask) | (value & mask); + updateInterruptLine(); + } + + public static int irqRequestRead32(int addr) { + return irqRequest; + } + + public static void irqMaskWrite32(int addr, int value, int mask) { + irqMask = (irqMask & ~mask) | (value & mask); + } + + public static int irqMaskRead32(int addr) { + return irqMask; + } + + @Override + public void raiseIRQ(int irq) { + _raiseIRQ(irq); + } + + public static synchronized void _raiseIRQ(int irq) { + irqRequest |= (1 << irq); + updateInterruptLine(); + } + + private static int oldRequest; + + private static void updateInterruptLine() { + assert Thread.holdsLock(IRQControllerImpl.class); + int changes = oldRequest ^ irqRequest; + oldRequest = irqRequest; + int irq = 0; + while (irq < IRQ_COUNT && changes != 0) { + if (0 != (changes & 1)) { + IRQOwner owner = owners[irq]; + if (owner != null) { + if (0 != (irqRequest & (1 << irq))) { + owner.irqSet(); + } else { + owner.irqCleared(); + } + } + } + changes >>= 1; + irq++; + } + scp.setInterruptLine(2, 0 != ((irqMask & irqRequest) & ALL_INTERRUPTS)); + } + + public int getIRQRequest() { + return irqRequest; + } + + public int getIRQMask() { + return irqMask; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQOwnerBase.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQOwnerBase.java new file mode 100644 index 0000000..a2fc69f --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/IRQOwnerBase.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.irq.IRQOwner; + +public abstract class IRQOwnerBase implements IRQOwner { + public static final Logger log = Logger.getLogger(IRQControllerImpl.CATEGORY); + protected int irq; + protected String name; + private IRQController controller; + + public IRQOwnerBase(int irq, String name) { + this.irq = irq; + this.name = name; + } + + public void register(IRQController controller) { + this.controller = controller; + log.info("registering IRQ " + getName()); + controller.registerIRQOwner(this); + } + + public final int getIRQ() { + return irq; + } + + public final String getName() { + return name; + } + + public void raiseIRQ() { + controller.raiseIRQ(getIRQ()); + } + + // in case the device needs to know + public void irqSet() { + } + + // in case the device needs to know + public void irqCleared() { + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/MTScheduler.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/MTScheduler.java new file mode 100644 index 0000000..59cac1e --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/MTScheduler.java @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.cpu.PollBlockListener; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.ScheduledAction; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.runtime.SingletonJPSXComponent; + +public class MTScheduler extends SingletonJPSXComponent implements Scheduler { + private static final Logger log = Logger.getLogger("Scheduler"); + private static final boolean logTraceEnabled = log.isTraceEnabled(); + + public MTScheduler() { + super("JPSX Multi-threaded Scheduler"); + } + + private Quartz quartz; + private R3000 r3000; + private PollBlockListener pollBlockListeners; + + private static TickGeneratorThread tickThread; + private static ActionThread actionThread; + + private static final Object cpuControlMonitor = new Object(); + private static volatile int cpuResumeCount; + + public void init() { + super.init(); + tickThread = new TickGeneratorThread(); + actionThread = new ActionThread(); + CoreComponentConnections.SCHEDULER.set(this); + } + + public void resolveConnections() { + super.resolveConnections(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + r3000 = CoreComponentConnections.R3000.resolve(); + pollBlockListeners = CoreComponentConnections.POLL_BLOCK_LISTENERS.resolve(); + } + + public void begin() { + tickThread.start(); + actionThread.start(); + } + + public void schedule(long time, ScheduledAction action) { + schedule(time, Quartz.MSEC, action); + } + + public void schedule(long time, long jitter, ScheduledAction action) { + if (jitter < Quartz.MSEC) { + // todo fix this via CPU + throw new IllegalStateException("jitter <1 msec not yet supported"); + } + actionThread.schedule(time, action); + } + + public boolean isScheduled(ScheduledAction action) { + // todo cope with non-action thread actions when we have them + return actionThread.isScheduled(action); + } + + public void cpuThreadWait() { + assert r3000.isExecutionThread(); + pollBlockListeners.aboutToBlock(); + int count = cpuResumeCount; + synchronized (cpuControlMonitor) { + // if we've had an interruption in the meanwhile, then we don't bother to wait + if (count == cpuResumeCount) { + try { + cpuControlMonitor.wait(); + } catch (InterruptedException e) { + } + } + } + } + + public void cpuThreadNotify() { + synchronized (cpuControlMonitor) { + cpuResumeCount++; + cpuControlMonitor.notify(); + } + } + + + /** + * high priority thread which does tight sleep(1) loop. On Win32 this keeps + * pretty good time + */ + private static class TickGeneratorThread extends Thread { + private TickGeneratorThread() { + super("JPSX Scheduler tick generator thread"); + setPriority(MAX_PRIORITY); + setDaemon(true); + } + + public void run() { + log.info("Tick generator thread starts"); + try { + for (; ;) { + actionThread.tick(); + try { + sleep(1); + } catch (InterruptedException e) { + } + } + } finally { + log.info("Tick generator thread ends"); + } + } + } + + private class ActionThread extends Thread { + private static final int MAX_ACTIONS = 64; + /** + * List of actions, not kept sorted since it is generally small; indeed we limit the size + * the list does not auto-compact instead null entries are left in the middle + */ + private ScheduledAction[] actions = new ScheduledAction[MAX_ACTIONS]; + /** + * List of scheduled times, not kept sorted since it is generally small; indeed we limit the size + * the list does not auto-compact instead null entries are left in the middle marked by 0L time. + */ + private long[] times = new long[MAX_ACTIONS]; + private int length = 0; // length of above arrays + + private volatile long wakeupTime = Long.MAX_VALUE; + + public ActionThread() { + super("JPSX Scheduler action thread"); + setPriority(NORM_PRIORITY + 2); + setDaemon(true); + } + + public void tick() { + // called by the tick generator thread, should do any signalling and return ASAP + long time = quartz.nanoTime(); + if (time < wakeupTime) return; + synchronized (this) { + // wake our potentially blocked thread up + notify(); + } + } + + public void run() { + log.info("ScheduledAction thread starts"); + for (; ;) { + long now = sleepUntilWakeupTime(); + if (logTraceEnabled) { + log.trace("Wakeup " + traceTime(now)); + } + // make one pass over the array, providing synchronized access to our data structures + // but not holding a lock during a callback + int i = 0; + for (; ;) { + ScheduledAction toRun = null; + synchronized (this) { + if (i >= length) break; + long t = times[i]; + if (t != 0L && t <= now) { + toRun = actions[i]; + assert toRun != null; + } + } + if (toRun != null) { + if (logTraceEnabled) { + log.trace("Run " + toRun); + } + long rescheduleTime = toRun.run(now); + if (logTraceEnabled) { + log.trace("Reschedule = " + traceTime(rescheduleTime)); + } + synchronized (this) { + times[i] = rescheduleTime; + if (rescheduleTime == 0L) { + actions[i] = null; + if (i == length) length--; + } + } + } + i++; + } + updateWakeupTime(); + } + } + + private synchronized void updateWakeupTime() { + long next = Long.MAX_VALUE; + if (logTraceEnabled) { + log.trace("New actions: "); + for (int i = 0; i < length; i++) { + long t = times[i]; + if (t != 0L) { + log.trace(traceTime(t) + " " + actions[i]); + } + } + } + for (int i = 0; i < length; i++) { + long t = times[i]; + if (t != 0L && t < next) next = t; + } + wakeupTime = next; + } + + private long sleepUntilWakeupTime() { + for (; ;) { + long t = quartz.nanoTime(); + if (t >= wakeupTime) return t; + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + // we interrupt ourselves in {@link #schedule} if an action + // is inserted before the current wakeup time. + } + } + } + } + + public synchronized void schedule(long time, ScheduledAction action) { + if (logTraceEnabled) { + log.trace("Adding " + traceTime(time) + " " + action); + } + boolean added = false; + for (int i = 0; i < length; i++) { + if (actions[i] == null) { + actions[i] = action; + times[i] = time; + added = true; + } + } + if (!added) { + if (length == MAX_ACTIONS) throw new IllegalStateException("too many actions"); + actions[length] = action; + times[length++] = time; + } + if (time < wakeupTime) { + wakeupTime = time; + // interrupt the action thread, unless we are the action thread! + if (Thread.currentThread() != this) { + actionThread.interrupt(); + } + } + } + + public synchronized boolean isScheduled(ScheduledAction action) { + for (int i = 0; i < length; i++) { + if (actions[i] == action) return true; + } + return false; + } + } + + private static String traceTime(long time) { + return String.valueOf(time / Quartz.MSEC); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/R3000Impl.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/R3000Impl.java new file mode 100644 index 0000000..8dde2f2 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/R3000Impl.java @@ -0,0 +1,1027 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.*; +import org.apache.log4j.Logger; +import org.jpsx.api.CPUControl; +import org.jpsx.api.CPUListener; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.api.components.core.ContinueExecutionException; +import org.jpsx.api.components.core.ImmediateBreakoutException; +import org.jpsx.api.components.core.ReturnFromExceptionException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceListener; +import org.jpsx.api.components.core.cpu.*; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.bootstrap.classloader.ClassModifier; +import org.jpsx.bootstrap.classloader.JPSXClassLoader; +import org.jpsx.bootstrap.connection.SimpleConnection; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.*; +import org.jpsx.runtime.util.ClassUtil; +import org.jpsx.runtime.util.MiscUtil; + +import java.lang.reflect.Modifier; +import java.util.List; +import java.util.Map; + +public final class R3000Impl extends SingletonJPSXComponent implements ClassModifier, R3000, CPUControl, InstructionRegistrar { + private static final Logger logPrintf = Logger.getLogger("PRINTF"); + private static final Logger logCache = Logger.getLogger("Cache"); + private static final Logger log = Logger.getLogger("R3000"); + + private static final String CLASS = R3000Impl.class.getName(); + private static final String UTIL_CLASS = R3000.Util.class.getName(); + private static final String DECODER_CLASS = ClassUtil.innerClassName(R3000Impl.class, "Decoder"); + + private static final String INTERPRET_SIGNATURE = "(I)V"; + private static final Class[] INTERPRET_ARGS = {int.class}; + + public static class Settings extends FinalComponentSettings { + public static final boolean debugBIOS = false; + public static final boolean traceExecutionFlow = false; + public static final boolean skipShell = false; // todo move this elsewhere + public static final boolean dumpRegsOnCall = false; + } + + private static class Refs extends FinalResolvedConnectionCache { + public static final AddressSpace addressSpace = resolve(CoreComponentConnections.ADDRESS_SPACE); + public static final SCP scp = resolve(CoreComponentConnections.SCP); + public static final Scheduler scheduler = resolve(CoreComponentConnections.SCHEDULER); + } + + // todo figure out how to do this generically + public static boolean shellHit; + + private static final int MAX_EXECUTION_DEPTH = 4; + private static final boolean[] inCompiler = new boolean[MAX_EXECUTION_DEPTH]; + private static int executionDepth = -1; + private static Map instructionDisassemblers = CollectionsFactory.newHashMap(); + + public static final int[] regs = new int[32]; + public static int reg_lo; + public static int reg_hi; + public static int reg_pc; // this is the PC if in BIOS etc, or the low 28 bits if in 0/8/A RAM. + //public static int reg_pc_upper; // value to OR with reg_pc to get true PC value.. this changes when jumping between ram banks). + + private static int delayedPCDelta = 4; + private static int interpretedJumpAndLinkTarget = -1; + private static int interpretedJumpAndLinkRetAddr = -1; + + private static int interpretedJumpTarget = -1; + private static int currentPCDelta; + + // todo revisit this; execution control interface + private static final Object cpuControlSemaphore = new Object(); + private static volatile boolean cpuCmdPending; // cpu should pause and wait for command + private static boolean cpuReadyForCommand; + private static int cpuCmd; + private static final int CMD_NOP = 0; + private static final int CMD_STEP = 1; + private static final int CMD_RUN = 2; + private static final int CMD_UPDATE_BREAKPOINTS = 3; + + private static CPUInstruction[] decoding; + private static CPUInstruction[] decodingSPECIAL; + private static CPUInstruction[] decodingREGIMM; + + private static List breakpoints = CollectionsFactory.newArrayList(); + + private static NativeCompiler compiler; + private static CPUListener executionListeners; + + private static int breakpointAdd; + private static int breakpointRemove; + + public R3000Impl() { + super("JPSX Main Processor"); + } + + @Override + public void init() { + super.init(); + RuntimeConnections.CPU_CONTROL.set(this); + CoreComponentConnections.R3000.set(this); + JPSXClassLoader.registerClassModifier(DECODER_CLASS, this); + JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); + machine.addInitializer(JPSXMachine.PRIORITY_ADD_INSTRUCTIONS, new Runnable() { + public void run() { + addInstructions(); + } + }); + CoreComponentConnections.ADDRESS_SPACE_LISTENERS.add(new AddressSpaceListener() { + public void cacheCleared() { + R3000Impl.cacheCleared(); + } + }); + } + + protected void addInstructions() { + i_invalid = new CPUInstruction("invalid", R3000Impl.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION | CPUInstruction.FLAG_INVALID); + decoding = new CPUInstruction[64]; + for (int i = 0; i < 64; i++) { + decoding[i] = i_invalid; + } + decodingSPECIAL = new CPUInstruction[64]; + for (int i = 0; i < 64; i++) { + decodingSPECIAL[i] = i_invalid; + } + decodingREGIMM = new CPUInstruction[32]; + for (int i = 0; i < 32; i++) { + decodingREGIMM[i] = i_invalid; + } + // create connection wrapper so we can close it + SimpleConnection connection = SimpleConnection.create("InstructionRegistrar", InstructionRegistrar.class); + connection.set(this); + CoreComponentConnections.INSTRUCTION_PROVIDERS.resolve().addInstructions(connection.resolve()); + CoreComponentConnections.INSTRUCTION_PROVIDERS.close(); + connection.close(); + } + +// public void registerAddresses() +// { +// // todo move this somewhere else +// AddressSpaceImpl.registerWrite8Callback( 0x1f802041, CLASS, "bootStatus"); + // } + + private static CPUInstruction i_invalid; + + public CPUInstruction getInvalidInstruction() { + return i_invalid; + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + compiler = CoreComponentConnections.NATIVE_COMPILER.peek(); + } + + public static void bootStatus(int address, int value) { + //System.out.println( "BIOS: BOOT STATUS " + value ); + } + + public CPUInstruction decodeInstruction(int ci) { + int index = ci >> 26; + CPUInstruction rc; + switch (index) { + case 0: + rc = decodingSPECIAL[ci & 0x3f]; + break; + case 1: + rc = decodingREGIMM[Util.bits_rt(ci)]; + break; + default: + rc = decoding[index & 0x3f]; + break; + } + return rc.subDecode(ci); + } + + public void setInstructionDisassembler(String name, CPUInstructionDisassembler disassembler) { + instructionDisassemblers.put(name, disassembler); + } + + public void setInstruction(int index, CPUInstruction inst) { + decoding[index] = inst; + } + + public void setSPECIALInstruction(int index, CPUInstruction inst) { + decodingSPECIAL[index] = inst; + } + + public void setREGIMMInstruction(int index, CPUInstruction inst) { + decodingREGIMM[index] = inst; + } + + private static void checkInstruction(CPUInstruction inst) { + // todo decide whether to put this back; needs a flag for those instructions with subdecode + try { + java.lang.reflect.Method method = inst.getInterpreterClass().getDeclaredMethod(inst.getInterpretMethodName(), INTERPRET_ARGS); + if (!Modifier.isStatic(method.getModifiers())) { + throw new InvalidConfigurationException("Interpreter method " + inst.getInterpretMethodName() + " on class " + inst.getInterpreterClass().getName() + " is not static"); + } + } catch (Exception e) { + throw new InvalidConfigurationException("Missing correct interpreter method " + inst.getInterpretMethodName() + " on class " + inst.getInterpreterClass().getName(), e); + } + } + + /** + * The methods in this class are replaced by the morph method + * above at runtime + */ + private static class Decoder { + public static void invokeSpecial(final int ci) { + // this method is runtime generated + throw new EmulationException("should have been generated"); + } + + public static void invokeRegImm(final int ci) { + // this method is runtime generated + throw new EmulationException("should have been generated"); + } + + public static void invoke(final int ci) { + // this method is runtime generated + throw new EmulationException("should have been generated"); + } + } + + private static Thread executionThread; + + public boolean isExecutionThread() { + return Thread.currentThread() == executionThread; + } + + public void begin() { + executionListeners = CoreComponentConnections.CPU_LISTENERS.resolve(); + executionThread = new R3000Thread(); + cpuCmdPending = true; // thread should configure and wait for a cmd + executionThread.start(); + } + + public static void shutdown() { + //pause(); + //m_cpuLaunch = false; + //synchronized (m_cpuControlSemaphore) { + // m_cpuControlSemaphore.notify(); + //} + } + + /** + * If not called from the execution thread, then this blocks until the execution is paused; + * otherwise it + */ + public void pause() { + sendCmd(CMD_NOP); + } + + /** + * Sends a command to the execution thread. Generally this is synchronous, and waits for the command to be acknowledged; + * however if called from the execution thread itself, then this method will throw an exception to return to safely + * return control to the command handling code. PC will be at the currently executing instruction, but side effects + * may already have happened. + * + * @param cmd + */ + private static void sendCmd(int cmd) { + //System.out.println("main: sendCmd "+cmd); + synchronized (cpuControlSemaphore) { + cpuCmdPending = true; + if (Thread.currentThread() != executionThread) { + // normally fine just to have the execution thread make itself ready for a command as soon as possible + CoreComponentConnections.R3000.resolve().requestBreakout(); + if (!cpuReadyForCommand) { + //System.out.println("main: waiting for cpu to be ready"); + try { + cpuControlSemaphore.wait(); + } catch (InterruptedException e) { + } + } + cpuCmd = cmd; + //System.out.println("main: informing cpu of cmd"); + cpuControlSemaphore.notify(); + //System.out.println("main: waiting for cpu to acknowledge cmd"); + try { + cpuControlSemaphore.wait(); + } catch (InterruptedException e) { + } + } else { + // by definition the execution thread is not ready for a command + assert !cpuReadyForCommand; + cpuCmd = cmd; + // This won't return, as we are the execution thread, and this must throw + // an exception to achieve its goals + CoreComponentConnections.R3000.resolve().immediateBreakout(); + } + } + } + + public void step() { + sendCmd(CMD_STEP); + // wait for step to complete by sending another cmd + sendCmd(CMD_NOP); + } + + public void go() { + sendCmd(CMD_RUN); + } + + private static void cpuWaitForCmd() { + executionListeners.cpuPaused(); + synchronized (cpuControlSemaphore) { + boolean done = false; + while (!done) { + //System.out.println("cpu: signalling read for cmd"); + // notify that we're ready for a command + cpuReadyForCommand = true; + cpuControlSemaphore.notify(); + + //System.out.println("cpu: waiting for cmd"); + try { + cpuControlSemaphore.wait(); + } catch (InterruptedException e) { + } + switch (cpuCmd) { + case CMD_NOP: + cpuCmdPending = false; + break; + case CMD_RUN: + done = true; + cpuCmdPending = false; + executionListeners.cpuResumed(); + break; + case CMD_STEP: + done = true; + cpuCmdPending = true; + break; + case CMD_UPDATE_BREAKPOINTS: + updateBreakpoints(); + cpuCmdPending = false; + break; + } + cpuReadyForCommand = false; + cpuControlSemaphore.notify(); + //System.out.println("cpu: acknowledging cmd"); + } + } + } + + // todo revisit this + private class R3000Thread extends Thread { + public R3000Thread() { + super("Execution thread"); + synchronized (cpuControlSemaphore) { + cpuReadyForCommand = false; + } + } + + public void run() { + log.info("Processor thread starts"); + executeFromPC(); + log.info("Processor thread ends"); + } + } + + public final void executeFromPC() { + executionDepth++; + assert executionDepth < MAX_EXECUTION_DEPTH; + + delayedPCDelta = currentPCDelta = 4; + + while (true) { + try { + interpreterLoop(); + } catch (ContinueExecutionException e) { + if (inCompiler[executionDepth]) { + compiler.exceptionInCompiler(e); + inCompiler[executionDepth] = false; + } + if (e.skipCurrentInstruction()) { + reg_pc += 4; + } + // System.out.println("... broke out to execute loop"); + // continue from where we were! + delayedPCDelta = currentPCDelta = 4; + } catch (ReturnFromExceptionException rfe) { + if (inCompiler[executionDepth]) { + compiler.exceptionInCompiler(rfe); + inCompiler[executionDepth] = false; + } + //System.out.println("... returned from exception"); + assert delayedPCDelta == 4 : "rfe delayedPCDelta should be 4"; + currentPCDelta = 4; + // on return from exception we exit loop + break; + } catch (Throwable t) { + boolean ok = false; + if (inCompiler[executionDepth]) { + ok = compiler.exceptionInCompiler(t); + inCompiler[executionDepth] = false; + } + if (!ok) { + t.printStackTrace(); + System.out.println("Execution paused due to Java exception!"); + cpuWaitForCmd(); + } + } + } + executionDepth--; + } + + // should ready this only + public static boolean breakout; + + public void requestBreakout() { + breakout = true; + if (compiler != null) { + compiler.interrupt(); + } + } + + private void handleInterpreterBreakout() { + assert isExecutionThread(); + // all breakouts should cause another breakout if they wish to have another one + breakout = false; + if (Refs.scp.shouldInterrupt()) { + restoreInterpreterState(); + Refs.scp.signalInterruptException(); + } + } + + public final void compilerInterrupted() { + handleInterpreterBreakout(); + if (cpuCmdPending) { + // need to return to CPU loop + immediateBreakout(); + } + } + + @Override + public final void immediateBreakout() { + assert isExecutionThread(); + restoreInterpreterState(); + throw new ImmediateBreakoutException(); + } + + public final void interpreterLoop() { + if (Settings.traceExecutionFlow) { + log.trace("Enter interpreter loop at " + MiscUtil.toHex(reg_pc, 8)); + } + do { + boolean checkBreakout = (currentPCDelta != 4) && (delayedPCDelta == 4); // only check interrupt on non linear flow + + currentPCDelta = delayedPCDelta; + delayedPCDelta = 4; + + boolean shouldWait = cpuCmdPending; + + // not using for each since we want to avoid iterator allocation + for (int i = 0; i < breakpoints.size(); i++) { + if (reg_pc == breakpoints.get(i)) { + shouldWait = true; + break; + } + } + + if (shouldWait) { + cpuWaitForCmd(); + } + + + if (checkBreakout && breakout) { + // not sure if this is the right place for this check; basically we don't want to take interrupts while + // we're stepping + if (!cpuCmdPending) { + handleInterpreterBreakout(); + } + } + + if (reg_pc == interpretedJumpAndLinkTarget) { + if (Settings.skipShell) { + if (!shellHit && reg_pc == 0x80030000) { + shellHit = true; + reg_pc = regs[31]; + } + } + if (Settings.dumpRegsOnCall && shouldDumpRegs(reg_pc)) { + dumpRegs(); + } + // interpreted jalr/jal got us to this PC + if (false && 0 != Refs.scp.currentExceptionType()) { + log.trace("Call " + MiscUtil.toHex(reg_pc, 8) + " from " + MiscUtil.toHex(regs[31] - 8, 8)); + } + + interpretedJumpAndLinkTarget = -1; + + if (!shouldWait && compiler != null) { + + if (Settings.traceExecutionFlow) { + log.trace("calling compiler for " + MiscUtil.toHex(reg_pc, 8)); + } + + inCompiler[executionDepth] = true; + if (compiler.jumpAndLink(reg_pc, interpretedJumpAndLinkRetAddr)) { + // we expect the registers are already restored + inCompiler[executionDepth] = false; + + if (Settings.traceExecutionFlow) { + log.trace("returning from level0 unit"); + } + + // on returning from a call, it must have been a JR, so we can't be in a delay slot + delayedPCDelta = 4; + continue; + } + } + if (Settings.traceExecutionFlow) { + System.out.println("staying in interpreter for " + MiscUtil.toHex(reg_pc, 8)); + } + // todo move this + if (Settings.debugBIOS) { + // todo, register functions s.t. the compiler can insert these also! + if (reg_pc == 0x00001b44) { + debugDeliverEvent(); + } + + if (reg_pc == 0xa0) { + debugA0(); + } + + if (reg_pc == 0xb0) { + debugB0(); + } + + if (reg_pc == 0xc0) { + debugC0(); + } + + } + + // todo move this + if (reg_pc == 0xbfc018e0) { + debugPrintf(); + } + } + + if (reg_pc == interpretedJumpTarget && reg_pc == regs[31]) { + if (false && 0 != Refs.scp.currentExceptionType()) { + System.out.println("return to " + MiscUtil.toHex(regs[31], 8)); + } + if (Settings.traceExecutionFlow) { + System.out.println("r31 return to " + MiscUtil.toHex(reg_pc, 8)); + } + } + + // the virtual invokation here isn't much of a problem compared to the speed of the interpreter + int ci = Refs.addressSpace.internalRead32(reg_pc); + + Decoder.invoke(ci); + + assert regs[0] == 0 : "instruction changed r0"; + + reg_pc += currentPCDelta; + } while (true); + } + + public static boolean shouldDumpRegs(int addr) { + if (Settings.dumpRegsOnCall) { + //return addr==0x80072c1c || addr==0x800729ac || addr==0x8001a504 || addr==0x80019988 || addr==0x800198d8 || addr==0x8003c05c || addr==0x8003a62c; + } + return false; + } + + public static void tempHackForException() { + currentPCDelta = 0; + delayedPCDelta = 4; + } + + public void addBreakpoint(int address) { + // todo fix this shit + breakpointAdd = address; + breakpointRemove = -1; + sendCmd(CMD_UPDATE_BREAKPOINTS); + } + + + public void removeBreakpoint(int address) { + // todo fix this shit + breakpointAdd = -1; + breakpointRemove = address; + sendCmd(CMD_UPDATE_BREAKPOINTS); + } + + private static void updateBreakpoints() { + if (breakpointAdd != -1) { + if (!breakpoints.contains(breakpointAdd)) { + breakpoints.add(0, breakpointAdd); + if (compiler != null) { + compiler.addBreakpoint(breakpointAdd); + } + } + breakpointAdd = -1; + } + if (breakpointRemove != -1) { + if (breakpointRemove >= 0 && breakpointRemove < breakpoints.size()) { + int address = breakpoints.remove(breakpointRemove); + if (compiler != null) { + compiler.removeBreakpoint(address); + } + } else { + int index = breakpoints.indexOf(breakpointRemove); + if (index != -1) { + breakpoints.remove(index); + if (compiler != null) { + compiler.removeBreakpoint(breakpointRemove); + } + } + } + breakpointRemove = -1; + } + } + + public int[] getBreakpoints() { + int[] rc = new int[breakpoints.size()]; + for (int i = 0; i < rc.length; i++) { + rc[i] = breakpoints.get(i); + } + return rc; + } + + // move this elswehere + private static int getParam(int index) { + if (index < 4) { + return regs[4 + index]; + } + return Refs.addressSpace.read32(regs[R_SP] + 0x10 + 4 * (index - 4)); + } + + // move this elsewhere + public static void debugPrintf() { + if (logPrintf.isInfoEnabled()) { + String fmt = readString(regs[4]); + StringBuilder s = new StringBuilder(); + + int param = 1; + int perc = fmt.indexOf('%'); + while (perc != -1) { + s.append(fmt.substring(0, perc)); + + boolean leadingZero = false; + boolean firstDigit = false; + int digits = 0; + + outer: + do { + int c = fmt.charAt(++perc); + switch (c) { + case's': + s.append(readString(getParam(param++))); + break outer; + case'x': + if (digits != 0) { + if (leadingZero) { + s.append(MiscUtil.toHex(getParam(param++), digits)); + } else { + s.append(MiscUtil.toHex(getParam(param++), digits)); + } + } else { + s.append(Integer.toHexString(getParam(param++))); + } + break outer; + case'd': + s.append(getParam(param++)); + break outer; + case'.': + case'-': + case'h': + break; + default: + if (c >= '0' && c <= '9') { + if (firstDigit) { + leadingZero = c == '0'; + firstDigit = false; + } + digits = digits * 10 + (int) (c - '0'); + } else { + break outer; + } + break; + } + } while (true); + + fmt = fmt.substring(perc + 1); + perc = fmt.indexOf('%'); + } + s.append(fmt); + String str = s.toString(); + while (str.endsWith("\n") || str.endsWith("\r")) { + str = str.substring(0, str.length() - 1); + } + logPrintf.info(str); + } + } + + private static String readString(int address) { + String rc = ""; + do { + int val = Refs.addressSpace.read8(address++); + if (val != 0) { + rc += (char) val; + } else { + break; + } + } while (true); + return rc; + } + + public static void debugA0() { + switch (regs[9]) { + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + // boring c library + break; + case 0x3f: // printf + // handled elsewhere + break; + default: + System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: A0 " + MiscUtil.toHex(regs[9], 2)); + } + } + + public static void debugB0() { + switch (regs[9]) { + case 0x3d: // putchar + // part of printf (too verbose) + break; + default: + System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: B0 " + MiscUtil.toHex(regs[9], 2)); + } + } + + public static void debugC0() { + switch (regs[9]) { + default: + System.out.println(MiscUtil.toHex(regs[31], 8) + " BIOS: C0 " + MiscUtil.toHex(regs[9], 2)); + } + } + + public static void debugDeliverEvent() { + System.out.println(MiscUtil.toHex(regs[31], 8) + "BIOS: DeliverEvent " + MiscUtil.toHex(regs[4], 8) + ", " + MiscUtil.toHex(regs[5], 8) + ", " + MiscUtil.toHex(regs[6], 8)); + } + + private static int totalBreakouts; + + /** + * called when the instruction cache is flushed + */ + private static void cacheCleared() { + // remove any RAM based code units +/* for( Iterator i = codeUnits.keySet().iterator(); i.hasNext(); ) { + Integer a = (Integer)i.next(); + int address = a.intValue(); + if (!AddressSpaceImpl.isBIOS( address)) { + i.remove(); + } + } */ + totalBreakouts++; + if (compiler != null) { + compiler.clearCache(); + if (inCompiler[executionDepth]) { + ContinueExecutionException e = ContinueExecutionException.SKIP_CURRENT; + if (logCache.isDebugEnabled()) { + logCache.debug("cacheCleared in compiler depth=" + executionDepth + "; throwing ContinueExecutionException..."); + } + throw e; + } else { + if (logCache.isDebugEnabled()) { + logCache.debug("cacheCleared in interpreter depth=" + executionDepth + "; continuing interpreting..."); + } + } + } + } + + public ClassGen modifyClass(String classname, ClassGen cgen) { + ConstantPoolGen cp = cgen.getConstantPool(); + + // regular decode + + Method m = cgen.containsMethod("invoke", "(I)V"); + MethodGen mg = JPSXClassLoader.emptyMethod(cgen, m); + + InstructionList il = mg.getInstructionList(); + il.append(new ILOAD(0)); + il.append(new BIPUSH((byte) 26)); + il.append(new ISHR()); + + InstructionHandle[] handles = new InstructionHandle[64]; + int[] matches = new int[64]; + for (int i = -32; i < 32; i++) { + int j = i; + if (j < 0) j = j + 64; + matches[i + 32] = i; + CPUInstruction inst = decoding[j]; + handles[i + 32] = il.append(new ILOAD(0)); + switch (j) { + case 0: + il.append(new INVOKESTATIC(cp.addMethodref(DECODER_CLASS, "invokeSpecial", "(I)V"))); + break; + case 1: + il.append(new INVOKESTATIC(cp.addMethodref(DECODER_CLASS, "invokeRegImm", "(I)V"))); + break; + default: + checkInstruction(inst); + il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); + break; + } + il.append(new RETURN()); + } + InstructionHandle def = il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); + il.append(new RETURN()); + il.insert(handles[0], new TABLESWITCH(matches, handles, def)); + mg.setMaxLocals(); + mg.setMaxStack(); + cgen.replaceMethod(m, mg.getMethod()); + il.dispose(); + + // special decode + + m = cgen.containsMethod("invokeSpecial", "(I)V"); + mg = JPSXClassLoader.emptyMethod(cgen, m); + + il = mg.getInstructionList(); + il.append(new ILOAD(0)); + il.append(new BIPUSH((byte) 63)); + il.append(new IAND()); + + handles = new InstructionHandle[64]; + matches = new int[64]; + for (int i = 0; i < 64; i++) { + matches[i] = i; + CPUInstruction inst = decodingSPECIAL[i]; + handles[i] = il.append(new ILOAD(0)); + checkInstruction(inst); + il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); + il.append(new RETURN()); + } + def = il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); + il.append(new RETURN()); + il.insert(handles[0], new TABLESWITCH(matches, handles, def)); + mg.setMaxLocals(); + mg.setMaxStack(); + cgen.replaceMethod(m, mg.getMethod()); + il.dispose(); + + // regimm decode + + m = cgen.containsMethod("invokeRegImm", INTERPRET_SIGNATURE); + mg = JPSXClassLoader.emptyMethod(cgen, m); + + il = mg.getInstructionList(); + il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(UTIL_CLASS, "bits_rt", "(I)I"))); + + handles = new InstructionHandle[32]; + matches = new int[32]; + for (int i = 0; i < 32; i++) { + matches[i] = i; + CPUInstruction inst = decodingREGIMM[i]; + handles[i] = il.append(new ILOAD(0)); + checkInstruction(inst); + il.append(new INVOKESTATIC(cp.addMethodref(inst.getInterpreterClass().getName(), inst.getInterpretMethodName(), INTERPRET_SIGNATURE))); + il.append(new RETURN()); + } + def = il.append(new ILOAD(0)); + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "interpret_invalid", INTERPRET_SIGNATURE))); + il.append(new RETURN()); + il.insert(handles[0], new TABLESWITCH(matches, handles, def)); + mg.setMaxLocals(); + mg.setMaxStack(); + cgen.replaceMethod(m, mg.getMethod()); + il.dispose(); + return cgen; + } + + public void restoreInterpreterState() { + if (inCompiler[executionDepth]) { + compiler.restoreInterpreterState(); + } + } + + // todo threading? + public final int getReg(int reg) { + if (inCompiler[executionDepth]) { + return compiler.getReg(reg); + } else { + return regs[reg]; + } + } + + public final void setReg(int reg, int val) { + if (inCompiler[executionDepth]) { + compiler.setReg(reg, val); + } else { + regs[reg] = val; + } + } + + // todo recheck this; this is a hack to avoid problems with certain versions of HotSpot (perhaps 1.4?) + private static boolean breakHotspot; + + public static final void interpret_invalid(final int ci) { + breakHotspot = false; + Refs.scp.signalReservedInstructionException(); + } + + public String disassemble(int address, int ci) { + CPUInstruction inst = decodeInstruction(ci); + CPUInstructionDisassembler disassembler = instructionDisassemblers.get(inst.getName()); + if (disassembler != null) + return disassembler.disassemble(inst, address, ci); + else + return "(" + inst.getName() + ")"; + } + + /** + * Method should be called from any code which + * is returning from blah + */ + public static void safeReturn() { + } + + // ------------- utility functions + + public static void dumpRegs() { + String s = MiscUtil.toHex(reg_pc, 8); + for (int i = 0; i < 32; i++) { + s += " " + MiscUtil.toHex(regs[i], 8); + } + System.out.println(s); + } + + /** + * Control flow instruction for use by R3000 instruction implementation + * + * @param relativeToDelay target address relative to the delay slot + */ + public void interpreterBranch(int relativeToDelay) { + delayedPCDelta = relativeToDelay; + } + + /** + * Control flow instruction for use by R3000 instruction implementation + * + * @param relativeToDelay target address relative to the delay slot + * @param target the target address + */ + public void interpreterJump(int relativeToDelay, int target) { + delayedPCDelta = relativeToDelay; + interpretedJumpTarget = target; + } + + /** + * Control flow instruction for use by R3000 instruction implementation + * + * @param relativeToDelay target address relative to the delay slot + * @param target the target address + * @param retAddr the return address + */ + public void interpreterJumpAndLink(int relativeToDelay, int target, int retAddr) { + delayedPCDelta = relativeToDelay; + interpretedJumpAndLinkTarget = target; + interpretedJumpAndLinkRetAddr = retAddr; + } + + + public int[] getInterpreterRegs() { + return regs; + } + + public final int getPC() { + return reg_pc; + } + + public final int getLO() { + return reg_lo; + } + + public final int getHI() { + return reg_hi; + } + + public final void setPC(int pc) { + reg_pc = pc; + } + + public final void setLO(int lo) { + reg_lo = lo; + } + + public final void setHI(int hi) { + reg_hi = hi; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/core/SCPImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/components/core/SCPImpl.java new file mode 100644 index 0000000..56d1015 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/core/SCPImpl.java @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.core; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.ContinueExecutionException; +import org.jpsx.api.components.core.ReturnFromExceptionException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.*; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.util.MiscUtil; + +public class SCPImpl extends SingletonJPSXComponent implements SCP, InstructionProvider { + private static final Logger log = Logger.getLogger("SCP"); + + private static long debugNextSecond; + private static int vsyncsTaken; + + private static final boolean debugSCP = log.isDebugEnabled(); + + private static final int STATUS_CU_3 = 0x80000000; + private static final int STATUS_CU_2 = 0x40000000; + private static final int STATUS_CU_1 = 0x20000000; + private static final int STATUS_CU_0 = 0x10000000; + private static final int STATUS_RE = 0x02000000; // is this supported? + private static final int STATUS_BEV = 0x00400000; + private static final int STATUS_TS = 0x00200000; + private static final int STATUS_PE = 0x00100000; // parity + private static final int STATUS_CM = 0x00080000; + private static final int STATUS_PZ = 0x00080000; + private static final int STATUS_SWC = 0x00020000; + private static final int STATUS_ISC = 0x00010000; // cache + private static final int STATUS_IM7 = 0x00008000; + private static final int STATUS_IM6 = 0x00004000; + private static final int STATUS_IM5 = 0x00002000; + private static final int STATUS_IM4 = 0x00001000; + private static final int STATUS_IM3 = 0x00000800; + private static final int STATUS_IM2 = 0x00000400; + private static final int STATUS_IM1 = 0x00000200; + private static final int STATUS_IM0 = 0x00000100; + private static final int STATUS_KUO = 0x00000020; + private static final int STATUS_IEO = 0x00000010; + private static final int STATUS_KUP = 0x00000008; + private static final int STATUS_IEP = 0x00000004; + private static final int STATUS_KUC = 0x00000002; + private static final int STATUS_IEC = 0x00000001; + + private static final int STATUS_IMS = STATUS_IM7 | STATUS_IM6 | STATUS_IM5 | STATUS_IM4 | STATUS_IM3 | STATUS_IM2 | STATUS_IM1 | STATUS_IM0; + + private static final int STATUS_W = STATUS_CU_3 | STATUS_CU_2 | STATUS_CU_1 | STATUS_CU_0 | STATUS_RE | STATUS_BEV | + STATUS_TS | STATUS_PE | STATUS_CM | STATUS_PZ | STATUS_SWC | STATUS_ISC | STATUS_IMS | + STATUS_KUO | STATUS_IEO | STATUS_KUP | STATUS_IEP | STATUS_KUC | STATUS_IEC; + + private static final int CAUSE_BD = 0x80000000; + private static final int CAUSE_CE = 0x30000000; + private static final int CAUSE_CE_SHIFT = 28; + private static final int CAUSE_IP7 = 0x00008000; + private static final int CAUSE_IP6 = 0x00004000; + private static final int CAUSE_IP5 = 0x00002000; + private static final int CAUSE_IP4 = 0x00001000; + private static final int CAUSE_IP3 = 0x00000800; + private static final int CAUSE_IP2 = 0x00000400; + private static final int CAUSE_IP1 = 0x00000200; + private static final int CAUSE_IP0 = 0x00000100; + + private static final int CAUSE_CODE = 0x0000003c; + private static final int CAUSE_CODE_SHIFT = 2; + + private static final int CAUSE_W = CAUSE_IP0 | CAUSE_IP1; + + private static final int REG_INDEX = 0; + private static final int REG_RAND = 1; + private static final int REG_TLBLO = 2; + private static final int REG_BPC = 3; + private static final int REG_CTXT = 4; + private static final int REG_BPA = 5; + private static final int REG_PIDMASK = 6; + private static final int REG_DGIC = 7; + private static final int REG_BADVADDR = 8; + private static final int REG_BDAM = 9; + private static final int REG_TLBHI = 10; + private static final int REG_BPCM = 11; + private static final int REG_STATUS = 12; + private static final int REG_CAUSE = 13; + private static final int REG_EPC = 14; + private static final int REG_PRID = 15; // ID - unimplemented + + private static int status = 0; + private static int cause = 0; + + private static int errorEPC = 0; + private static int EPC = 0; + + private static boolean causeIV; + private static boolean causeBD; + private static int causeCE; + private static int causeIPS; + + private static AddressSpace addressSpace; + private static R3000 r3000; + private static Quartz quartz; + private static Scheduler scheduler; + private static IRQController irqController; + private static int[] interpreterRegs; + + public SCPImpl() { + super("JPSX System Control Processor"); + } + + public void begin() { + signalResetException(); + } + + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + r3000 = CoreComponentConnections.R3000.resolve(); + interpreterRegs = r3000.getInterpreterRegs(); + irqController = CoreComponentConnections.IRQ_CONTROLLER.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + scheduler = CoreComponentConnections.SCHEDULER.resolve(); + } + + public void addInstructions(InstructionRegistrar registrar) { + log.info("Adding COP0 instructions..."); + final CPUInstruction i_eret = new CPUInstruction("eret", SCPImpl.class, 0, CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE); + final CPUInstruction i_mfc0 = new CPUInstruction("mfc0", SCPImpl.class, 0, CPUInstruction.FLAG_WRITES_RT); + // note this needs references_pc because it can cause a return from exception exception + final CPUInstruction i_mtc0 = new CPUInstruction("mtc0", SCPImpl.class, 0, CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_REFERENCES_PC); + + CPUInstruction i_cop0 = new CPUInstruction("cop0", SCPImpl.class, 0, 0) { + public CPUInstruction subDecode(int ci) { + switch (R3000.Util.bits_rs(ci)) { + case 0: + return i_mfc0; + case 4: + return i_mtc0; + case 16: + return i_eret; + } + return r3000.getInvalidInstruction(); + } + }; + registrar.setInstruction(16, i_cop0); + } + + public static void interpret_cop0(final int ci) { + switch (R3000.Util.bits_rs(ci)) { + case 0: + interpret_mfc0(ci); + return; + case 4: + interpret_mtc0(ci); + return; + case 16: + interpret_eret(ci); + return; + } + _signalReservedInstructionException(); + } + + public static void interpret_mtc0(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int sel = ci & 0x7; + int value = interpreterRegs[rt]; + + writeRegister(rd, sel, value); + } + + public static void interpret_mfc0(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int sel = ci & 0x7; + int value = readRegister(rd, sel); + if (rt != 0) + interpreterRegs[rt] = value; + } + + private static void writeRegister(int reg, int sel, int value) { + switch ((sel << 16) + reg) { + case REG_STATUS: + status = (status & ~STATUS_W) | (value & STATUS_W); + addressSpace.enableMemoryWrite((status & STATUS_ISC) == 0); + break; + case REG_CAUSE: + cause = (cause & ~CAUSE_W) | (value & CAUSE_W); + break; + default: + if (log.isDebugEnabled()) + log.debug("SCP: write " + reg + ":" + sel + " " + MiscUtil.toHex(value, 8)); + } + } + + private static int readRegister(int reg, int sel) { + int rc = 0; + switch ((sel << 16) + reg) { + case REG_STATUS: + rc = status; + break; + case REG_CAUSE: + rc = cause; + break; + case REG_EPC: + rc = EPC; + break; + default: + if (log.isDebugEnabled()) { + log.debug("SCP: read " + reg + ":" + sel); + } + } + return rc; + } + + public static void interpret_eret(final int ci) { + // fudge, because PSX BIOS seems to do + // + // jr new_pc + // eret + // + // which is invalid according to r3000 docs; still we can check + // for a JR. + // + // this is a bit of a hack, it doesn't take care of branching directly + // to the ERET, however this would only be bad if the ERET was + // in a delay slot and that was branched to, which seems unlikely - all + // in all I'm very unhappy about this; perhaps revisit when we + // support BD correctly! + + // make sure the regs are written back in case we came from the compiler + r3000.restoreInterpreterState(); + int prevci = addressSpace.internalRead32(r3000.getPC() - 4); + if ((prevci & 0xfc1fffff) == 8) { + EPC = interpreterRegs[R3000.Util.bits_rs(prevci)]; + } else { + throw new IllegalStateException("Expected ERET preceeded by JR"); + } + returnFromException(); + } + + public void init() { + super.init(); + status = 0; + cause = 0; + CoreComponentConnections.SCP.set(this); + CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); + } + + public void signalResetException() { + status = STATUS_BEV; + r3000.setPC(0xbfc00000); + } + + private static boolean getStatusBEV() { + return 0 != (status & STATUS_BEV); + } + + private static void setCauseCE(int val) { + cause = (cause & ~CAUSE_CE) | ((val << CAUSE_CE_SHIFT) & CAUSE_CE); + } + + private static void setCauseExcCode(int val) { + cause = (cause & ~CAUSE_CODE) | ((val << CAUSE_CODE_SHIFT) & CAUSE_CODE); + } + + private static int getCauseExcCode() { + return (cause & CAUSE_CODE) >> CAUSE_CODE_SHIFT; + } + + // todo fix these + private static int getCauseIPS() { + return 0; + } + + private static int getStatusIMS() { + return 0; + } + + public void signalIntegerOverflowException() { + throw new IllegalStateException("INT OVERFLOW"); + } + + public void signalBreakException() { + throw new IllegalStateException("BREAK"); + } + + public void signalReservedInstructionException() { + _signalReservedInstructionException(); + } + + public static void _signalReservedInstructionException() { + throw new IllegalStateException("RESERVED INSTRUCTION"); + } + + public void signalSyscallException() { + if (debugSCP) { + r3000.restoreInterpreterState(); + log.debug("SYSCALL " + interpreterRegs[4]); + } + signalExceptionHelper(EXCEPT_SYSCALL, 0, true); + } + + public boolean shouldInterrupt() { + return _shouldInterrupt(); + } + + private static boolean _shouldInterrupt() { + return (0 != (cause & status & 0xff00)) && (0 != (status & STATUS_IEC)); + } + + public void signalInterruptException() { + if (debugSCP) log.debug("interrupt!"); + if (false) { + if (0 != (1 & irqController.getIRQRequest() & irqController.getIRQMask())) { + vsyncsTaken++; + } + long time = quartz.nanoTime(); + if (time > debugNextSecond) { + log.info("VSYNC/SEC " + vsyncsTaken); + debugNextSecond = time + Quartz.SEC; + vsyncsTaken = 0; + } + } + signalExceptionHelper(EXCEPT_INTERRUPT, 0, false); + } + + + public void setInterruptLine(int line, boolean raised) { + // todo assert range + if (raised) { + cause |= 1 << (line + 8); + } else { + cause &= ~(1 << (line + 8)); + } + checkBreakout(); + // wake up the cpu thread if it is blocked + scheduler.cpuThreadNotify(); + } + + protected static void checkBreakout() { + if (_shouldInterrupt()) { + // need to cause an interrupt + r3000.requestBreakout(); + } + } + + private static void signalExceptionHelper(int type, int faultingCoprocessor, boolean expectSkip) { + // we expect PC to be correct already + r3000.restoreInterpreterState(); + if (debugSCP) log.debug("Exception " + type); + int vectorOffset = 0; + // todo, currently recoverable exceptions aren't + // currently unsupported in the delay slot + if (false/* && r3000.executingDelaySlot()*/) { + cause |= CAUSE_BD; + EPC = r3000.getPC() - 4; + } else { + cause &= ~CAUSE_BD; + EPC = r3000.getPC(); + } +// if (type==EXCEPT_TLB_REFILL_L || type==EXCEPT_TLB_REFILL_S) +// vectorOffset = 0; +// else if (type==EXCEPT_INTERRUPT && getCauseIV()) +// vectorOffset = 0x200; +// else +// vectorOffset = 0x180; + vectorOffset = 0x80; + setCauseCE(faultingCoprocessor); + setCauseExcCode(type); + + status = (status & 0xffffffc0) | ((status << 2) & 0x3c); + + int pc; + if (getStatusBEV()) { + // not sure about this + pc = 0xbfc00200 + vectorOffset; + } else { + pc = 0x80000080; + } + + //System.out.println("about to take exception vector at "+MiscUtil.toHex(pc,8)+" pc was "+MiscUtil.toHex(m_EPC,8)); + executeException(pc, expectSkip); + } + + public int currentExceptionType() { + if (0 != (status & 3)) { + return -1; + } + return getCauseExcCode(); + } + + public static void executeException(int pc, boolean expectSkip) { + int exppc = r3000.getPC(); + int expsp = interpreterRegs[R3000.R_SP]; + + if (debugSCP) { + log.debug("take exception r_pc " + MiscUtil.toHex(r3000.getPC(), 8) + " sp " + MiscUtil.toHex(interpreterRegs[R3000.R_SP], 8) + " go to " + MiscUtil.toHex(pc, 8)); + } + + // quick hack for now + if (expectSkip) exppc += 4; + + r3000.setPC(pc); + r3000.executeFromPC(); + + //System.out.println("return from exception r_pc "+MiscUtil.toHex( r3000.getPC(), 8)+" sp "+MiscUtil.toHex( interpreterRegs[R3000.R_SP], 8)); + // todo check what happened if we were in delay slot + if (r3000.getPC() != exppc || interpreterRegs[R3000.R_SP] != expsp) { + log.debug("unexpected execution flow: pc " + MiscUtil.toHex(r3000.getPC(), 8) + "," + MiscUtil.toHex(exppc, 8) + " sp " + MiscUtil.toHex(interpreterRegs[R3000.R_SP], 8) + "," + MiscUtil.toHex(expsp, 8)); + throw ContinueExecutionException.DONT_SKIP_CURRENT; + } else { + // todo if expect skip, then we can also just return, because the next instruction will be invoked + // we want to reset m_currentPCDelta to 0, and m_delayedPCDelta to 4 + // so that we continue there. + //if (expectSkip) r3000.tempHackForException(); + if (expectSkip) { + r3000.setPC(r3000.getPC() - 4); + } + } + } + + public static void returnFromException() { + status = (status & 0xffffffc0) | ((status >> 2) & 0xf); + //System.out.println("return from execption to pc "+MiscUtil.toHex( pc, 8)); + // todo cope with delay slot! + checkBreakout(); + r3000.setPC(EPC); + throw ReturnFromExceptionException.INSTANCE; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java new file mode 100644 index 0000000..ea83f53 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.apache.bcel.classfile.JavaClass; +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.ContinueExecutionException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +import java.lang.ref.SoftReference; + +// todo check threading +/** + * The CodeUnit class represents all that is known about + * a particular piece sequence R3000 code. + *

+ * It embodies the various states that a piece + * of code can be in (flow analyzed, stage 1 compiled, etc.) + */ +public class CodeUnit { + Logger log = Logger.getLogger("CodeUnit"); + /** + * Used by the compiled code to determine + * which version of the code to use + *

+ * Note this is also used as a guard to ensure visibility between threads + */ + public volatile boolean useStage2; + /** + * Used by the compiled code, to determine + * when to move through the state machine... + * when this counts down to zero, countComplete() is called. + *

+ * This is not volatile, since it is repeatedly updated by the processor thread, and only + * rarely modified by another thread. it is however guaranteed to be visible, since the processor + * thread reads useStage2 before reading this, and non processor threads write useStage2 afterwards + */ + public int count = MultiStageCompiler.Settings.stage2Threshold; + + private Class stage2Class; + private int state; + + // base address of code unit + protected final int base; // todo accessor + private int end; + private final boolean rom; + + private Executable executable; + protected boolean linksFollowed; // todo accessor + private volatile boolean stage1Ready; + //private boolean stage2Ready; + + // todo accessor + protected int stage2Version; + + private int preBreakpointState; + private boolean preBreakpointUseStage2; + private int breakpointCount; + + private static final int STATE_STAGE1 = 0; + private static final int STATE_WAITING_FOR_STAGE2 = 1; + private static final int STATE_STAGE2 = 2; + private static final int STATE_BREAKPOINT = 3; + + // todo it is not clear this is safe to share in the presence of code modification + private SoftReference flowInfoRef = new SoftReference(null); + private SoftReference stage1JavaClassRef = new SoftReference(null); + + public CodeUnit(int base) { + this.base = base; + rom = AddressSpace.Util.isBIOS(base); + } + + public final int getBase() { + return base; + } + + public final boolean isROM() { + return rom; + } + + public Executable getExecutable() { + return executable; + } + + public void setExecutable(Executable executable) { + this.executable = executable; + } + + /** + * unsynchronzied, since different threads should + * use different flow analyzers. + * + * may return null for a garbage method if not called on the execution thread + */ + public FlowAnalyzer.FlowInfo getFlowInfo(FlowAnalyzer flowAnalyzer, boolean executionThread) { + FlowAnalyzer.FlowInfo rc = (FlowAnalyzer.FlowInfo) flowInfoRef.get(); + if (rc == null) { + rc = flowAnalyzer.buildFlowGraph(base, executionThread); + if (rc != null) { + end = rc.end; + flowInfoRef = new SoftReference(rc); + } + } + return rc; + } + + /** + * Get the JavaClass representation of this unit. + *

+ * This method may be called from the execution or background + * compilation thread; in either case it is not synchronized, + * since we don't want the execution thread to wait on the + * background thread if they end up compiling the same class. + * + * this may return null if not on the execution thread for garbage code + */ + public JavaClass getStage1JavaClass(Stage1Generator generator, boolean executionThread) { + // note while not synchronized, once stage1Ready is set + // we know for sure that we don't want to do any + // background compilation + if (!executionThread && stage1Ready) + return null; + + JavaClass rc = (JavaClass) stage1JavaClassRef.get(); + if (rc == null) { + rc = generator.createJavaClass(this, executionThread); + if (!executionThread) { + stage1JavaClassRef = new SoftReference(rc); + } else { + //System.out.println("*** COMPILE IN EXEC THREAD "+MiscUtil.toHex( base, 8)); + } + } + return rc; + } + + public void stage1ClassReady() { + stage1Ready = true; + // note we may miss clearing the soft reference, but oh well! + stage1JavaClassRef.clear(); + // make sure we know about any breakpoints + MultiStageCompiler.enumerateBreakpoints(this); + } + + // This can return null on non java thread for garbage code + public JavaClass getStage2JavaClass(Stage2Generator generator, boolean executionThread) { + return generator.createJavaClass(this, executionThread); + } + + public void stage2ClassReady(Class stage2Class) { + //stage2Ready = true; + this.stage2Class = stage2Class; + count = Integer.MAX_VALUE; + state = STATE_STAGE2; + stage2Version++; + useStage2 = true; + } + + public void stage2ClassBroken() { + // shouldn't be able to happen when we have a breakpoint in the function + assert state != STATE_BREAKPOINT; + // todo setting for this + if (stage2Version < 5) { + try { + stage2Class.getField("replaced").setBoolean(null, true); + } catch (Throwable ignore) { + assert false; + } + if (log.isDebugEnabled()) { + log.debug("Re-write " + MiscUtil.toHex(base, 8) + " version " + (stage2Version + 1)); + } + count = MultiStageCompiler.Settings.stage2Threshold; + state = STATE_STAGE1; + } else { + // just give up + if (log.isDebugEnabled()) { + log.debug("Too many rewrites for " + MiscUtil.toHex(base, 8)); + } + state = STATE_WAITING_FOR_STAGE2; + } + useStage2 = false; + } + + public void breakpointAdded(int address) { + if (stage1Ready) { + assert end != 0; + if (address >= base && address < end) { + breakpointCount++; + if (breakpointCount == 1) { + log.info("HAVE BREAKPOINT IN " + MiscUtil.toHex(base, 8)); + preBreakpointState = state; + preBreakpointUseStage2 = useStage2; + state = STATE_BREAKPOINT; + count = 0; + useStage2 = false; + } + } + } + } + + public void breakpointRemoved(int address) { + if (stage1Ready) { + assert end != 0; + if (address >= base && address < end) { + breakpointCount--; + if (breakpointCount == 0) { + count = MultiStageCompiler.Settings.stage2Threshold; + state = preBreakpointState; + useStage2 = preBreakpointUseStage2; + } + } + } + } + + public void countComplete() { + switch (state) { + case STATE_STAGE1: + state = STATE_WAITING_FOR_STAGE2; + count = Integer.MAX_VALUE; + if (MultiStageCompiler.Settings.enableSecondStage) { + MultiStageCompiler.registerForStage2(this); + } + break; + case STATE_BREAKPOINT: + // break out into the interpreter + CoreComponentConnections.R3000.resolve().setPC(base); + count = 0; + //System.out.println( "entered compiled function that has a breakpoint!" ); + throw ContinueExecutionException.DONT_SKIP_CURRENT; + default: + count = Integer.MAX_VALUE; + break; + } + } + + public boolean stage1Ready() + { + return stage1Ready; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java new file mode 100644 index 0000000..f805e96 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.apache.log4j.Logger; + +// TODO allow for complete generator + +public class CompilerClassLoader extends ClassLoader { + private static final Logger logger = Logger.getLogger(MultiStageCompiler.CATEGORY); + private final String description; + + public CompilerClassLoader(String description, ClassLoader parent) { + super(parent); + this.description = description; + } + + public Class findClass(final String name) throws ClassNotFoundException { + // make sure we haven't defined it already + Class c = findLoadedClass(name); + if (c == null) { + if (logger.isDebugEnabled()) { + logger.debug(description + ": findClass " + name); + } + // Note it is a bit confusing, that because of the delegation model, it is generally + // the rom loader that gets to generate the class here; however this call actually + // generates the class using the rom or current ram loader as appropriate + c = MultiStageCompiler.generateClass(name); + } + return c; + } + + public Class createClass(final String name, byte[] classData) { + if (logger.isDebugEnabled()) { + logger.debug(description + ": defineClass " + name); + } + return defineClass(name, classData, 0, classData.length, null); + } + + public String toString() { + return description; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Executable.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Executable.java new file mode 100644 index 0000000..ca490ae --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Executable.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +public interface Executable { + public int e(int returnAddress, boolean jump); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java new file mode 100644 index 0000000..d40f353 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +import java.util.Stack; + +// todo cope with method > MAX_R3000_METHOD_INSTRUCTIONS +// todo remove maxBlockSize stuff + +public class FlowAnalyzer { + private static final boolean debugFlow = false; + /** + * contains a block value if the corresponding timestamp is correct, + * however, only guaranteed to be the correct BasicBlock if the + * offset is a branch target. Note, we can have + * dangling references to BasicBlocks here, however the number + * is limited, so we don't care. + */ + private final BasicBlock[] blocks = new BasicBlock[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + private final BasicBlock[] branchTargets = new BasicBlock[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + + // if timeStamps correct, then block/flags are valid + private final int[] timeStamps = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + private final byte[] flags = new byte[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + + private static final byte VISITED = 1; + private static final byte BLOCK_START = 2; + private static final byte DELAY_SLOT = 4; + private static final byte CONDITIONAL_BRANCH = 8; + private static final byte UNCONDITIONAL_BRANCH = 16; + + private int currentTimeStamp; + + private int currentBase; + private int blockCount; + private Stack pendingPaths = new Stack(); + private static final Integer i0 = 0; + + private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); + + // note high offset so it isn't seen as a back branch + public final BasicBlock UNKNOWN_BRANCH_TARGET = new BasicBlock(0, 0x40000000, BasicBlock.UNKNOWN_TARGET); + + /** + * Traces execution flow from an entry point. + *

+ * BasicBlocks are constructed for all reachable code paths + * starting at the base address, subject to the limit + * {@link MultiStageCompiler.Settings#maxR3000InstructionsPerUnit}.
+ *

+ * In the case that this limit is exceeded, + * special blocks will be emitted to handle branching + * out of the block.
+ *

+ * As a side of this function, the following + * array members are populated for use by the caller + * + * @param base the entry point + * @return the entry-point {@link BasicBlock} or null if the method appears to be garbage (only for intendedForExecutionThread flow analyzers) + */ + public FlowInfo buildFlowGraph(int base, boolean executionThread) { + return buildFlowGraph(base, 800, executionThread); + } + + public FlowInfo buildFlowGraph(int base, int maxBlockSize, boolean executionThread) { + int instructionCount = 0; + + currentBase = base; + if (debugFlow) System.out.println("buildFlowGraph " + MiscUtil.toHex(base, 8)); + assert 0 == (base & 3); + + currentTimeStamp++; + blockCount = 0; + + BasicBlock firstExtraBlock = null; + BasicBlock lastExtraBlock = null; + + pendingPaths.push(i0); + + + // We might be speculatively analyzing empty memory, so we OR all the instructions together + int ciOR = 0; + + int max = 0; + while (!pendingPaths.isEmpty()) { + int offset = pendingPaths.pop(); + + if (timeStamps[offset] == currentTimeStamp && 0 != (flags[offset] & VISITED)) { + if (0 != (flags[offset] & DELAY_SLOT)) { + // todo graham 12/23/14 - this doesn't make much sense... + // todo it seems like we should be caring if it was already a BLOCK_START + + // nasty case of branching to delay slot which has already been + // visited; however the flow might previously have stopped exactly + // at the delay slot. since the delay slot may not be a branch instruction + // (or if it was would still have another delay slot following), + // we try the next instruction also in case it has never been visited + if (debugFlow) { + System.out.println("RARE: Checking code beyond branched-to delay-slot at " + MiscUtil.toHex(base + offset * 4, 8)); + } + // note this has the side effect of always making the delay slot a single instruction block; + offset++; + } else { + // starting a block which has already been visited, so nothing to do + continue; + } + } + + // side effect is to create block if necessary + getBlock(offset); + + boolean flowOut = false; + + // todo we don't actually handle the case where the method is bigger than this + int end = MultiStageCompiler.Settings.maxR3000InstructionsPerUnit - 1; // -1 in case we need delay slot + int blockLimit = offset + maxBlockSize; + byte nextFlags = 0; + + for (; offset < end; offset++) { + if (offset >= blockLimit && 0 == nextFlags) { + // not delay slot or anything else of interest... + // end our block, but continue where we left off. + pendingPaths.push(offset); + break; + } + if (timeStamps[offset] == currentTimeStamp) { + // run into something we've seen before, so just update the flags + flags[offset] |= nextFlags; + // if we've already actually been here, then quit; + // otherwise we're flowing into a branch target + // we haven't yet visited + if (0 != (flags[offset] & VISITED)) { + break; + } + flags[offset] |= VISITED; + } else { + timeStamps[offset] = currentTimeStamp; + flags[offset] = (byte) (nextFlags | VISITED); + } + nextFlags = 0; + int address = base + (offset << 2); + int ci = addressSpace.internalRead32(address); + ciOR |= ci; + CPUInstruction inst = r3000.decodeInstruction(ci); + + int iFlags = inst.getFlags(); + + if (!executionThread && 0 != (iFlags & CPUInstruction.FLAG_INVALID)) { + // don't like invalid instructions when working in a background thread + // because we might be analyzing garbage. + if (debugFlow) { + System.out.println("Probable garbage at " + MiscUtil.toHex(base, 8) + " because of invalid instruction"); + } + return null; + } + if (0 != (iFlags & CPUInstruction.FLAG_BRANCH)) { + int branchType = inst.getBranchType(ci); + if (0 == (iFlags & CPUInstruction.FLAG_LINK)) { + // note we are a non-linking instruction, so there + // we cannot have both conditional branch and + // register target... which would be bad. + if (0 != (iFlags & (CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_IMM_FAR_TARGET))) { + int target; + if (0 != (iFlags & CPUInstruction.FLAG_IMM_NEAR_TARGET)) { + target = address + 4 + R3000.Util.signed_branch_delta(ci); + } else { + // todo assert Far target + target = ((address + 4) & 0xf0000000) | ((ci & 0x3fffff) << 2); + } + int targetOffset = (target - base) >> 2; + if (targetOffset < 0 || targetOffset >= MultiStageCompiler.Settings.maxR3000InstructionsPerUnit) { + branchTargets[offset] = new BasicBlock(currentBase, targetOffset, BasicBlock.JUMP_WRAPPER); + if (firstExtraBlock == null) { + firstExtraBlock = lastExtraBlock = branchTargets[offset]; + } else { + lastExtraBlock.next = branchTargets[offset]; + lastExtraBlock = branchTargets[offset]; + } + blockCount++; + } else { + branchTargets[offset] = getBlock(targetOffset); + //flags[targetOffset] |= BLOCK_START; + pendingPaths.push(targetOffset); + } + } else { + branchTargets[offset] = UNKNOWN_BRANCH_TARGET; + } + + if (branchType == CPUInstruction.BRANCH_ALWAYS) { + flags[offset] |= UNCONDITIONAL_BRANCH; + } else { + flags[offset] |= CONDITIONAL_BRANCH; + flowOut = true; + } + + // done after the next instruction (delay slot) + end = offset + 2; + nextFlags = DELAY_SLOT; + } + } + } + if (offset > max) { + max = offset; + } + if (flowOut) { + // want to move straight on to next block + pendingPaths.push(offset); + } + } + if (!executionThread && ciOR == 0) { + // all NOPs and then we fell off the end + if (debugFlow) { + System.out.println("Garbage empty-ness at " + MiscUtil.toHex(base, 8)); + } + return null; + } + + BasicBlock block = null; + BasicBlock flowingInBlock = null; + + for (int offset = 0; offset < max; offset++) { + if (timeStamps[offset] == currentTimeStamp) { + assert (0 != (flags[offset] & VISITED)); + + if (0 != (flags[offset] & BLOCK_START)) { + if (block != null) { + block.next = blocks[offset]; + } + block = blocks[offset]; + if (flowingInBlock != null) { + flowingInBlock.flowOut = block; + } + flowingInBlock = block; + } + if (0 != (flags[offset] & DELAY_SLOT)) { + block.includesDelaySlot = true; + } + block.size++; + instructionCount++; + if (0 != (flags[offset] & (CONDITIONAL_BRANCH | UNCONDITIONAL_BRANCH))) { + block.branchOffset = offset; + block.branchOut = branchTargets[offset]; + if (0 != (flags[offset] & UNCONDITIONAL_BRANCH)) { + flowingInBlock = null; + } + } + } + } + + if (debugFlow) { + for (int offset = 0; offset < max; offset++) { + if (timeStamps[offset] == currentTimeStamp) { + int address = base + (offset << 2); + String debug = MiscUtil.toHex(address, 8) + " "; + if (0 != (flags[offset] & BLOCK_START)) { + System.out.println("--- " + blocks[offset]); + debug += "*"; + } else { + debug += " "; + } + if (0 != (flags[offset] & UNCONDITIONAL_BRANCH)) { + if (branchTargets[offset] == null) { + debug += "UBR"; + } else { + debug += "UB" + branchTargets[offset].type; + } + } else if (0 != (flags[offset] & CONDITIONAL_BRANCH)) { + debug += "CB" + branchTargets[offset].type; + } else { + debug += " "; + } + if (0 != (flags[offset] & DELAY_SLOT)) { + debug += "D"; + } else { + debug += " "; + } + + int ci = addressSpace.internalRead32(address); + debug += " " + r3000.disassemble(address, ci); + System.out.println(debug); + } + } + } + assert (block.next == null); + block.next = firstExtraBlock; + + FlowInfo rc = new FlowInfo(); + rc.root = blocks[0]; + rc.instructionCount = instructionCount; + rc.blockCount = blockCount; + rc.base = base; + rc.end = base + max * 4; + return rc; + } + + protected BasicBlock getBlock(int offset) { + if (timeStamps[offset] != currentTimeStamp) { + timeStamps[offset] = currentTimeStamp; + flags[offset] = 0; + } + if (0 == (flags[offset] & BLOCK_START)) { + flags[offset] |= BLOCK_START; + blocks[offset] = new BasicBlock(currentBase, offset); + blockCount++; + } + return blocks[offset]; + } + + // note this class should be immutable with accessors... it may be + // shared by more than one thread + public static class BasicBlock { + /** + * block this flows into, or null if it always branches (e.g. ends with jr) + *

+ * Note that more than one block may flow into another block + * because we need to create a dummy block when someone + * branches to a delay slot + */ + public BasicBlock flowOut; + /** + * block this branches to, or null if it doesn't end with a branch + */ + public BasicBlock branchOut; + + /** + * linked list of blocks in ascending offset order + */ + public BasicBlock next; + + /** + * configure instruction offset within enclsoing method + */ + public int offset; + + /** + * offset of branch instruction + */ + public int branchOffset; + + public int base; + /** + * number of instructions in the method + */ + public int size; + + public boolean includesDelaySlot; + + public int type; + + public static final int NORMAL = 0; + public static final int JUMP_WRAPPER = 1; + public static final int UNKNOWN_TARGET = 2; + + public BasicBlock(int base, int offset) { + this.base = base; + this.offset = offset; + } + + public BasicBlock(int base, int offset, int type) { + this.base = base; + this.offset = offset; + this.type = type; + } + + public String toString() { + String rc; + if (size == 0) { + rc = "unvisited block " + MiscUtil.toHex(base + offset * 4, 8); + } else { + rc = "block " + MiscUtil.toHex(base + offset * 4, 8) + "->" + MiscUtil.toHex(base + offset * 4 + size * 4, 8); + if (flowOut != null) { + rc += " flow " + MiscUtil.toHex(base + flowOut.offset * 4, 8); + } + if (branchOut != null) { + rc += " branch " + MiscUtil.toHex(base + branchOut.offset * 4, 8); + if (!includesDelaySlot) { + rc += " missing-delay-slot"; + } + } + } + return rc; + } + } + + public static class FlowInfo { + public BasicBlock root; + public int instructionCount; + public int base; + public int end; + public int blockCount; + + public String toString() { + return "FlowInfo@" + Integer.toHexString(hashCode()) + " ic=" + instructionCount + " base=" + MiscUtil.toHex( base, 8 ) + " bc=" + blockCount; + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java new file mode 100644 index 0000000..0d3400a --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java @@ -0,0 +1,896 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.apache.bcel.classfile.JavaClass; +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.ContinueExecutionException; +import org.jpsx.api.components.core.ImmediateBreakoutException; +import org.jpsx.api.components.core.ReturnFromExceptionException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.NativeCompiler; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.*; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +import java.lang.reflect.Field; +import java.util.LinkedList; +import java.util.Map; + +// todo, compilation shouldn't fail it should just make a class which throws ContinueExecutionException + +// todo set addressSpace.tagAddressAccess based on whether we're doing 2 stage compile + +// todo, cope with compilation errors caused by data being overwritten in another thread + +// todo consider caching byte code for instruction cache flush + +// todo look for and follow "switch tables" + +// todo handle usuallyRAMRegs better - we could detect methods which obviously set SP to weird values for example + +public class MultiStageCompiler extends SingletonJPSXComponent implements NativeCompiler { + public static final String CATEGORY = "Compiler"; + private static final Logger log = Logger.getLogger(CATEGORY); + + public static final byte TAG_UNWRITTEN_REGS = AddressSpace.TAG_RESERVED_FOR_COMPILER; + public static final byte TAG_DELAY_SLOT = AddressSpace.TAG_RESERVED_FOR_COMPILER_2; + + + protected static Stage1Generator immediateGenerator; + // for use if we need to figure out what the real stage2 generator + // would have done (to fixup unwritten regs when we mispredict memory access + // and have to return to the interpreter); + // note we can't use the real one since it is not thread safe + private static Stage2Generator fixupStage2Generator; + + protected static CompilerClassLoader ramLoader; + protected static CompilerClassLoader romLoader; + protected static int ramLoaderCount = 0; + + protected static final Map romUnits = CollectionsFactory.newHashMap(); + protected static final Map ramUnits = CollectionsFactory.newHashMap(); + + protected static CompilationBroker broker; + + private static final int MAX_BREAKPOINTS = 64; + + private static final int[] breakpoints = new int[MAX_BREAKPOINTS]; + private static int breakpointLimit; + + private static class Refs extends FinalResolvedConnectionCache { + public static final int[] interpreterRegs = CoreComponentConnections.R3000.resolve().getInterpreterRegs(); + } + + private static R3000 r3000; + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + r3000 = CoreComponentConnections.R3000.resolve(); + } + + protected static class ExecutionContext { + public int nativeDepth; + public boolean cacheStale; + } + + protected static int contextDepth = 0; + protected static ExecutionContext context; + protected static final int MAX_CONTEXT_DEPTH = 4; + protected static final ExecutionContext[] contexts; + + protected static boolean ownRegs; + private static AddressSpace addressSpace; + + public MultiStageCompiler() { + super("JPSX Multi-Stage Compiler"); + } + + /** + * Number of jr/jalr calls within native code... we + * limit these if they get to big, in case we're + * not running functions as we suspect... e.g. + * Final Fantasy has a state machine with jal which recurses + * consuming no stack rather than returning! + */ + + static { + contexts = new ExecutionContext[MAX_CONTEXT_DEPTH]; + for (int i = 0; i < MAX_CONTEXT_DEPTH; i++) { + contexts[i] = new ExecutionContext(); + } + context = contexts[0]; + } + + protected static class Settings extends FinalComponentSettings { + // todo, assert this happens late enough + public static final boolean enableSpeculativeCompilation = getComponent().getBooleanProperty("speculativeCompilation", true); + public static final boolean enableSecondStage = getComponent().getBooleanProperty("stage2", true); + public static final boolean secondStageInBackground = true; + public static final int minSizeForSpeculativeCompile = 50; + public static final int maxNativeDepth = 100; + public static final int stage2Threshold = 30; + public static final int maxR3000InstructionsPerUnit = 8000; +// 1 at Assembler temporary. +// 2- 3 v0-v1 Subroutine return values +// 4- 7 a0-a3 Subroutine arguments +// 8-15 t0-t7 Temporaries, may be changed by subroutines +//16-23 s0-s7 Register variables, must be saved by subs. +//24-25 t8-t9 Temporaries, may be changed by subroutines +//26-27 k0-k1 Reserved for the kernel +//28 gp Global pointer +//29 sp Stack pointer +//30 fp(s8) 9th register variable, subs can use this as a frame + // pointer + //31 ra Return address + public static final int savedOnCallRegs = 0x30ff0001; + // We assume these are RAM at first (in this case just SP) + public static final int usuallyRAMRegs = 0x20000000; + public static final boolean saveClasses = getComponent().getBooleanProperty("saveClasses", false); + public static final boolean biosInterruptWorkaround = true; + public static final boolean printCode = getComponent().getBooleanProperty("printCode", false); + protected static final boolean addLineNumbers = true; + protected static final boolean debugPC = false; + protected static final boolean profiling = false; + protected static final boolean megaTrace = false; + protected static final boolean printRare = getComponent().getBooleanProperty("printRare", false); + protected static final boolean statistics = getComponent().getBooleanProperty("statistics", false); + protected static final boolean dumpMemoryMisPredictions = false; + // todo printCode here just because the print code stuff doesn't work properly with basic blocks that have been split into separate methods + // todo the larger number can cause some branches to become too large + protected static final int maxMethodInstructionCount = printCode?8000:800; // todo justify this choice of number + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.NATIVE_COMPILER.set(this); + JPSXMachine machine = RuntimeConnections.MACHINE.resolve(); + machine.addInitializer(JPSXMachine.PRIORITY_FREEZE_SETTINGS, new Runnable() { + @Override + public void run() { + Settings.setComponent(MultiStageCompiler.this); + log.info("printCode " + Settings.printCode); + log.info("Speculative compilation enabled = " + Settings.enableSpeculativeCompilation); + log.info("Second stage enabled = " + Settings.enableSecondStage); + } + }); + } + + public void begin() { + immediateGenerator = new Stage1Generator("c1gen.out", true); + romLoader = new CompilerClassLoader("ROM classloader", MultiStageCompiler.class.getClassLoader()); + broker = new CompilationBroker(); + broker.begin(); + clearCache(); + } + + public boolean jumpAndLink(int address, int returnAddress) { + int oldNativeDepth = contexts[contextDepth].nativeDepth; + + context = contexts[++contextDepth]; + assert !context.cacheStale; + + CodeUnit unit = getCodeUnit(address); + + Executable exec = unit.getExecutable(); + if (exec == null) { + exec = makeExecutable(unit); + if (exec == null) { + return false; + } + } + + context.nativeDepth = oldNativeDepth; + if (!ownRegs) { + interpreterToCompiler(); + } + int retaddr = exec.e(returnAddress, false); + compilerToInterpreter(); + assert retaddr == returnAddress; + assert oldNativeDepth == context.nativeDepth : "nativeDepth mismatch for " + MiscUtil.toHex(address, 8) + " " + oldNativeDepth + "!=" + context.nativeDepth; + contextDepth--; + assert contextDepth >= 0; + r3000.setPC(retaddr); + return true; + } + + /** + * Note this method is always called in the execution thread + * either from the classloader, or from jumpAndLink + */ + protected static Executable makeExecutable(CodeUnit unit) { + assert r3000.isExecutionThread(); + JavaClass jclass = unit.getStage1JavaClass(immediateGenerator, true); + Class clazz = createClass(unit, jclass); + unit.stage1ClassReady(); + try { + Executable executable = (Executable) clazz.newInstance(); + Field field = clazz.getField("unit"); + field.set(executable, unit); + broker.registerLinkedFunctions(unit, true); + unit.setExecutable(executable); + return executable; + } catch (Throwable t) { + t.printStackTrace(); + throw new IllegalStateException("could not create/cast to CodeUnit " + clazz.getName()); + } + } + + public void clearCache() { + log.debug("clearCache"); + synchronized (MultiStageCompiler.class) { + broker.reset(); + ramLoaderCount++; + // we delegate to the rom loader for bios functions + ramLoader = new CompilerClassLoader("RAM classloader " + ramLoaderCount, romLoader); + synchronized (ramUnits) { + ramUnits.clear(); + } + // make sure we know that we cannot continue executing code + // in any higher nested execution levels + // todo this should be 0...? + for (int i = 1; i < contextDepth; i++) { + contexts[i].cacheStale = true; + } + } + } + + public boolean exceptionInCompiler(Throwable t) { +// System.out.println("Exception in compiler depth="+contextDepth+" "+t.getClass().getName()); + assert contextDepth >= 1; + context = contexts[--contextDepth]; + compilerToInterpreter(); + if (t instanceof ReturnFromExceptionException || t instanceof ContinueExecutionException) { + // don't need to update PC + return true; + } + + StackTraceElement trace[] = t.getStackTrace(); + int exceptionPC = -1; + int base = 0; + String className = null; + for (int i = 0; i < trace.length; i++) { + className = trace[i].getClassName(); + if (className.length() == 10 && className.startsWith("_")) { + String methodName = trace[i].getMethodName(); + if (methodName.equals(Stage1Generator.STATIC_METHOD) || methodName.startsWith(Stage1Generator.UNINLINED_METHOD_PREFIX)) { + exceptionPC = base = MiscUtil.parseHex(className.substring(2)); + int ln = trace[i].getLineNumber(); + if (ln >= 0) { + exceptionPC += ln * 4; + } + break; + // todo constant + } else if (methodName.equals(Stage1Generator.NORMAL_METHOD)) { + System.out.println("Can't get PC!"); + break; + } + } + } + if (exceptionPC != -1) { + int restartPC; + if (0 != (addressSpace.getTag(exceptionPC) & TAG_DELAY_SLOT)) { + // todo we don't currently cope with a mis-prediction in a direct jump to a delay slot instruction + // todo we need the compiler to make separate code for both cases; hopefully this is a pathological case anyway + restartPC = exceptionPC - 4; + if (log.isDebugEnabled()) { + int ci = addressSpace.internalRead32(restartPC); + log.debug("Java exception was in delay slot at " + MiscUtil.toHex(exceptionPC, 8) + + " rewinding to branch instruction " + MiscUtil.toHex(restartPC, 8) + ": " + r3000.disassemble(restartPC, ci)); + } + } else { + restartPC = exceptionPC; + } + r3000.setPC(restartPC); + if (!className.startsWith(Stage1Generator.CLASS_NAME_PREFIX)) { + // Note using exceptionPC seems to make sense, since the code for that instruction actually happens + // before the preceding branch (which itself can't have changed any constant registers anyway) + if (0 != (addressSpace.getTag(exceptionPC) & TAG_UNWRITTEN_REGS)) { + // if we get here it is because we have had a memory mis-predict, but we cannot safely + // restart, because we omitted code to update actual register values during this basic block. + // what we need to do here, is to re-examine the code unit, and figure out what the register values must have been (i.e. + // for any CR at this location, and update those). + if (log.isDebugEnabled()) { + log.debug("NEED REG WRITEBACK AT " + MiscUtil.toHex(exceptionPC, 8)); + } + // we gave regs to interpreter above so we must claim them back + interpreterToCompiler(); + fixupUnwrittenCompilerRegs(base, exceptionPC); + compilerToInterpreter(); + } + if (t.getClass() == ArrayIndexOutOfBoundsException.class) { + // could be due to mis-predicted memory access + int ci = addressSpace.internalRead32(exceptionPC); + CPUInstruction inst = r3000.decodeInstruction(ci); + if (0 != (inst.getFlags() & CPUInstruction.FLAG_MEM)) { + if (log.isDebugEnabled()) { + log.debug("***** Mispredicted memory access at " + MiscUtil.toHex(exceptionPC, 8)); + } + if (Settings.dumpMemoryMisPredictions) { + String dis = r3000.disassemble(exceptionPC, ci); + System.out.println("MemoryFail at " + MiscUtil.toHex(exceptionPC, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); + t.printStackTrace(); + System.out.println("r0 " + MiscUtil.toHex(Refs.interpreterRegs[0], 8) + " r1 " + MiscUtil.toHex(Refs.interpreterRegs[1], 8) + " r2 " + MiscUtil.toHex(Refs.interpreterRegs[2], 8) + " r3 " + MiscUtil.toHex(Refs.interpreterRegs[3], 8) + " pc " + MiscUtil.toHex(r3000.getPC(), 8)); + System.out.println("r4 " + MiscUtil.toHex(Refs.interpreterRegs[4], 8) + " r5 " + MiscUtil.toHex(Refs.interpreterRegs[5], 8) + " r6 " + MiscUtil.toHex(Refs.interpreterRegs[6], 8) + " r7 " + MiscUtil.toHex(Refs.interpreterRegs[7], 8) + " lo " + MiscUtil.toHex(r3000.getLO(), 8)); + System.out.println("r8 " + MiscUtil.toHex(Refs.interpreterRegs[8], 8) + " r9 " + MiscUtil.toHex(Refs.interpreterRegs[9], 8) + " r10 " + MiscUtil.toHex(Refs.interpreterRegs[10], 8) + " r11 " + MiscUtil.toHex(Refs.interpreterRegs[11], 8) + " hi " + MiscUtil.toHex(r3000.getHI(), 8)); + System.out.println("r12 " + MiscUtil.toHex(Refs.interpreterRegs[12], 8) + " r13 " + MiscUtil.toHex(Refs.interpreterRegs[13], 8) + " r14 " + MiscUtil.toHex(Refs.interpreterRegs[14], 8) + " r15 " + MiscUtil.toHex(Refs.interpreterRegs[15], 8)); + System.out.println("r16 " + MiscUtil.toHex(Refs.interpreterRegs[16], 8) + " r17 " + MiscUtil.toHex(Refs.interpreterRegs[17], 8) + " r18 " + MiscUtil.toHex(Refs.interpreterRegs[18], 8) + " r19 " + MiscUtil.toHex(Refs.interpreterRegs[19], 8)); + System.out.println("r20 " + MiscUtil.toHex(Refs.interpreterRegs[20], 8) + " r21 " + MiscUtil.toHex(Refs.interpreterRegs[21], 8) + " r22 " + MiscUtil.toHex(Refs.interpreterRegs[22], 8) + " r23 " + MiscUtil.toHex(Refs.interpreterRegs[23], 8)); + System.out.println("r24 " + MiscUtil.toHex(Refs.interpreterRegs[24], 8) + " r25 " + MiscUtil.toHex(Refs.interpreterRegs[25], 8) + " r26 " + MiscUtil.toHex(Refs.interpreterRegs[26], 8) + " r27 " + MiscUtil.toHex(Refs.interpreterRegs[27], 8)); + System.out.println("r28 " + MiscUtil.toHex(Refs.interpreterRegs[28], 8) + " r29 " + MiscUtil.toHex(Refs.interpreterRegs[29], 8) + " r30 " + MiscUtil.toHex(Refs.interpreterRegs[30], 8) + " r31 " + MiscUtil.toHex(Refs.interpreterRegs[31], 8)); + } + + CodeUnit unit = getCodeUnit(base); + assert unit.useStage2; + unit.stage2ClassBroken(); + return true; + } + } + } + // This exception is allowed anywhere + return t instanceof ImmediateBreakoutException; + } else { + log.warn("PC could not be calculated from stack trace, maybe you need -XX:-OmitStackTraceInFastThrow?"); + } + return false; + } + + public void interrupt() { + isInterrupted = true; + } + + public synchronized boolean addBreakpoint(int address) { + boolean ok = false; + for (int i = 0; i < breakpointLimit; i++) { + if (breakpoints[i] == -1) { + breakpoints[i] = address; + ok = true; + break; + } + } + if (!ok) { + if (breakpointLimit == MAX_BREAKPOINTS) { + return false; + } + breakpoints[breakpointLimit++] = address; + } + Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; + synchronized (map) { + for (CodeUnit unit : map.values()) { + unit.breakpointAdded(address); + } + } + // make sure we know that we should not continue executing code + // in any higher nested execution levels + for (int i = 1; i < contextDepth; i++) { + contexts[i].cacheStale = true; + } + return true; + } + + public synchronized void removeBreakpoint(int address) { + for (int i = 0; i < breakpointLimit; i++) { + if (breakpoints[i] == address) { + breakpoints[i] = -1; + if (i == breakpointLimit - 1) { + breakpointLimit--; + } + Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; + synchronized (map) { + for (CodeUnit unit : map.values()) { + unit.breakpointRemoved(address); + } + } + return; + } + } + assert false : "attempt to remove non-existent breakpoint " + MiscUtil.toHex(address, 8); + } + + public static void enumerateBreakpoints(CodeUnit unit) { + for (int i = 0; i < breakpointLimit; i++) { + if (breakpoints[i] != -1) { + unit.breakpointAdded(breakpoints[i]); + } + } + } + + public int getReg(int index) { + assert false; + return 0; + } + + public void setReg(int index, int value) { + assert false; + } + + /** + * called by the class loader when a referenced + * but not yet generated class is executed + */ + public static Class generateClass(String classname) throws ClassNotFoundException { + // Note we only expect C1 classes, as those are the only ones defined on demand + // C2 classes are generated in the background, and other classes should exist + if (classname.startsWith(Stage1Generator.CLASS_NAME_PREFIX)) { + int address = MiscUtil.parseHex(classname.substring(2)); + CodeUnit unit = getCodeUnit(address); + Executable executable = makeExecutable(unit); + // todo; what if this fails? + return executable.getClass(); + } else { + throw new IllegalStateException("findClass not called for C1: " + classname); + } + } + + protected static Class createClass(CodeUnit unit, + JavaClass jclass) { + if (AddressSpace.Util.isBIOS(unit.getBase())) { + return romLoader.createClass(jclass.getClassName(), jclass.getBytes()); + } else { + return ramLoader.createClass(jclass.getClassName(), jclass.getBytes()); + } + } + + protected static void returnToInterpreter(int address) { + compilerToInterpreter(); + r3000.setPC(address); + throw ContinueExecutionException.DONT_SKIP_CURRENT; + } + + public static void registerForStage2(CodeUnit unit) { + broker.registerForStage2(unit); + } + + protected static CodeUnit getCodeUnit(int address) { + Map map = AddressSpace.Util.isBIOS(address) ? romUnits : ramUnits; + Integer key = address; + synchronized (map) { + CodeUnit rc = map.get(key); + if (rc == null) { + rc = new CodeUnit(address); + map.put(key, rc); + } + return rc; + } + } + + protected static class CompilationBroker implements Runnable { + protected LinkedList unitsToFollow = new LinkedList(); + protected LinkedList unitsForStage1 = new LinkedList(); + protected LinkedList unitsForStage2 = new LinkedList(); + + protected FlowAnalyzer linkFlowAnalyzer = new FlowAnalyzer(); + protected Stage1Generator stage1Generator; + protected Stage2Generator stage2Generator; + protected int resetCount; + + public CompilationBroker() { + if (Settings.enableSpeculativeCompilation) { + stage1Generator = new Stage1Generator("c1specgen.out", false); + } + if (Settings.enableSecondStage) { + stage2Generator = new Stage2Generator("c2gen.out", !Settings.secondStageInBackground); + } + } + + public void begin() { + if (Settings.enableSpeculativeCompilation || + (Settings.enableSecondStage && Settings.secondStageInBackground)) { + log.info("Starting background compilation thread"); + Thread t = new Thread(this, "Background compilation"); + t.setPriority(Thread.NORM_PRIORITY - 2); // low priority + t.start(); + } + } + + public synchronized void registerLinkedFunctions(CodeUnit unit, boolean executionThread) { + if (!Settings.enableSpeculativeCompilation || unit.linksFollowed || unit.isROM()) { + return; + } + if (executionThread) { + // when called from the main compile thread, we + // put the function to the head of the list + unitsToFollow.addFirst(unit); + notify(); + } else { + // ones we follow go at end, i.e. the go behind any functions we + // have actually executed + unitsToFollow.addLast(unit); + } + } + + public synchronized void registerForStage2(CodeUnit unit) { + if (Settings.enableSecondStage) { + if (Settings.secondStageInBackground) { + unitsForStage2.add(unit); + notify(); + } else { + //System.out.println( "foreground stage2 compile " + MiscUtil.toHex( unit.getBase(), 8 ) ); + JavaClass jclass = unit.getStage2JavaClass(stage2Generator, true); + Class clazz = createClass(unit, jclass); + unit.stage2ClassReady(clazz); + } + } + } + + // todo: since we're compiling in the background it is possible we'll compile + // something that it is being overwritten... + public void run() { + try { + while (true) { + CodeUnit linkUnit = null; + CodeUnit c1Unit = null; + CodeUnit c2Unit = null; + int priorResetCount = 0; + synchronized (this) { + priorResetCount = resetCount; + if (unitsToFollow.size() > 0) { + // first priority is to follow any new links + linkUnit = (CodeUnit) unitsToFollow.removeFirst(); + } else if (unitsForStage1.size() > 0) { + // second priority is speculative compile + c1Unit = (CodeUnit) unitsForStage1.removeFirst(); + } else if (unitsForStage2.size() > 0) { + // third priority is stage 2 compile + c2Unit = (CodeUnit) unitsForStage2.removeFirst(); + } else { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + if (linkUnit != null && !linkUnit.linksFollowed) { + //System.out.println("Follow links "+MiscUtil.toHex( linkUnit.getBase(), 8)); + followLinks(linkUnit, false); + } else if (c1Unit != null) { + // simply get the java class + //System.out.println("Spec compile "+MiscUtil.toHex( c1Unit.getBase(), 8)); + // todo graham 12/21/14, I put this synchronized block in before I went on vacation 2 weeks + // todo and can't remember what it is for - seems like it would have like a comment + // todo anyway the only thing that it shares synchronization with is instruction cache clear + // todo so there must have been some issues with compilation during the clearing of other data + // todo structures. anyways, I'm leaving it as is for now since it is not time critical + // todo you'd expect this would affect the stage2 compiler too. + // todo in any case we need better exception handling here anyway, since we may be compiling + // todo R3000 code that is being overwritten prior to an instruction cache clear + synchronized (MultiStageCompiler.class) { + JavaClass jclass = c1Unit.getStage1JavaClass(stage1Generator, false); + } + } else if (c2Unit != null) { + //System.out.println("background stage2 compile "+MiscUtil.toHex( c2Unit.getBase(), 8)); + JavaClass jclass = c2Unit.getStage2JavaClass(stage2Generator, false); + // todo state machine handling here seems flaky + if (jclass != null) { + // todo fix this; + // a) resetCount is not protected; + // b) don't want to delay + // synchronized( this) { + if (resetCount == priorResetCount) { + // only create the class if we haven't been reset + Class clazz = createClass(c2Unit, jclass); + c2Unit.stage2ClassReady(clazz); + } + // } + } + } + } + } catch (Throwable t) { + log.error(this + " exits abnormally:", t); + // todo fix this + RuntimeConnections.MACHINE.resolve().close(); + } + } + + public synchronized void reset() { + unitsToFollow.clear(); + unitsForStage1.clear(); + unitsForStage2.clear(); + resetCount++; + } + + protected void followLinks(CodeUnit unit, boolean executionThread) { + FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(linkFlowAnalyzer, executionThread); + if (flowInfo != null) { + if (!unit.stage1Ready() && flowInfo.instructionCount > Settings.minSizeForSpeculativeCompile) { + //System.out.println(">>>>>>>>>>>> should compile "+MiscUtil.toHex( unit.base, 8)); + unitsForStage1.add(unit); + } + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { + for (int offset = block.offset; offset < block.offset + block.size; offset++) { + int address = flowInfo.base + offset * 4; + int ci = addressSpace.internalRead32(address); + CPUInstruction inst = r3000.decodeInstruction(ci); + int iFlags = inst.getFlags(); + if (0 != (iFlags & CPUInstruction.FLAG_LINK)) { + if (0 != (iFlags & CPUInstruction.FLAG_IMM_FAR_TARGET)) { + int target = ((address + 4) & 0xf0000000) | ((ci & 0x3fffff) << 2); + // System.out.println(MiscUtil.toHex( target, 8)+" called from "+MiscUtil.toHex( address, 8)); + if (!AddressSpace.Util.isBIOS(target)) { + registerLinkedFunctions(getCodeUnit(target), false); + } + } + } + } + } + } + // todo should we set this to true for flowInfo == null ? + unit.linksFollowed = true; + } + } + } + + /** + * for use of compiled code, since we always know what + * register an instruction uses, there's no point + * in taking the hit of an array lookup + */ + public static int reg_1; + public static int reg_2; + public static int reg_3; + public static int reg_4; + public static int reg_5; + public static int reg_6; + public static int reg_7; + public static int reg_8; + public static int reg_9; + public static int reg_10; + public static int reg_11; + public static int reg_12; + public static int reg_13; + public static int reg_14; + public static int reg_15; + public static int reg_16; + public static int reg_17; + public static int reg_18; + public static int reg_19; + public static int reg_20; + public static int reg_21; + public static int reg_22; + public static int reg_23; + public static int reg_24; + public static int reg_25; + public static int reg_26; + public static int reg_27; + public static int reg_28; + public static int reg_29; + public static int reg_30; + public static int reg_31; + public static boolean isInterrupted; + + public static final String INTERPRETER_TO_COMPILER_METHOD = "interpreterToCompiler"; + + public static void interpreterToCompiler() { + assert !ownRegs; + reg_1 = Refs.interpreterRegs[1]; + reg_2 = Refs.interpreterRegs[2]; + reg_3 = Refs.interpreterRegs[3]; + reg_4 = Refs.interpreterRegs[4]; + reg_5 = Refs.interpreterRegs[5]; + reg_6 = Refs.interpreterRegs[6]; + reg_7 = Refs.interpreterRegs[7]; + reg_8 = Refs.interpreterRegs[8]; + reg_9 = Refs.interpreterRegs[9]; + reg_10 = Refs.interpreterRegs[10]; + reg_11 = Refs.interpreterRegs[11]; + reg_12 = Refs.interpreterRegs[12]; + reg_13 = Refs.interpreterRegs[13]; + reg_14 = Refs.interpreterRegs[14]; + reg_15 = Refs.interpreterRegs[15]; + reg_16 = Refs.interpreterRegs[16]; + reg_17 = Refs.interpreterRegs[17]; + reg_18 = Refs.interpreterRegs[18]; + reg_19 = Refs.interpreterRegs[19]; + reg_20 = Refs.interpreterRegs[20]; + reg_21 = Refs.interpreterRegs[21]; + reg_22 = Refs.interpreterRegs[22]; + reg_23 = Refs.interpreterRegs[23]; + reg_24 = Refs.interpreterRegs[24]; + reg_25 = Refs.interpreterRegs[25]; + reg_26 = Refs.interpreterRegs[26]; + reg_27 = Refs.interpreterRegs[27]; + reg_28 = Refs.interpreterRegs[28]; + reg_29 = Refs.interpreterRegs[29]; + reg_30 = Refs.interpreterRegs[30]; + reg_31 = Refs.interpreterRegs[31]; +// System.out.println("i->c"); + ownRegs = true; + } + + public void restoreInterpreterState() { + compilerToInterpreter(); + } + + public static final String COMPILER_TO_INTERPRETER_METHOD = "compilerToInterpreter"; + + public static void compilerToInterpreter() { + if (ownRegs) { +// System.out.println("c->i"); + ownRegs = false; + Refs.interpreterRegs[1] = reg_1; + Refs.interpreterRegs[2] = reg_2; + Refs.interpreterRegs[3] = reg_3; + Refs.interpreterRegs[4] = reg_4; + Refs.interpreterRegs[5] = reg_5; + Refs.interpreterRegs[6] = reg_6; + Refs.interpreterRegs[7] = reg_7; + Refs.interpreterRegs[8] = reg_8; + Refs.interpreterRegs[9] = reg_9; + Refs.interpreterRegs[10] = reg_10; + Refs.interpreterRegs[11] = reg_11; + Refs.interpreterRegs[12] = reg_12; + Refs.interpreterRegs[13] = reg_13; + Refs.interpreterRegs[14] = reg_14; + Refs.interpreterRegs[15] = reg_15; + Refs.interpreterRegs[16] = reg_16; + Refs.interpreterRegs[17] = reg_17; + Refs.interpreterRegs[18] = reg_18; + Refs.interpreterRegs[19] = reg_19; + Refs.interpreterRegs[20] = reg_20; + Refs.interpreterRegs[21] = reg_21; + Refs.interpreterRegs[22] = reg_22; + Refs.interpreterRegs[23] = reg_23; + Refs.interpreterRegs[24] = reg_24; + Refs.interpreterRegs[25] = reg_25; + Refs.interpreterRegs[26] = reg_26; + Refs.interpreterRegs[27] = reg_27; + Refs.interpreterRegs[28] = reg_28; + Refs.interpreterRegs[29] = reg_29; + Refs.interpreterRegs[30] = reg_30; + Refs.interpreterRegs[31] = reg_31; + } + } + + /** + * called by compiled code, when it detects + * that isInterrupted is true + */ + public static final String INTERRUPTED_METHOD = "c_interrupted"; + + public static void c_interrupted(int address) { + r3000.setPC(address); + isInterrupted = false; + r3000.compilerInterrupted(); + // check to see if we should return to the interpreter + if (context.cacheStale) { + context.cacheStale = false; + throw ContinueExecutionException.DONT_SKIP_CURRENT; + } + if (!ownRegs) { + interpreterToCompiler(); + } + } + + /** + * called by compiled code when it executes + * an instruction whose side effects are unknown + */ + public static final String SAFE_RETURN_METHOD = "c_safe_return"; + + public static void c_safe_return() { + if (!ownRegs) { + interpreterToCompiler(); + } + } + + public static final String JUMP_METHOD = "c_jump"; + + public static int c_jump(int address, int returnAddress) { + context.nativeDepth++; + if (context.nativeDepth > Settings.maxNativeDepth) { + log.debug("STACK OVERFLOW; COLLAPSING..."); + returnToInterpreter(address); + } + //if (Debug.traceExecutionFlow) { + // System.out.println("Indirect compiled jump "+MiscUtil.toHex( address,8)+" with retaddr "+MiscUtil.toHex( returnAddress, 8)); + //} + CodeUnit unit = getCodeUnit(address); + + Executable exec = unit.getExecutable(); + if (exec == null) { + exec = makeExecutable(unit); + if (exec == null) { + returnToInterpreter(address); + } + } + int rc = exec.e(returnAddress, true); + context.nativeDepth--; + return rc; + } + + public static final String CALL_METHOD = "c_call"; + + public static void c_call(int address, int returnAddress) { + context.nativeDepth++; + if (context.nativeDepth > Settings.maxNativeDepth) { + log.debug("STACK OVERFLOW; COLLAPSING..."); + returnToInterpreter(address); + } + //if (Debug.traceExecutionFlow) { + // System.out.println("Indirect compiled jump "+MiscUtil.toHex( address,8)+" with retaddr "+MiscUtil.toHex( returnAddress, 8)); + //} + CodeUnit unit = getCodeUnit(address); + + Executable exec = unit.getExecutable(); + if (exec == null) { + exec = makeExecutable(unit); + if (exec == null) { + // this unconditionally throws exception + returnToInterpreter(address); + } + } + assert exec != null; + int rc = exec.e(returnAddress, false); + assert (rc == returnAddress) : "call to unit should always return to the right spot"; + context.nativeDepth--; + } + + public static void traceEnterUnit(int address, int returnAddress, boolean jump) { + System.out.println("Entering compiled unit " + MiscUtil.toHex(address, 8) + " retaddr=" + MiscUtil.toHex(returnAddress, 8) + " jump=" + jump + " r31=" + MiscUtil.toHex(reg_31, 8)); + } + + public static void traceCheckJumpTarget(int target, int returnAddress) { + System.out.println("Check jump target " + MiscUtil.toHex(target, 8) + ", retaddr " + MiscUtil.toHex(returnAddress, 8)); + } + + public static void traceDirectCall(int address, int returnAddress) { + System.out.println("Direct compiled call " + MiscUtil.toHex(address, 8) + " with retaddr " + MiscUtil.toHex(returnAddress, 8)); + } + + public static void traceDirectJump(int address, int returnAddress) { + System.out.println("Direct compiled jump " + MiscUtil.toHex(address, 8) + " with retaddr " + MiscUtil.toHex(returnAddress, 8)); + } + + public static void traceLeaveUnit(int address) { + System.out.println("Leaving compiled unit " + MiscUtil.toHex(address, 8)); + } + + /** + * If we got here, then we are trying to return to the interpreter due to an exception + * in stage2 compiled code, but the register values aren't all correct since the stage2 + * compiler deferred writing the values back until later and didn't expect to need the + * value at this point; this is a rare occurrence, and as such we don't mind taking the + * hit, which involves going back and figuring out what registers have constant values at this point. + *

+ * Note that being able to do this relies on the fact that we only omit writing back registers + * whose values are constant; not that we calculate at run time + * + * @param pc + */ + private void fixupUnwrittenCompilerRegs(int base, int pc) { + if (fixupStage2Generator == null) { + fixupStage2Generator = new Stage2Generator("c2fixup.out", true); + } + CodeUnit unit = getCodeUnit(base); + assert unit.useStage2; + fixupStage2Generator.fixupUnwrittenRegs(unit, pc); + } +} + +// when we execute a class for the first time, we want to follow all links and make sure we have a JavaClass +// available for large methods (note they may have been destroyed)... + + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java new file mode 100644 index 0000000..b5eb9e9 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java @@ -0,0 +1,1277 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.apache.bcel.Constants; +import org.apache.bcel.classfile.ConstantPool; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.*; +import org.apache.log4j.Logger; +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.CompilationContext; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.R3000Impl; +import org.jpsx.runtime.util.ClassUtil; +import org.jpsx.runtime.util.MiscUtil; +import org.jpsx.runtime.util.Timing; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Set; + +// todo background generators need to save the state as atomically as possible (copying the instructions basically) +// todo the FlowInfo needs to be in sync too - the fact that we share that though means that we can (in the future) +// todo quickly detect differences between the actual code and the cached flow graph (without having to regen the +// todo flow graph)... stage2 generators should probably take a hash of the code from stage 1 to make sure all is kosher +public class Stage1Generator implements CompilationContext { + public static final Logger log = Logger.getLogger("Stage1"); + + protected static final String CLASS_NAME_PREFIX = "_1"; + protected static final String STATIC_METHOD = "s"; + protected static final String NORMAL_METHOD = "e"; + protected static final String UNINLINED_METHOD_PREFIX = "_"; + + protected final FlowAnalyzer analyzer = new FlowAnalyzer(); + + // state shared with sub-class + protected final int[] opCodes = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected final CPUInstruction[] instructions = new CPUInstruction[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected final int[] regsRead = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected final int[] regsWritten = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected final int[] flags = new int[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected PrintStream codeWriter; + + private final int[] simulateRegs = new int[32]; + private final InstructionList[] instructionLists = new InstructionList[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + private final HashMap extraInstructionLists = new HashMap(); + private final InstructionHandle[] endHandles = MultiStageCompiler.Settings.printCode ? (new InstructionHandle[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]) : null; + private final InstructionList printCodeIL = new InstructionList(); + + private String codeFilename; + + private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); + + /** + * Generators are not thread safe, and they also can assert in pertinent places that they are being called from the correct + * thread, as this stuff gets a bit complicated/messy. + */ + protected final boolean intendedForExecutionThread; + + public Stage1Generator(String codeFilename, boolean intendedForExecutionThread) { + this.codeFilename = codeFilename; + this.intendedForExecutionThread = intendedForExecutionThread; + if (MultiStageCompiler.Settings.printCode) { + try { + codeWriter = new PrintStream(new FileOutputStream(codeFilename)); + } catch (IOException e) { + throw new InvalidConfigurationException("can't open " + codeFilename + " for output", e); + } + } + } + + protected final String R3000_CLASS = r3000.getClass().getName(); + protected static final String COMPILER_CLASS = MultiStageCompiler.class.getName(); + protected final String ADDRESS_SPACE_CLASS = addressSpace.getMainStaticInterfaceClassName(); + protected final String HW_CLASS = addressSpace.getHardwareStaticInterfaceClassName(); + + protected static final String EXECUTABLE_CLASS = Executable.class.getName(); + protected static final String CODEUNIT_CLASS = CodeUnit.class.getName(); + protected static final String CODEUNIT_SIGNATURE = ClassUtil.signatureOfClass(CODEUNIT_CLASS); + + protected static final int LOCAL_RETADDR = 0; + protected static final int LOCAL_JUMP = 1; + protected static final int LOCAL_PRIVATE_TEMP = 2; + protected static final int LOCAL_TEMP0 = 3; + protected static final int LOCAL_LAST = 8; + + protected static final int MINIMUM_INSTRUCTIONS_PER_METHOD = 4; + + protected static final int ALL_REGS = 0xffffffff; + protected static final int WRITABLE_REGS = 0xfffffffe; + + protected String getClassNamePrefix(CodeUnit unit) { + return CLASS_NAME_PREFIX; + } + + protected int getMaxMethodInstructionCount() { + return MultiStageCompiler.Settings.maxMethodInstructionCount; + } + + protected boolean shouldPrintCode() { + return true; + } + + protected void emitMethodHeader(InstructionList il) { + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new PUSH(contextCP, contextBase)); + il.append(new ILOAD(LOCAL_RETADDR)); + il.append(new ILOAD(LOCAL_JUMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceEnterUnit", "(IIZ)V"))); + } + FieldGen fg = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, Type.getType(CODEUNIT_SIGNATURE), "unit", contextCP); + contextClassGen.addField(fg.getField()); + il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE))); + il.append(new GETFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "useStage2", "Z"))); + IFEQ ifeq = new IFEQ(null); + il.append(ifeq); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(Stage2Generator.CLASS_NAME_PREFIX, contextBase), STATIC_METHOD, "(IZ)I"))); + il.append(new IRETURN()); + ifeq.setTarget(il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE)))); + il.append(new GETFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "count", "I"))); + il.append(new ISTORE(LOCAL_TEMP0)); + il.append(new ILOAD(LOCAL_TEMP0)); + IFLE ifle = new IFLE(null); + il.append(ifle); + il.append(new IINC(LOCAL_TEMP0, -1)); + il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE))); + il.append(new ILOAD(LOCAL_TEMP0)); + il.append(new PUTFIELD(contextCP.addFieldref(CODEUNIT_CLASS, "count", "I"))); + GOTO gt = new GOTO(null); + il.append(gt); + ifle.setTarget(il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "unit", CODEUNIT_SIGNATURE)))); + il.append(new INVOKEVIRTUAL(contextCP.addMethodref(CODEUNIT_CLASS, "countComplete", "()V"))); + gt.setTarget(il.append(new NOP())); + + } + + protected void emitBlockHeader(InstructionList il) { + contextDelaySlotEmitted = false; + } + + protected void emitBlockFooter(InstructionList il) { + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + // make sure we got all the code + int size = contextBlock.size; + if (size != 0) { + if (contextBlock.branchOut != null && contextBlock.includesDelaySlot) { + // don't want to count the delay slot, which will be output by the branch anyway + size--; + } + assert size > 0; + endHandles[contextBlock.offset + size - 1] = il.getEnd(); + } + } + contextDelaySlotEmitted = false; + } + + protected void initBlockStructures(FlowAnalyzer.FlowInfo flowInfo) { + noInterruptCheck = false; + extraInstructionLists.clear(); + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + if (block.size != 0) { + if (instructionLists[block.offset] == null) { + instructionLists[block.offset] = new InstructionList(); + } else { + // instruction list should be empty + assert null == instructionLists[block.offset].getStart(); + } + } + for (int offset = block.offset; offset < block.offset + block.size; offset++) { + int address = flowInfo.base + offset * 4; + int ci = addressSpace.internalRead32(address); + opCodes[offset] = ci; + CPUInstruction inst = r3000.decodeInstruction(ci); + instructions[offset] = inst; + int iFlags = inst.getFlags(); + flags[offset] = iFlags; + regsRead[offset] = 0; + regsWritten[offset] = 0; + if (0 != (iFlags & CPUInstruction.FLAG_READS_RS)) { + regsRead[offset] |= 1 << R3000.Util.bits_rs(ci); + } + if (0 != (iFlags & CPUInstruction.FLAG_READS_RT)) { + regsRead[offset] |= 1 << R3000.Util.bits_rt(ci); + } + if (0 != (iFlags & CPUInstruction.FLAG_WRITES_RT)) { + regsWritten[offset] |= 1 << R3000.Util.bits_rt(ci); + } + if (0 != (iFlags & CPUInstruction.FLAG_WRITES_RD)) { + regsWritten[offset] |= 1 << R3000.Util.bits_rd(ci); + } + if (MultiStageCompiler.Settings.biosInterruptWorkaround) { + if (0 != (regsWritten[offset] & 0x0c000000)) { + noInterruptCheck = true; + } + } + if (0 != (iFlags & CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE)) { + regsRead[offset] = ALL_REGS; + regsWritten[offset] |= WRITABLE_REGS; + } else if (0 != (iFlags & CPUInstruction.FLAG_LINK)) { + regsRead[offset] = ALL_REGS; + regsWritten[offset] |= ~MultiStageCompiler.Settings.savedOnCallRegs; + } + regsWritten[offset] &= WRITABLE_REGS; + } + } + if (MultiStageCompiler.Settings.biosInterruptWorkaround && noInterruptCheck) { + if (log.isDebugEnabled()) { + log.debug("*** BIOS BUG WORKAROUND FOR " + MiscUtil.toHex(flowInfo.base, 8)); + } + } + } + + public String getClassName(String prefix, int base) { + return prefix + MiscUtil.toHex(base, 8); + } + + protected void emitICodeUnitMethods() { + contextClassGen.addInterface(EXECUTABLE_CLASS); + InstructionList il = new InstructionList(); + MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.INT, new Type[]{Type.INT, Type.BOOLEAN}, new String[]{"retAddr", "jump"}, "e", contextClassGen.getClassName(), il, contextCP); + + il.append(new ILOAD(1)); + il.append(new ILOAD(2)); + il.append(new INVOKESTATIC(contextCP.addMethodref(contextClassGen.getClassName(), STATIC_METHOD, "(IZ)I"))); + il.append(new IRETURN()); + mg.setMaxLocals(); + mg.setMaxStack(); + contextClassGen.addMethod(mg.getMethod()); + il.dispose(); + } + + protected void emitMethods(FlowAnalyzer.FlowInfo flowInfo) { + emitICodeUnitMethods(); + emitStaticExecuteMethod(flowInfo); + } + + protected void emitStaticExecuteMethod(FlowAnalyzer.FlowInfo flowInfo) { + InstructionList methodIL = new InstructionList(); + MethodGen mg = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, Type.INT, new Type[]{Type.INT, Type.BOOLEAN}, new String[]{"retAddr", "jump"}, STATIC_METHOD, contextClassGen.getClassName(), methodIL, contextCP); + + if (R3000Impl.Settings.skipShell && !R3000Impl.shellHit && contextBase == 0x80030000) { + R3000Impl.shellHit = true; + methodIL.append(new ILOAD(LOCAL_RETADDR)); + methodIL.append(new IRETURN()); + } else { + emitDebugs(methodIL); + + emitMethodHeader(methodIL); + + Set methodBlocks = CollectionsFactory.newHashSet(); + + int maxCount = getMaxMethodInstructionCount(); + if (flowInfo.instructionCount > maxCount) { + if (log.isDebugEnabled()) { + log.debug("Too many instructions in " + Integer.toHexString(flowInfo.base)); + } + // too many instructions, we want to sort basic blocks + // by size, and choose to inline the code up to the branch + // from each one + //System.out.println("sorting for "+flowInfo.instructionCount); + FlowAnalyzer.BasicBlock sizedBlocks[] = new FlowAnalyzer.BasicBlock[flowInfo.blockCount]; + int index = 0; + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + sizedBlocks[index++] = block; + } + Arrays.sort(sizedBlocks, new Comparator() { + public int compare(FlowAnalyzer.BasicBlock b1, FlowAnalyzer.BasicBlock b2) { + return getSizeWithoutBranch(b2) - getSizeWithoutBranch(b1); + } + }); + int instructionCount = flowInfo.instructionCount; + for (int i = 0; i < sizedBlocks.length && instructionCount > maxCount; i++) { + int size = getSizeWithoutBranch(sizedBlocks[i]); + if (size < MINIMUM_INSTRUCTIONS_PER_METHOD) { + break; + } + //System.out.println("collapsing block "+(i+1)+"/"+sizedBlocks.length+" size "+sizedBlocks[i].size); + instructionCount -= size; + methodBlocks.add(sizedBlocks[i]); + if (log.isDebugEnabled()) { + log.debug(" must call to "+sizedBlocks[i]+" size "+getSizeWithoutBranch(sizedBlocks[i])); + } + } + //System.out.println("final instruction count "+instructionCount); + } + + contextMethodGen = mg; + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + contextBlock = block; + if (MultiStageCompiler.Settings.printRare && block.branchOut != null && !block.includesDelaySlot) { + System.out.println(block); + } + + InstructionList blockIL = getInstructionList(block); + emitBlockHeader(blockIL); + if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { + int size = block.size; + if (block.branchOut != null && block.includesDelaySlot) { + // don't want to count the delay slot, which will be output by the branch anyway + size--; + } + if (methodBlocks.contains(block)) { + String methodname = UNINLINED_METHOD_PREFIX + block.offset; + InstructionList innerMethodIL = new InstructionList(); + MethodGen mgInner = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, Type.VOID, new Type[]{}, new String[]{}, methodname, contextClassGen.getClassName(), innerMethodIL, contextCP); + // emit head of block + int headSize = getSizeWithoutBranch(block); + contextMethodGen = mgInner; + emitCode(innerMethodIL, 0, headSize); + innerMethodIL.append(new RETURN()); + contextMethodGen = mg; + addMethod(mgInner); + blockIL.append(new INVOKESTATIC(contextCP.addMethodref(contextClassGen.getClassName(), methodname, "()V"))); + if (headSize != size) { + // emit branch part + emitCode(blockIL, headSize, size); + } + } else { + // emit whole block + emitCode(blockIL, 0, size); + } + if (block.branchOut != null && !block.includesDelaySlot && block.flowOut != null) { + // if we are missing our delay slot, and flow into the next block, it + // should be a single instruction which just flows into the next block + // (i.e. a delay slot instruction) + assert (block.flowOut.size == 1); + assert (block.flowOut.branchOut == null); + assert (block.flowOut.flowOut != null); + // we want to skip it, since we've already executed the delay slot + blockIL.append(new GOTO(getStartHandle(block.flowOut.flowOut))); + } + } else if (block.type == FlowAnalyzer.BasicBlock.JUMP_WRAPPER) { + emitJump(blockIL, contextBase + (block.offset << 2)); + } + emitBlockFooter(blockIL); + } + + // block instructions are only appended after all code is generated, since append removes + // the instructions from the block instruction lists + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + methodIL.append(getInstructionList(block)); + } + methodIL.append(new ILOAD(LOCAL_RETADDR)); + methodIL.append(new IRETURN()); + + } + + addMethod(mg); + } + + protected InstructionList getInstructionList(FlowAnalyzer.BasicBlock block) { + if (block.size != 0) { + return instructionLists[block.offset]; + } else { + InstructionList rc = (InstructionList) extraInstructionLists.get(block); + if (rc == null) { + rc = new InstructionList(); + extraInstructionLists.put(block, rc); + } + return rc; + } + } + + protected void disassemble(int index) { + int address = contextBase + (index << 2); + String prefix = ""; + if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_DELAY_SLOT)) { + prefix += "D"; + } else { + prefix += " "; + } + String prefix1 = ""; + String suffix = ""; + int ci = opCodes[index]; + String dis = r3000.disassemble(address, ci); + codeWriter.println(" " + prefix + " " + prefix1 + " " + MiscUtil.toHex(address, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis + suffix); + } + + protected void addMethod(MethodGen mg) { + mg.setMaxLocals(LOCAL_LAST); + mg.setMaxStack(); + Method m = mg.getMethod(); + if (m.getCode().getCode().length > 8000) { + if (log.isDebugEnabled()) { + log.debug(contextClassGen.getClassName() + "." + m.getName() + " has " + (m.getCode().getCode().length) + " bytes bytcode"); + } + } + contextClassGen.addMethod(m); + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + printCodeIL.append(mg.getInstructionList()); + } else { + mg.getInstructionList().dispose(); + } + } + + protected void emitConstructor() { + contextClassGen.addEmptyConstructor(Constants.ACC_PUBLIC); + } + + // PERF:addr:blocks:instructions:flow:initBlock:emitMethods:getJavaClass:createClass + + // can return null if not on execution thread for garbage looking code + public JavaClass createJavaClass(CodeUnit unit, boolean executionThread) { + return createJavaClass(unit, getClassName(getClassNamePrefix(unit), unit.getBase()), executionThread); + } + + // can return null if not on execution thread for garbage looking code + public JavaClass createJavaClass(CodeUnit unit, String classname, boolean executionThread) { + assert executionThread == this.intendedForExecutionThread; + contextUnit = unit; + contextBase = unit.getBase(); + contextClassGen = new ClassGen(classname, "java.lang.Object", + "", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null); + contextCP = contextClassGen.getConstantPool(); + + emitConstructor(); + long t0 = 0; + StringBuilder perf = null; + if (MultiStageCompiler.Settings.statistics) { + perf = new StringBuilder(); + t0 = Timing.nanos(); + } + FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(analyzer, executionThread);//analyzer.buildFlowGraph( contextBase, getMaxMethodInstructionCount()); + if (flowInfo == null) { + return null; + } + contextUnitIsGarbage = false; + if (MultiStageCompiler.Settings.statistics) { + long t1 = Timing.nanos() - t0; + perf.append("PERF:"); + perf.append(MiscUtil.toHex(unit.getBase(), 8)); + perf.append(':'); + perf.append(flowInfo.blockCount); + perf.append(':'); + perf.append(flowInfo.instructionCount); + perf.append(':'); + perf.append(t1); + t0 = Timing.nanos(); + } + initBlockStructures(flowInfo); + if (MultiStageCompiler.Settings.statistics) { + long t1 = Timing.nanos() - t0; + perf.append(':'); + perf.append(t1); + t0 = Timing.nanos(); + } + emitMethods(flowInfo); + if (contextUnitIsGarbage) { + return null; + } + if (MultiStageCompiler.Settings.statistics) { + long t1 = Timing.nanos() - t0; + perf.append(':'); + perf.append(t1); + t0 = Timing.nanos(); + } + JavaClass jclass = contextClassGen.getJavaClass(); + if (MultiStageCompiler.Settings.statistics) { + long t1 = Timing.nanos() - t0; + perf.append(':'); + perf.append(t1); + } + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + ConstantPool cp = jclass.getConstantPool(); + codeWriter.println(getClassNamePrefix(unit) + " unit at " + MiscUtil.toHex(contextBase, 8)); + InstructionHandle h = printCodeIL.getStart(); + InstructionHandle hLast = null; + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + codeWriter.println(" " + block); + + int size = block.size; + if (block.branchOut != null && block.includesDelaySlot) { + // don't want to count the delay slot, which will be output by the branch anyway + size--; + } + for (int index = block.offset; index < block.offset + size; index++) { + disassemble(index); + if (0 != (flags[index] & CPUInstruction.FLAG_BRANCH)) { + // disassemble delay slot + disassemble(index + 1); + } + InstructionHandle hEnd = endHandles[index]; + assert (hEnd != null); + if (hEnd != hLast) { + while (h != null) { + String bo = "" + h.getPosition(); + while (bo.length() < 5) { + bo = " " + bo; + } + codeWriter.println(bo + " " + h.getInstruction().toString(cp)); + hLast = h; + h = h.getNext(); + if (hLast == hEnd) + break; + } + } + if (0 != (flags[index] & CPUInstruction.FLAG_BRANCH)) { + // skip delay slot + index++; + } + } + } + printCodeIL.dispose(); + } + + if (MultiStageCompiler.Settings.saveClasses) { + try { + jclass.dump(codeFilename + classname + ".class"); + } catch (IOException ioe) { + } + } + return jclass; + } + + protected int getSizeWithoutBranch(FlowAnalyzer.BasicBlock b) { + if (b.branchOut == null) { + return b.size; + } else { + return b.branchOffset - b.offset; + } + } + + protected void emitCode(InstructionList il, int startOffset, int endOffset) { + startOffset += contextBlock.offset; + endOffset += contextBlock.offset; + for (contextOffset = startOffset; contextOffset < endOffset && !contextUnitIsGarbage; contextOffset++) { + // skip the instruction after an instruction which emitted a delay slot + if (contextDelaySlotEmitted) { + contextDelaySlotEmitted = false; + } else { + emitContextInstruction(il); + } + } + } + + protected void emitDebugs(InstructionList il) { + if (contextBase == 0xbfc018e0) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugPrintf", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + + if (!R3000Impl.Settings.debugBIOS) return; + + // todo, register functions s.t. the compiler can insert these also! + if (contextBase == 0x00001b44) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugDeliverEvent", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + + if (contextBase == 0xa0) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugA0", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + + if (contextBase == 0xb0) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugB0", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + + if (contextBase == 0xc0) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "debugC0", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + } + + public void emitContextInstruction(InstructionList il) { + contextAddress = contextBase + (contextOffset << 2); + + InstructionHandle endHandle = null; + + if (MultiStageCompiler.Settings.addLineNumbers) { + endHandle = il.getEnd(); + } + + if (MultiStageCompiler.Settings.profiling && contextOffset == contextBlock.offset) { + il.append(new PUSH(contextCP, contextAddress)); + il.append(new INVOKESTATIC(contextCP.addMethodref("jsx.core.NativeCompiler", "blockUsed", "(I)V"))); + } + + if (MultiStageCompiler.Settings.megaTrace) { + il.append(new PUSH(contextCP, contextAddress)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "dumpState", "(I)V"))); + } + + if (contextBlock.branchOut != null && contextBlock.branchOffset == contextOffset) { + assert 0 != (flags[contextOffset] & CPUInstruction.FLAG_BRANCH) : contextBlock + " " + MiscUtil.toHex(contextAddress, 8); + if (contextBlock.branchOut.offset <= contextBlock.offset) { + emitBreakoutCheck(il); + } + } + + // certain instructions require us to set the PC correctly + // todo check for delay slot! + if (MultiStageCompiler.Settings.debugPC || 0 != (flags[contextOffset] & (CPUInstruction.FLAG_REFERENCES_PC | + CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE | + CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE))) { + il.append(new PUSH(contextCP, contextAddress)); + il.append(new PUTSTATIC(contextCP.addFieldref(R3000_CLASS, "reg_pc", "I"))); + } + + emitContextInstructionGuts(il); + + if (0 != (flags[contextOffset] & CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE)) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + + if (MultiStageCompiler.Settings.addLineNumbers) { + // no point if we didn't add any code + if (endHandle != il.getEnd()) { + InstructionHandle first = endHandle == null ? il.getStart() : endHandle.getNext(); + // note the TAG_DELAY_SLOT will allow the exception handling code that uses the line numbers + // to know to re-execute from the previous instruction, however that doesn't take care of the + // case of code that branches directly to a delay slot. + // todo we don't handle that well today, but should be making separate basic blocks, and + // todo we could mark the code for that case with a special line number (e.g. very big) + // todo to tell the exception handling code not to step back + contextMethodGen.addLineNumber(first, contextOffset); + } + } + + if (contextIsDelaySlot) { + addressSpace.orTag(contextAddress, MultiStageCompiler.TAG_DELAY_SLOT); + } + + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + endHandle = il.getEnd(); + if (endHandle == null) endHandle = il.append(new NOP()); + endHandles[contextOffset] = endHandle; + } + } + + protected void emitBreakoutCheck(InstructionList il) { + if (!noInterruptCheck) { + // todo delay slot + il.append(new GETSTATIC(contextCP.addFieldref(COMPILER_CLASS, "isInterrupted", "Z"))); + IFEQ ieq = new IFEQ(null); + il.append(ieq); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERRUPTED_METHOD, "(I)V"))); + ieq.setTarget(il.append(new NOP())); + } + } + + protected void emitContextInstructionGuts(InstructionList il) { + // should simulate instructions which just read r0 + if (regsRead[contextOffset] == 1 && 0 != (flags[contextOffset] & CPUInstruction.FLAG_SIMULATABLE) && instructions[contextOffset].simulate(opCodes[contextOffset], simulateRegs)) { + for (int i = 1; i < 32; i++) { + if ((regsWritten[contextOffset] & (1 << i)) != 0) { + il.append(new PUSH(contextCP, simulateRegs[i])); + emitSetReg(il, i); + } + } + } else { + instructions[contextOffset].compile(this, contextAddress, opCodes[contextOffset], il); + } + } + + public InstructionHandle getStartHandle(FlowAnalyzer.BasicBlock block) { + InstructionHandle rc = getInstructionList(block).getStart(); + if (rc == null) { + rc = getInstructionList(block).append(new NOP()); + } + return rc; + } + // ------------- ICompilationContext + + // todo remove this, and pass to compiler + + public ConstantPoolGen getConstantPoolGen() { + return contextCP; + } + + protected boolean noInterruptCheck; + protected FlowAnalyzer.BasicBlock contextBlock; + protected int contextBase; + protected int contextOffset; + protected int contextAddress; + protected MethodGen contextMethodGen; + protected ConstantPoolGen contextCP; + protected ClassGen contextClassGen; + protected AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); + protected boolean contextDelaySlotEmitted; + protected boolean contextIsDelaySlot; + protected CodeUnit contextUnit; + protected boolean contextUnitIsGarbage; + + protected void invokeStaticMethod(java.lang.reflect.Method method) { + + } + + public void emitInterpretedInstruction(InstructionList il, int ci, String clazz, String method) { + + if (0 != (flags[contextOffset] & CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE)) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + } else { + int readsReg = getReadsReg(); + for (int r = 1; r < 32; r++) { + if (0 != (readsReg & (1 << r))) { + // R3000Impl.regs[r] = CompiledR3000.reg_r; + il.append(new GETSTATIC(contextCP.addFieldref(R3000_CLASS, "regs", "[I"))); + + il.append(new PUSH(contextCP, r)); + if (0 != (getConstantRegs() & (1 << r))) { + il.append(new PUSH(contextCP, getRegValue(r))); + } else { + emitGetReg(il, r); + } + il.append(new IASTORE()); + } + } + } + + il.append(new PUSH(contextCP, ci)); + il.append(new INVOKESTATIC(contextCP.addMethodref(clazz, method, "(I)V"))); + + if (0 != (flags[contextOffset] & (CPUInstruction.FLAG_REQUIRES_COMPLETE_INTERPRETER_STATE))) { + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } else { + int writesReg = getWritesReg(); + for (int r = 1; r < 32; r++) { + if (0 != (writesReg & (1 << r))) { + // CompiledR3000.reg_r = R3000Impl.reg[r]; + il.append(new GETSTATIC(contextCP.addFieldref(R3000_CLASS, "regs", "[I"))); + il.append(new PUSH(contextCP, r)); + il.append(new IALOAD()); + emitSetReg(il, r); + } + } + } + } + + public void emitGetReg(InstructionList il, int reg) { + il.append(new GETSTATIC(contextCP.addFieldref(COMPILER_CLASS, "reg_" + reg, "I"))); + } + + public void emitSetReg(InstructionList il, int reg) { + assert reg != 0; + il.append(new PUTSTATIC(contextCP.addFieldref(COMPILER_CLASS, "reg_" + reg, "I"))); + } + + public int getRegValue(int reg) { + assert reg == 0; + return 0; + } + + public int getConstantRegs() { + return 1; + } + + public int getWritesReg() { + return regsWritten[contextOffset]; + } + + public int getReadsReg() { + return regsRead[contextOffset]; + } + + public void emitJump(InstructionList il, int address) { + il.append(new PUSH(contextCP, address)); + emitJump(il); + } + + public void emitJump(InstructionList il) { + // this is decompilable (uses local var target) + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + InstructionHandle loop = il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new ILOAD(LOCAL_RETADDR)); + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new ILOAD(LOCAL_RETADDR)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceCheckJumpTarget", "(II)V"))); + } + IF_ICMPEQ icmpeq = new IF_ICMPEQ(null); + il.append(icmpeq); + + il.append(new ILOAD(LOCAL_JUMP)); + IFEQ ieq = new IFEQ(null); + il.append(ieq); + + icmpeq.setTarget(il.append(new ILOAD(LOCAL_PRIVATE_TEMP))); + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new PUSH(contextCP, contextBase)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceLeaveUnit", "(I)V"))); + } + il.append(new IRETURN()); + ieq.setTarget(il.append(new ILOAD(LOCAL_PRIVATE_TEMP))); + il.append(new ILOAD(LOCAL_RETADDR)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.JUMP_METHOD, "(II)I"))); + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new GOTO(loop)); + } + + public InstructionHandle getBranchTarget(int address) { + if (!intendedForExecutionThread && contextBlock.branchOut == null) { + contextUnitIsGarbage = true; + // a branch to ourselves + return getStartHandle(contextBlock); + } + assert contextBlock.branchOut != null : "null branch target - wanted " + MiscUtil.toHex(address, 8) + " base = " + MiscUtil.toHex(contextBlock.base, 8); + assert contextBase + (contextBlock.branchOut.offset << 2) == address : + contextBlock + ": Expected branch target " + MiscUtil.toHex(contextBase + (contextBlock.branchOut.offset << 2), 8) + " != actual " + MiscUtil.toHex(address, 8); + + if (MultiStageCompiler.Settings.printRare && address == contextAddress) { + System.out.println("Branch to self at " + MiscUtil.toHex(address, 8)); + } + return getStartHandle(contextBlock.branchOut); + } + + public void emitCall(InstructionList il, int address, int retAddr) { + if (R3000Impl.Settings.dumpRegsOnCall && R3000Impl.shouldDumpRegs(address)) { + il.append(new PUSH(contextCP, address)); + il.append(new PUTSTATIC(contextCP.addFieldref(R3000_CLASS, "reg_pc", "I"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(R3000_CLASS, "dumpRegs", "()V"))); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V"))); + } + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new PUSH(contextCP, address)); + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceDirectCall", "(II)V"))); + } + + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagClearPollCounters", "()V"))); + + if (AddressSpace.Util.isBIOS(contextAddress) && !AddressSpace.Util.isBIOS(address)) { + // calling from bios to ram must be indirect... note this is probably rare. + // todo i've seen the BIOS classloader have ram classes; I wonder why + //System.out.println( "Emitting bios to ram call" ); + il.append(new PUSH(contextCP, address)); + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); + } else { + il.append(new PUSH(contextCP, retAddr)); + il.append(new PUSH(contextCP, 0)); + il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(CLASS_NAME_PREFIX, address), STATIC_METHOD, "(IZ)I"))); + il.append(new POP()); + } + } + + /** + * Used for JALR etc where the address to call is at the top + * of the JVM stack + */ + public void emitCall(InstructionList il, int retAddr) { +/* if (R3000Impl.Settings.dumpRegsOnCall) { + il.append( new DUP()); + il.append( new PUTSTATIC( contextCP.addFieldref( R3000_CLASS, "reg_pc", "I" ) ) ); + il.append( new INVOKESTATIC( contextCP.addMethodref( COMPILER_CLASS, MultiStageCompiler.COMPILER_TO_INTERPRETER_METHOD, "()V" ) ) ); + il.append( new INVOKESTATIC( contextCP.addMethodref( R3000_CLASS, "dumpRegs", "()V" ) ) ); + il.append( new INVOKESTATIC( contextCP.addMethodref( COMPILER_CLASS, MultiStageCompiler.INTERPRETER_TO_COMPILER_METHOD, "()V" ) ) ); + }*/ + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagClearPollCounters", "()V"))); + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); + } + + public void emitReadMem8(InstructionList il, int address, boolean signed) { + rr.mem = null; + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); + return; + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); + } + if (signed) { + switch (address & 3) { + case 2: + il.append(new PUSH(contextCP, 8)); + il.append(new ISHL()); + break; + case 1: + il.append(new PUSH(contextCP, 16)); + il.append(new ISHL()); + break; + case 0: + il.append(new PUSH(contextCP, 24)); + il.append(new ISHL()); + break; + } + il.append(new PUSH(contextCP, 24)); + il.append(new ISHR()); + } else { + switch (address & 3) { + case 3: + il.append(new PUSH(contextCP, 24)); + il.append(new ISHR()); + break; + case 2: + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + break; + case 1: + il.append(new PUSH(contextCP, 8)); + il.append(new ISHR()); + break; + } + il.append(new PUSH(contextCP, 0xff)); + il.append(new IAND()); + } + } + + public void emitReadMem8(InstructionList il, int reg, int offset) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead8", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); + } + + public void emitReadMem16(InstructionList il, int address, boolean signed) { + rr.mem = null; + if (0 == (address & 1)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); + return; + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + if (signed) { + if (0 == (address & 2)) { + il.append(new PUSH(contextCP, 16)); + il.append(new ISHL()); + } + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + } else { + if (0 != (address & 2)) { + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + } + il.append(new PUSH(contextCP, 0xffff)); + il.append(new IAND()); + } + } + + public void emitReadMem16(InstructionList il, int reg, int offset) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead16", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + + public void emitReadMem32(InstructionList il, int address, boolean forceAlign) { + rr.mem = null; + if (forceAlign) { + address &= ~3; + } + if (0 == (address & 3)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "_read32", "(I)I"))); + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "read32", "(I)I"))); + } + } + + public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); + } + + public void emitWriteMem8(InstructionList il, int address, InstructionList il2) { + InstructionList il3 = new InstructionList(); + emitReadMem32(il3, address, true); + switch (address & 3) { + case 0: + il3.append(new PUSH(contextCP, 0xffffff00)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new IOR()); + break; + case 1: + il3.append(new PUSH(contextCP, 0xffff00ff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new PUSH(contextCP, 8)); + il3.append(new ISHL()); + il3.append(new IOR()); + break; + case 2: + il3.append(new PUSH(contextCP, 0xff00ffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new PUSH(contextCP, 16)); + il3.append(new ISHL()); + il3.append(new IOR()); + break; + default: + il3.append(new PUSH(contextCP, 0xffffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 24)); + il3.append(new ISHL()); + il3.append(new IOR()); + } + emitWriteMem32(il, address, il3, true); + il3.dispose(); + } + + public void emitWriteMem8(InstructionList il, int reg, int offset) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8", "(II)V"))); + } + + public void emitWriteMem16(InstructionList il, int address, InstructionList il2) { + if ((address & 1) != 0) { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); + } else { + InstructionList il3 = new InstructionList(); + // il3.stack(0) = oldvalue + emitReadMem32(il3, address, true); + switch (address & 3) { + case 0: + // il3.stack(1) = mask; + il3.append(new PUSH(contextCP, 0xffff0000)); + il3.append(new IAND()); + // il3.stack(0) = maskedOldValue; + il3.append(il2); + // il3.stack(1) = newvalue; + il3.append(new PUSH(contextCP, 0xffff)); + // il3.stack(2) = mask; + il3.append(new IAND()); + // il3.stack(1) = maskedNewValue; + il3.append(new IOR()); + // il3.stack(0) = newMemValue + break; + default: + il3.append(new PUSH(contextCP, 0xffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 16)); + il3.append(new ISHL()); + il3.append(new IOR()); + } + emitWriteMem32(il, address, il3, true); + il3.dispose(); + } + } + + public void emitWriteMem16(InstructionList il, int reg, int offset) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); + } + + public void emitWriteMem32(InstructionList il, int address, InstructionList il2, boolean forceAlign) { + rr.mem = null; + if (forceAlign) { + address &= ~3; + } + if (0 == (address & 3)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(il2); + il.append(new IASTORE()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(il2); + il.append(new IASTORE()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + /* + il.append( new GETSTATIC( contextCP.addFieldref( ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append( new PUSH( contextCP, rr.offset)); + il.append( il2); + il.append( new IASTORE());*/ + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); + } else { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + } + + public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList il2, boolean forceAlign) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + if (0 == (MultiStageCompiler.Settings.usuallyRAMRegs & (1 << reg))) { + il.append(new ISTORE(LOCAL_PRIVATE_TEMP)); + il.append(new PUSH(contextCP, contextAddress)); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessWrite", "(II)V"))); + il.append(new ILOAD(LOCAL_PRIVATE_TEMP)); + } + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + + public void emitDelaySlot(InstructionList il) { + contextOffset++; + contextIsDelaySlot = true; + emitContextInstruction(il); + contextIsDelaySlot = false; + contextDelaySlotEmitted = true; + contextOffset--; + //assert 0!=(flags[contextOffset]&Instruction.FLAG_BRANCH); + //if (delaySlot==null) { + // delaySlot = new CompilationContext1( mg, contextCP); + //} + //delaySlot.compile( contextAddress+4, il); + //delaySlotEmitted = true; + } + + public final int getTempLocal(int index) { + int rc = LOCAL_TEMP0 + index; + if (rc >= LOCAL_LAST) + throw new IllegalStateException("too many locals!"); + return rc; + } + + // ---- +} \ No newline at end of file diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java new file mode 100644 index 0000000..a5cdc0e --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java @@ -0,0 +1,1255 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.emulator.compiler; + +import org.apache.bcel.Constants; +import org.apache.bcel.generic.*; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.R3000Impl; +import org.jpsx.runtime.util.MiscUtil; + +import java.util.Stack; + +// todo is this true now? + +// note while it is tempting to omit the intervening write of reg8 here, +// +// addiu r8, r4, r0 +// lw r8, r8[4] +// +// we cannot do so (unless we know the value of r4 at compile time), because +// a memory type misprediction of the memory read in the lw instruction would +// cause us to have to re-execute the second instruction in the interpreter, and we wouldn't have +// a good way to figure out the true value of r8. +// +// Note, that it might be possible to do this, but it would involve more complicated +// code to figure out what we had done when we compiled the code, and then simulate the instructions we skipped. +// +// In the meanwhile, we just cope with figuring out what registers are constant at the re-execute + +// point, and write all of those back +public class Stage2Generator extends Stage1Generator { + protected static String CLASS_NAME_PREFIX = "_2"; + + private static final int READ_TAG_MASK = (AddressSpace.TAG_RAM | + AddressSpace.TAG_SCRATCH | + AddressSpace.TAG_HW | + AddressSpace.TAG_BIOS | + AddressSpace.TAG_PAR | + AddressSpace.TAG_POLL) & 0xff; + + private int getRegsOffset = -1; + private int[] regsAtOffset = new int[32]; + private int CRAtOffset = 0; + private final AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + private final R3000 r3000 = CoreComponentConnections.R3000.resolve(); + + public Stage2Generator(String codeFilename, boolean intendedForExecutionThread) { + super(codeFilename, intendedForExecutionThread); + } + + protected String getClassNamePrefix(CodeUnit unit) { + return "_" + (2 + unit.stage2Version); + } + + protected String getNextClassNamePrefix(CodeUnit unit) { + return "_" + (3 + unit.stage2Version); + } + + protected void emitBreakoutCheck(InstructionList il) { + // write back regs before the breakout check + writeBackRegs(il, ALL_REGS); + super.emitBreakoutCheck(il); + } + + protected void emitMethodHeader(InstructionList il) { + // don't emit all the junk that Compiler1 does + FieldGen fg = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, Type.BOOLEAN, "replaced", contextCP); + contextClassGen.addField(fg.getField()); + + il.append(new GETSTATIC(contextCP.addFieldref(contextClassGen.getClassName(), "replaced", "Z"))); + IFEQ ifeq = new IFEQ(null); + il.append(ifeq); + il.append(new ILOAD(0)); + il.append(new ILOAD(1)); + il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(getNextClassNamePrefix(contextUnit), contextBase), STATIC_METHOD, "(IZ)I"))); + il.append(new IRETURN()); + ifeq.setTarget(il.append(new NOP())); + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new PUSH(contextCP, contextBase)); + il.append(new ILOAD(LOCAL_RETADDR)); + il.append(new ILOAD(LOCAL_JUMP)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceEnterUnit", "(IIZ)V"))); + } + if (false/*Debug.dumpRegsOnCall*/) { + il.append(new PUSH(contextCP, contextBase)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "dumpState", "(I)V"))); + } + } + + protected static final boolean debugCR = true; + + protected BlockInfo[] blockInfo = new BlockInfo[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + /** + * Instructions that can safely be omitted because they have constant input and the + * output can be determined by simulation + */ + protected boolean[] simulated = new boolean[MultiStageCompiler.Settings.maxR3000InstructionsPerUnit]; + protected Stack dirtyBlocks = new Stack(); + protected int visitCount; + + protected class BlockInfo { + public BlockInfo(FlowAnalyzer.BasicBlock bb) { + this.bb = bb; + } + + FlowAnalyzer.BasicBlock bb; + boolean dirty; + boolean visited; + + int ICR; + int OCR; + int[] incomingRegValues = new int[32]; + int[] outgoingRegValues = new int[32]; + + public String toString() { + return "visited " + visited + " dirty " + dirty + " ICR " + MiscUtil.toHex(ICR, 8) + " OCR " + MiscUtil.toHex(OCR, 8) + " " + bb; + } + + public void updateIncoming(final int CR, final int[] regValues) { + // incoming constant regs are ANDed with what we knew before, unless we're + // not initialized yet (ICR==0) + int newICR = ICR == 0 ? CR : (CR & ICR); + + int stillConstant = ICR & newICR; + int nowConstant = (newICR ^ ICR) & newICR; + + int mask = 2; + for (int bit = 1; bit < 32; bit++) { + if (0 != (stillConstant & mask)) { + // check that the reg value isn't different for any "constant" register, + // meaning that it isn't constant. + if (incomingRegValues[bit] != regValues[bit]) { + newICR &= ~mask; + } + } else if (0 != (nowConstant & mask)) { + incomingRegValues[bit] = regValues[bit]; + } + mask <<= 1; + } + // note we will always be dirty at least once since ICR is initially zero + if (newICR != ICR) { + ICR = newICR; + dirty = true; + dirtyBlocks.push(this); + } + assert 1 == (ICR & 1); + } + + public void visit() { + if (dirty) { + if (debugCR) { + visitCount++; + } + //System.out.println( "visit "+this); + if (!visited) { + for (int i = 1; i < 32; i++) { + outgoingRegValues[i] = incomingRegValues[i]; + } + } + int oldOCR = OCR; + OCR = ICR; + simulate(!visited); + // after the first time through OCR should always be a subset of oldOCR + assert !visited || 0 == (OCR & ~oldOCR); + assert 1 == (OCR & 1); + dirty = false; + if (!visited || OCR != oldOCR) { + visited = true; + BlockInfo bbFlow = null; + BlockInfo bbBranch = null; + int scoreFlow = -1; + int scoreBranch = -1; + + if (bb.flowOut != null && bb.flowOut.type == FlowAnalyzer.BasicBlock.NORMAL) { + bbFlow = blockInfo[bb.flowOut.offset]; + // todo score + } + if (bb.branchOut != null && bb.branchOut.type == FlowAnalyzer.BasicBlock.NORMAL) { + bbBranch = blockInfo[bb.branchOut.offset]; + // todo score + } + + + if (scoreBranch > scoreFlow) { + bbBranch.updateIncoming(OCR, outgoingRegValues); + if (bbFlow != null) { + bbFlow.updateIncoming(OCR, outgoingRegValues); + } + } else if (scoreFlow > scoreBranch) { + bbFlow.updateIncoming(OCR, outgoingRegValues); + if (bbBranch != null) { + bbBranch.updateIncoming(OCR, outgoingRegValues); + } + } else { + if (bbBranch != null) { + bbBranch.updateIncoming(OCR, outgoingRegValues); + } + if (bbFlow != null) { + bbFlow.updateIncoming(OCR, outgoingRegValues); + } + } + } + } + } + + protected void simulateCalculate(int offset) { + if (0 != (flags[offset] & CPUInstruction.FLAG_SIMULATABLE) && + regsRead[offset] == (regsRead[offset] & OCR) && + instructions[offset].simulate(opCodes[offset], outgoingRegValues)) { + simulated[offset] = true; + OCR |= regsWritten[offset]; + } else { + OCR &= ~regsWritten[offset]; + simulated[offset] = false; + } + } + + protected void simulateNoCalculate(int offset) { + if (simulated[offset]) { + if (regsRead[offset] == (regsRead[offset] & OCR)) { + OCR |= regsWritten[offset]; + } else { + OCR &= ~regsWritten[offset]; + simulated[offset] = false; + } + } else { + OCR &= ~regsWritten[offset]; + } + } + + protected void simulate(boolean calculateValues) { + if (calculateValues) { + for (int offset = bb.offset; offset < bb.offset + bb.size; offset++) { + // special case to figure out constant regs at a particular location + if (offset == getRegsOffset) { + for (int i = 0; i < 32; i++) regsAtOffset[i] = outgoingRegValues[i]; + CRAtOffset = OCR; + } + if (0 != (flags[offset] & CPUInstruction.FLAG_BRANCH)) { + // re-order so that + simulateCalculate(offset + 1); + simulateCalculate(offset); + offset++; + } else { + simulateCalculate(offset); + } + } + } else { + for (int offset = bb.offset; offset < bb.offset + bb.size; offset++) { + // special case to figure out constant regs at a particular location + if (offset == getRegsOffset) { + for (int i = 0; i < 32; i++) regsAtOffset[i] = outgoingRegValues[i]; + CRAtOffset = OCR; + } + if (0 != (flags[offset] & CPUInstruction.FLAG_BRANCH)) { + // re-order so that + simulateNoCalculate(offset + 1); + simulateNoCalculate(offset); + offset++; + } else { + simulateNoCalculate(offset); + } + } + } + } + } + + + protected void initBlockStructures(FlowAnalyzer.FlowInfo flowInfo) { + super.initBlockStructures(flowInfo); + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { + blockInfo[block.offset] = new BlockInfo(block); + } + } + if (debugCR) { + visitCount = 0; + } + assert (dirtyBlocks.isEmpty()); + blockInfo[0].updateIncoming(1, new int[32]); + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + codeWriter.println("..."); + } + while (!dirtyBlocks.isEmpty()) { + ((BlockInfo) dirtyBlocks.pop()).visit(); + } + if (MultiStageCompiler.Settings.printCode && shouldPrintCode()) { + if (debugCR) { + codeWriter.println("CR took " + visitCount + " iterations for " + flowInfo.blockCount + " blocks: " + (visitCount / (double) flowInfo.blockCount)); + for (FlowAnalyzer.BasicBlock block = flowInfo.root; block != null; block = block.next) { + if (block.type == FlowAnalyzer.BasicBlock.NORMAL) { + BlockInfo info = blockInfo[block.offset]; + codeWriter.println("--- " + info); + for (int offset = block.offset; offset < block.offset + block.size; offset++) { + int address = flowInfo.base + offset * 4; + int ci = addressSpace.internalRead32(address); + String debug = simulated[offset] ? "* " : " "; + debug += MiscUtil.toHex(address, 8) + " " + r3000.disassemble(address, ci); + codeWriter.println(debug); + } + } + } + } + } + } + + protected void emitBlockHeader(InstructionList il) { + if (contextBlock.type == FlowAnalyzer.BasicBlock.NORMAL) { + BlockInfo blockInfo = this.blockInfo[contextBlock.offset]; + contextRegValues = blockInfo.incomingRegValues; + contextCR = blockInfo.ICR; + // ICR is initialized to zero, so code that is never reached needs to have r0 set + if (contextCR == 0 && !blockInfo.visited) { + contextCR = 1; + } + assert 1 == (contextCR & 1); + contextUnwrittenRegs = 0; + } + super.emitBlockHeader(il); + } + + protected void emitBlockFooter(InstructionList il) { + writeBackRegs(il, ALL_REGS); + super.emitBlockFooter(il); + } + + protected void emitContextInstructionGuts(InstructionList il) { + if (0 != (flags[contextOffset] & (CPUInstruction.FLAG_MAY_RESTORE_INTERPRETER_STATE))) { + writeBackRegs(il, ALL_REGS); + } + // note this function would be pretty broken if branch instructions were simulatable! + if (simulated[contextOffset]) { + instructions[contextOffset].simulate(opCodes[contextOffset], contextRegValues); +/* if (printCode && shouldPrintCode()) { + InstructionHandle endHandle = il.getEnd(); + if (endHandle == null) { + endHandle = il.append( new NOP() ); + } + endHandles[contextOffset] = endHandle; + }*/ + contextUnwrittenRegs |= regsWritten[contextOffset]; + contextCR |= regsWritten[contextOffset]; + } else { + // todo fix this; we only need to write back regs which aren't constant (unless the instruction + // doesn't observe constant regs) + writeBackRegs(il, regsRead[contextOffset]); + if (contextUnwrittenRegs != 0) { + // record the fact that we have unwritten regs + addressSpace.orTag(contextAddress, MultiStageCompiler.TAG_UNWRITTEN_REGS); + } + instructions[contextOffset].compile(this, contextAddress, opCodes[contextOffset], il); + contextUnwrittenRegs &= ~regsWritten[contextOffset]; + assert 0 == (regsWritten[contextOffset] & 1); + contextCR &= ~regsWritten[contextOffset]; + } + // write back registers before call/branch + if (contextIsDelaySlot) { + writeBackRegs(il, ALL_REGS); + } + } + + protected void writeBackRegs(InstructionList il, int regs) { + int toWrite = contextUnwrittenRegs & regs; + if (toWrite != 0) { + for (int reg = 1; reg < 32; reg++) { + if (0 != (toWrite & (1 << reg))) { + il.append(new PUSH(contextCP, contextRegValues[reg])); + emitSetReg(il, reg); + } + } + contextUnwrittenRegs &= ~regs; + } + } + + protected int[] contextRegValues; + protected int contextCR; + protected int contextUnwrittenRegs; + + public int getRegValue(int reg) { + assert 0 != (contextCR & (1 << reg)); + return contextRegValues[reg]; + } + + public int getConstantRegs() { + assert (1 == (contextCR & 1)); + return contextCR; + } + + protected void disassemble(int index) { + int address = contextBase + (index << 2); + String prefix = ""; + if (simulated[index]) { + prefix = "X"; + } else { + prefix = " "; + } + // graham 12/23/14 commented this out as it makes no sense contextCR is not necessarily the constant registers for this instruction +// if (regsRead[index] == (contextCR & regsRead[index])) { +// prefix += "C"; +// } else { +// prefix += " "; +// } + if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_UNWRITTEN_REGS)) { + prefix += ">"; + } else { + prefix += " "; + } + if (0 != (addressSpace.getTag(address) & MultiStageCompiler.TAG_DELAY_SLOT)) { + prefix += "D"; + } else { + prefix += " "; + } + String prefix1 = ""; + String suffix = ""; + int ci = opCodes[index]; + String dis = r3000.disassemble(address, ci); + codeWriter.println(" " + prefix + " " + prefix1 + " " + MiscUtil.toHex(address, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis + suffix); + } + + public void emitCall(InstructionList il, int address, int retAddr) { + if (R3000Impl.Settings.traceExecutionFlow) { + il.append(new PUSH(contextCP, address)); + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, "traceDirectCall", "(II)V"))); + } + + if (AddressSpace.Util.isBIOS(contextAddress) && !AddressSpace.Util.isBIOS(address)) { + // calling from bios to ram must be indirect... note this is probably rare. + System.out.println("Emitting bios to ram call"); + il.append(new PUSH(contextCP, address)); + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); + } else { + il.append(new PUSH(contextCP, retAddr)); + il.append(new PUSH(contextCP, 0)); + il.append(new INVOKESTATIC(contextCP.addMethodref(getClassName(Stage1Generator.CLASS_NAME_PREFIX, address), STATIC_METHOD, "(IZ)I"))); + il.append(new POP()); + } + } + + /** + * Used for JALR etc where the address to call is at the top + * of the JVM stack + */ + public void emitCall(InstructionList il, int retAddr) { + il.append(new PUSH(contextCP, retAddr)); + il.append(new INVOKESTATIC(contextCP.addMethodref(COMPILER_CLASS, MultiStageCompiler.CALL_METHOD, "(II)V"))); + } + + public void emitReadMem8(InstructionList il, int address, boolean signed) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // we must do tag==0 since this means we haven't executed this statement yet + if (tag == 0 || 0 != (tag & AddressSpace.TAG_POLL)) { + il.append(new PUSH(contextCP, address)); + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll8", "(I)V"))); + } + rr.mem = null; + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); + return; + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); + } + if (signed) { + switch (address & 3) { + case 2: + il.append(new PUSH(contextCP, 8)); + il.append(new ISHL()); + break; + case 1: + il.append(new PUSH(contextCP, 16)); + il.append(new ISHL()); + break; + case 0: + il.append(new PUSH(contextCP, 24)); + il.append(new ISHL()); + break; + } + il.append(new PUSH(contextCP, 24)); + il.append(new ISHR()); + } else { + switch (address & 3) { + case 3: + il.append(new PUSH(contextCP, 24)); + il.append(new ISHR()); + break; + case 2: + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + break; + case 1: + il.append(new PUSH(contextCP, 8)); + il.append(new ISHR()); + break; + } + il.append(new PUSH(contextCP, 0xff)); + il.append(new IAND()); + } + } + + public void emitReadMem8(InstructionList il, int reg, int offset) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + if (0 == tag || 0 != (tag & AddressSpace.TAG_POLL)) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll8", "(I)V"))); + tag &= ~AddressSpace.TAG_POLL; + } + switch (tag) { + case AddressSpace.TAG_RAM: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Ram", "(I)I"))); + break; + case AddressSpace.TAG_SCRATCH: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Scratch", "(I)I"))); + break; + case AddressSpace.TAG_BIOS: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8Bios", "(I)I"))); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read8", "(I)I"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read8", "(I)I"))); + } + } + + public void emitReadMem16(InstructionList il, int address, boolean signed) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // we must do tag==0 since this means we haven't executed this statement yet + if (tag == 0 || 0 != (tag & AddressSpace.TAG_POLL)) { + il.append(new PUSH(contextCP, address)); + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll16", "(I)V"))); + } + rr.mem = null; + if (0 == (address & 1)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); + return; + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + if (signed) { + if (0 == (address & 2)) { + il.append(new PUSH(contextCP, 16)); + il.append(new ISHL()); + } + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + } else { + if (0 != (address & 2)) { + il.append(new PUSH(contextCP, 16)); + il.append(new ISHR()); + } + il.append(new PUSH(contextCP, 0xffff)); + il.append(new IAND()); + } + } + + public void emitReadMem16(InstructionList il, int reg, int offset) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + if (0 == tag || 0 != (tag & AddressSpace.TAG_POLL)) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll16", "(I)V"))); + tag &= ~AddressSpace.TAG_POLL; + } + switch (tag) { + case AddressSpace.TAG_RAM: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Ram", "(I)I"))); + break; + case AddressSpace.TAG_SCRATCH: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Scratch", "(I)I"))); + break; + case AddressSpace.TAG_BIOS: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16Bios", "(I)I"))); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read16", "(I)I"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read16", "(I)I"))); + } + } + + public void emitReadMem32(InstructionList il, int address, boolean forceAlign) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // we must do tag==0 since this means we haven't executed this statement yet + if (tag == 0) { + // this only calls _checkPoll32 sometimes + il.append(new PUSH(contextCP, contextAddress)); + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); + } else if (0 != (tag & AddressSpace.TAG_POLL)) { + il.append(new PUSH(contextCP, address)); + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll32", "(I)V"))); + } + rr.mem = null; + if (forceAlign) { + address &= ~3; + } + if (0 == (address & 3)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(new IALOAD()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read32", "(I)I"))); + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); + } + } + + public void emitReadMem32(InstructionList il, int reg, int offset, boolean forceAlign) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + // we must do tag==0 since this means we haven't executed this statement yet + if (tag == 0) { + il.append(new PUSH(contextCP, contextAddress)); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + // this only calls _checkPoll32 sometimes + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_tagAddressAccessRead32", "(II)V"))); + } else if (0 != (tag & AddressSpace.TAG_POLL)) { + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + // todo note this only detects REALLY tight polling; we'd be better off waiting to get a tag somehow (de-optimize perhaps) + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_checkPoll32", "(I)V"))); + tag &= ~AddressSpace.TAG_POLL; + } + switch (tag) { + case AddressSpace.TAG_RAM: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.RAM_AND)); + il.append(new IAND()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(new IALOAD()); + break; + case AddressSpace.TAG_SCRATCH: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.SCRATCH_XOR)); + il.append(new IXOR()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(new IALOAD()); + break; + case AddressSpace.TAG_BIOS: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.BIOS_XOR)); + il.append(new IXOR()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(new IALOAD()); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "read32", "(I)I"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_read32", "(I)I"))); + } + } + + public void emitWriteMem8(InstructionList il, int address, InstructionList il2) { + InstructionList il3 = new InstructionList(); + emitReadMem32(il3, address, true); + switch (address & 3) { + case 0: + il3.append(new PUSH(contextCP, 0xffffff00)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new IOR()); + break; + case 1: + il3.append(new PUSH(contextCP, 0xffff00ff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new PUSH(contextCP, 8)); + il3.append(new ISHL()); + il3.append(new IOR()); + break; + case 2: + il3.append(new PUSH(contextCP, 0xff00ffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 0xff)); + il3.append(new IAND()); + il3.append(new PUSH(contextCP, 16)); + il3.append(new ISHL()); + il3.append(new IOR()); + break; + default: + il3.append(new PUSH(contextCP, 0xffffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 24)); + il3.append(new ISHL()); + il3.append(new IOR()); + } + emitWriteMem32(il, address, il3, true); + il3.dispose(); + } + + public void emitWriteMem8(InstructionList il, int reg, int offset) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + switch (tag) { + case AddressSpace.TAG_RAM: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Ram", "(II)V"))); + break; + case AddressSpace.TAG_SCRATCH: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Scratch", "(II)V"))); + break; + case AddressSpace.TAG_BIOS: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8Bios", "(II)V"))); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write8", "(II)V"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write8", "(II)V"))); + } + } + + public void emitWriteMem16(InstructionList il, int address, InstructionList il2) { + if ((address & 1) != 0) { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); + } else { + InstructionList il3 = new InstructionList(); + // il3.stack(0) = oldvalue + emitReadMem32(il3, address, true); + switch (address & 3) { + case 0: + // il3.stack(1) = mask; + il3.append(new PUSH(contextCP, 0xffff0000)); + il3.append(new IAND()); + // il3.stack(0) = maskedOldValue; + il3.append(il2); + // il3.stack(1) = newvalue; + il3.append(new PUSH(contextCP, 0xffff)); + // il3.stack(2) = mask; + il3.append(new IAND()); + // il3.stack(1) = maskedNewValue; + il3.append(new IOR()); + // il3.stack(0) = newMemValue + break; + default: + il3.append(new PUSH(contextCP, 0xffff)); + il3.append(new IAND()); + il3.append(il2); + il3.append(new PUSH(contextCP, 16)); + il3.append(new ISHL()); + il3.append(new IOR()); + } + emitWriteMem32(il, address, il3, true); + il3.dispose(); + } + } + + public void emitWriteMem16(InstructionList il, int reg, int offset) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + switch (tag) { + case AddressSpace.TAG_RAM: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Ram", "(II)V"))); + break; + case AddressSpace.TAG_SCRATCH: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Scratch", "(II)V"))); + break; + case AddressSpace.TAG_BIOS: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16Bios", "(II)V"))); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write16", "(II)V"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new SWAP()); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write16", "(II)V"))); + } + } + + public void emitWriteMem32(InstructionList il, int address, InstructionList il2, boolean forceAlign) { + rr.mem = null; + if (forceAlign) { + address &= ~3; + } + if (0 == (address & 3)) { + addressSpace.resolve(address, rr); + if (rr.tag == AddressSpace.TAG_RAM) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(il2); + il.append(new IASTORE()); + } else if (rr.tag == AddressSpace.TAG_SCRATCH) { + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(il2); + il.append(new IASTORE()); + } else if (rr.tag == AddressSpace.TAG_BIOS) { + // just read the address to make sure TAG is correct + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + il.append(new PUSH(contextCP, rr.offset)); + il.append(il2); + il.append(new IALOAD()); + il.append(new POP()); + } else if (rr.tag == AddressSpace.TAG_HW) { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); + } else { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + } else { + il.append(new PUSH(contextCP, address)); + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + } + + public void emitWriteMem32(InstructionList il, int reg, int offset, InstructionList il2, boolean forceAlign) { + int tag = addressSpace.getTag(contextAddress) & READ_TAG_MASK; + // todo note that right now we don't tag usuallyRAMRegs, but we could in the future so this tag == 0 check is there for that + if (tag == 0 && (0 != ((1 << reg) & MultiStageCompiler.Settings.usuallyRAMRegs))) { + tag = AddressSpace.TAG_RAM; + } + switch (tag) { + case AddressSpace.TAG_RAM: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "ramD", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.RAM_AND)); + il.append(new IAND()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(il2); + il.append(new IASTORE()); + break; + case AddressSpace.TAG_SCRATCH: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "scratch", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.SCRATCH_XOR)); + il.append(new IXOR()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(il2); + il.append(new IASTORE()); + break; + case AddressSpace.TAG_BIOS: + il.append(new GETSTATIC(contextCP.addFieldref(ADDRESS_SPACE_CLASS, "bios", "[I"))); + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + il.append(new PUSH(contextCP, AddressSpace.BIOS_XOR)); + il.append(new IXOR()); + il.append(new PUSH(contextCP, 2)); + il.append(new ISHR()); + il.append(il2); + // just read to check TAG_ is correct + il.append(new IALOAD()); + il.append(new POP()); + break; + case AddressSpace.TAG_HW: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(HW_CLASS, "write32", "(II)V"))); + break; + default: + emitGetReg(il, reg); + if (offset != 0) { + il.append(new PUSH(contextCP, offset)); + il.append(new IADD()); + } + if (forceAlign) { + il.append(new PUSH(contextCP, 0xfffffffc)); + il.append(new IAND()); + } + il.append(il2); + il.append(new INVOKESTATIC(contextCP.addMethodref(ADDRESS_SPACE_CLASS, "_write32", "(II)V"))); + } + } + + protected boolean shouldPrintCode() { + return true; + } + + public void fixupUnwrittenRegs(CodeUnit unit, int pc) { + // todo we could keep the info we needed here about in soft reference I guess; even so we need this code + assert r3000.isExecutionThread(); + assert intendedForExecutionThread; + FlowAnalyzer.FlowInfo flowInfo = unit.getFlowInfo(analyzer, true); + getRegsOffset = (pc - unit.base) >> 2; + initBlockStructures(flowInfo); + if (0 != (CRAtOffset & 0x00000002)) { + MultiStageCompiler.reg_1 = regsAtOffset[1]; + } + if (0 != (CRAtOffset & 0x00000004)) { + MultiStageCompiler.reg_2 = regsAtOffset[2]; + } + if (0 != (CRAtOffset & 0x00000008)) { + MultiStageCompiler.reg_3 = regsAtOffset[3]; + } + if (0 != (CRAtOffset & 0x00000010)) { + MultiStageCompiler.reg_4 = regsAtOffset[4]; + } + if (0 != (CRAtOffset & 0x00000020)) { + MultiStageCompiler.reg_5 = regsAtOffset[5]; + } + if (0 != (CRAtOffset & 0x00000040)) { + MultiStageCompiler.reg_6 = regsAtOffset[6]; + } + if (0 != (CRAtOffset & 0x00000080)) { + MultiStageCompiler.reg_7 = regsAtOffset[7]; + } + if (0 != (CRAtOffset & 0x00000100)) { + MultiStageCompiler.reg_8 = regsAtOffset[8]; + } + if (0 != (CRAtOffset & 0x00000200)) { + MultiStageCompiler.reg_9 = regsAtOffset[9]; + } + if (0 != (CRAtOffset & 0x00000400)) { + MultiStageCompiler.reg_10 = regsAtOffset[10]; + } + if (0 != (CRAtOffset & 0x00000800)) { + MultiStageCompiler.reg_11 = regsAtOffset[11]; + } + if (0 != (CRAtOffset & 0x00001000)) { + MultiStageCompiler.reg_12 = regsAtOffset[12]; + } + if (0 != (CRAtOffset & 0x00002000)) { + MultiStageCompiler.reg_12 = regsAtOffset[13]; + } + if (0 != (CRAtOffset & 0x00004000)) { + MultiStageCompiler.reg_14 = regsAtOffset[14]; + } + if (0 != (CRAtOffset & 0x00008000)) { + MultiStageCompiler.reg_15 = regsAtOffset[15]; + } + if (0 != (CRAtOffset & 0x00010000)) { + MultiStageCompiler.reg_16 = regsAtOffset[16]; + } + if (0 != (CRAtOffset & 0x00020000)) { + MultiStageCompiler.reg_17 = regsAtOffset[17]; + } + if (0 != (CRAtOffset & 0x00040000)) { + MultiStageCompiler.reg_18 = regsAtOffset[18]; + } + if (0 != (CRAtOffset & 0x00080000)) { + MultiStageCompiler.reg_19 = regsAtOffset[19]; + } + if (0 != (CRAtOffset & 0x00100000)) { + MultiStageCompiler.reg_20 = regsAtOffset[20]; + } + if (0 != (CRAtOffset & 0x00200000)) { + MultiStageCompiler.reg_21 = regsAtOffset[21]; + } + if (0 != (CRAtOffset & 0x00400000)) { + MultiStageCompiler.reg_22 = regsAtOffset[22]; + } + if (0 != (CRAtOffset & 0x00800000)) { + MultiStageCompiler.reg_23 = regsAtOffset[23]; + } + if (0 != (CRAtOffset & 0x01000000)) { + MultiStageCompiler.reg_24 = regsAtOffset[24]; + } + if (0 != (CRAtOffset & 0x02000000)) { + MultiStageCompiler.reg_25 = regsAtOffset[25]; + } + if (0 != (CRAtOffset & 0x04000000)) { + MultiStageCompiler.reg_26 = regsAtOffset[26]; + } + if (0 != (CRAtOffset & 0x08000000)) { + MultiStageCompiler.reg_27 = regsAtOffset[27]; + } + if (0 != (CRAtOffset & 0x10000000)) { + MultiStageCompiler.reg_28 = regsAtOffset[28]; + } + if (0 != (CRAtOffset & 0x20000000)) { + MultiStageCompiler.reg_29 = regsAtOffset[29]; + } + if (0 != (CRAtOffset & 0x40000000)) { + MultiStageCompiler.reg_30 = regsAtOffset[30]; + } + if (0 != (CRAtOffset & 0x80000000)) { + MultiStageCompiler.reg_31 = regsAtOffset[31]; + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java new file mode 100644 index 0000000..df09aa4 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware; + +import org.jpsx.api.components.hardware.cd.CDAudioSink; +import org.jpsx.api.components.hardware.cd.CDDrive; +import org.jpsx.api.components.hardware.gpu.Display; +import org.jpsx.api.components.hardware.gpu.DisplayManager; +import org.jpsx.api.components.hardware.sio.SerialPort; +import org.jpsx.bootstrap.connection.SimpleConnection; + +/** + * Stock connections used by the base JPSX hardware implementations + */ +public class HardwareComponentConnections { + public static final SimpleConnection CD_DRIVE = SimpleConnection.create("CD Drive", CDDrive.class); + public static final SimpleConnection CD_AUDIO_SINK = SimpleConnection.create("CD Audio Sink", CDAudioSink.class); + public static final SimpleConnection LEFT_PORT_INSTANCE = SimpleConnection.create("Left Serial Port", SerialPort.class); + public static final SimpleConnection RIGHT_PORT_INSTANCE = SimpleConnection.create("Right Serial Port", SerialPort.class); + public static final SimpleConnection DISPLAY = SimpleConnection.create("JPSX GPU Display", Display.class); + public static final SimpleConnection DISPLAY_MANAGER = SimpleConnection.create("JPXS GPU Display Manager", DisplayManager.class); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java new file mode 100644 index 0000000..887b2b1 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.bios; + +import org.jpsx.api.InvalidConfigurationException; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.nio.channels.FileChannel; + +/** + * ImageBIOS is a simple component which maps + * a file base image of an R3000 BIOS into + * the PSX address base. This file can be + * a real PSX BIOS image, though it need not be + */ +public class ImageBIOS extends JPSXComponent { + private static final int ADDRESS = 0xbfc00000; + // todo get size from file! + private static final int SIZE = 0x80000; + + public ImageBIOS() { + super("JPSX BIOS using ROM image"); + } + + public void init() { + super.init(); + CoreComponentConnections.ALL_POPULATORS.add(new Runnable() { + public void run() { + populateMemory(); + } + }); + } + + private void populateMemory() { + String filename = "bios.bin"; + //MiscUtil.consoleOut( "Loading bios " + filename + "..." ); + try { + RandomAccessFile in = new RandomAccessFile(filename, "r"); + AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); + AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + addressSpace.resolve(ADDRESS, SIZE, true, rr); + + FileChannel channel = in.getChannel(); + ByteBuffer bytebuf = ByteBuffer.allocateDirect(SIZE); + bytebuf.order(ByteOrder.LITTLE_ENDIAN); + IntBuffer intbuf = bytebuf.asIntBuffer(); + bytebuf.clear(); + + if (SIZE != channel.read(bytebuf, 0)) { + throw new InvalidConfigurationException("BIOS image " + filename + " is not the correct size"); + } + intbuf.rewind(); + intbuf.get(rr.mem); + channel.close(); + } catch (IOException e) { + throw new InvalidConfigurationException("Can't load BIOS image " + filename, e); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/CD.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/CD.java new file mode 100644 index 0000000..6f4f664 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/CD.java @@ -0,0 +1,1676 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.cd; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.cpu.SCP; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.ScheduledAction; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.api.components.hardware.cd.CDAudioSink; +import org.jpsx.api.components.hardware.cd.CDDrive; +import org.jpsx.api.components.hardware.cd.CDMedia; +import org.jpsx.api.components.hardware.cd.MediaException; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.DMAChannelOwnerBase; +import org.jpsx.runtime.components.core.IRQOwnerBase; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.CDUtil; +import org.jpsx.runtime.util.MiscUtil; + +// todo return the correct thing for audio/no disc +// todo filter! +// todo end of file! + +// todo no need for static + + +// note we are two times over-clocked; we just slow stuff down if streaming XA audio +/** + * New cd plan as follows: + *

+ * All CD action is timing based; i.e. when spinning we update head position on interrupt. + * Data is read into buffers, Audio is passed straight along at the correct speed. + *

+ * AudioSink should bufer after a reset. + *

+ * it is up to native back end to read in bursts + */ +public class CD extends JPSXComponent implements MemoryMapped { + private static boolean rateLimit1 = false; + private static boolean rateLimit2 = true; + + private static final Logger log = Logger.getLogger("CD"); + /** + * Logs information on CD commands set by the PSX + */ + private static final Logger cmdLog = Logger.getLogger("CD.CMD"); + private static final boolean cmdLogDebug = cmdLog.isDebugEnabled(); + + /** + * The CD drive implementation + */ + private static CDDrive drive; + /** + * The current CD media, or null + */ + private static CDMedia media; + + private static XADecoder xaDecoder = new XADecoder(); + private static CDAudioSink cdAudioSink; + private static int cdFreq = 0; + + private static long rateLimitStartTime; + private static boolean rateLimitEnabled; + + // ratelimit1 stuff + // number of audio bytes we've fed + private static int actualAudioBytes; + + // ratelimit2 stuff + private static int actualSectors; + + private static final boolean traceCD = log.isTraceEnabled(); + private static final boolean softwareCDDA = true; + // Hardware addresses + public static final int ADDR_CD_REG0 = 0x1f801800; + public static final int ADDR_CD_REG1 = 0x1f801801; + public static final int ADDR_CD_REG2 = 0x1f801802; + public static final int ADDR_CD_REG3 = 0x1f801803; + + // 0, 1, 2, 3 as set by low 3 bits of reg0 + private static int regMode; + + // cdMode of the CD as set by CdlSetMode + private static int cdMode = 0; + + private static int filterFile = 0; + private static int filterChannel = 0; + + private static final int STATE_NONE = 0; + private static final int STATE_STANDBY = 1; + private static final int STATE_READN = 2; + private static final int STATE_READS = 3; + private static final int STATE_PLAY = 4; + private static final int STATE_SEEKL = 5; + private static final int STATE_SEEKP = 6; + private static final int STATE_PAUSE = 7; + private static final int STATE_STOP = 8; + + private static int substate; + private static int state; + + private static boolean interruptEnabled; + private static boolean seeking; + private static boolean sectorReady; + private static boolean sectorDismissed; + private static boolean someDataRead; + private static boolean waitForDataRead; + private static int waitForDataReadCounter; + + private static boolean resultCleared; + + private static int[] currentSector = new int[2352 / 4]; + private static int currentSectorOffset; + private static int currentSectorEnd; + + // reg0 status bits + private static final int REG0_UNKNOWN_READY3 = 0x08; + private static final int REG0_UNKNOWN_READY4 = 0x10; + private static final int REG0_RESULTS_READY = 0x20; + private static final int REG0_DATA_READY = 0x40; +// private static final int REG0_CMDINPROGRESS = 0x80; + + // reg3 status bits + + // not sure about error bits; sometime 0x1c is used as an error mask, sometimes 0x1d + private static final int REG3_CDDA_PLAYING = 0x80; + private static final int REG3_SEEKING = 0x40; + private static final int REG3_READING_DATA = 0x20; + private static final int REG3_SHELL_OPEN = 0x10; + private static final int REG3_SEEK_ERROR = 0x04; + private static final int REG3_STANDBY = 0x02; // spinning + private static final int REG3_ERROR = 0x01; + + // cdMode values + private static final int CD_MODE_DOUBLE_SPEED = 0x80; + // playing XA data + private static final int CD_MODE_XA = 0x40; + + private static final int CD_MODE_SIZE_MASK = 0x30; + private static final int CD_MODE_SIZE_2048 = 0x00; + private static final int CD_MODE_SIZE_2340 = 0x20; + //private static final int CD_MODE_SIZE_2328 = 0x10; + + private static final int CD_MODE_FILTER = 0x08; + // i guess this is supposed to send data while playing + private static final int CD_MODE_REPORT = 0x04; + // should pause at the end of a track + private static final int CD_MODE_AUTO_PAUSE = 0x02; + // playing DA data? + private static final int CD_MODE_DA = 0x01; + + // -------------------------------------------------------------------- + + private static IRQ irq; + private static AddressSpace addressSpace; + private static SCP scp; + private static Quartz quartz; + private static Scheduler scheduler; + + private static class IRQ extends IRQOwnerBase { + private boolean set; + + private boolean inIRQCleared; + private boolean inRaiseIRQ; + + private boolean pendingIRQ; + + public IRQ() { + super(IRQController.IRQ_CD, "CD"); + } + + public boolean isSet() { + return set; + } + + // not synched, because irq already synchronized + public void irqSet() { + assert !set; + if (false || traceCD) log.trace("Set CD interrupt"); + set = true; + } + + public void irqCleared() { + assert set; + if (false || traceCD) log.trace("Clear CD interrupt"); + set = false; + try { + synchronized (this) { + assert !inIRQCleared; + inIRQCleared = true; + // if we're in raise IRQ, then the irq is getting set anyway, + // so no point in checking for another one. + if (inRaiseIRQ) + return; + } + checkForIRQ(); + } finally { + synchronized (this) { + assert inIRQCleared; + inIRQCleared = false; + if (pendingIRQ) { + pendingIRQ = false; + if (!set) { + super.raiseIRQ(); + } + } + } + } + } + + public void raiseIRQ() { + // work around deadlock possibility: + // thread1: owns CD lock, and tries to signal CD interrupt (needs IRQ lock) + // thread2: clearing CD intterrupt (owns IRQ lock), waiting on CD lock + // + // to do this, we simply ask the irq clearing thread to signal the interrupt when it is done. + try { + synchronized (this) { + assert !inRaiseIRQ; + inRaiseIRQ = true; + // if we're in irqCleared(), then just + // get it to set the irq for us. + if (inIRQCleared) { + pendingIRQ = true; + return; + } + } + super.raiseIRQ(); + } finally { + synchronized (this) { + assert inRaiseIRQ; + inRaiseIRQ = false; + } + } + } + } + + // -------------------------------------------------------------------- + + public CD() { + super("JPSX CD Controller"); + } + + public void init() { + super.init(); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + irq = new IRQ(); + CoreComponentConnections.IRQ_OWNERS.add(irq); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new CDDMAChannel()); + } + + public void resolveConnections() { + drive = HardwareComponentConnections.CD_DRIVE.resolve(); + media = drive.getCurrentMedia(); + cdAudioSink = HardwareComponentConnections.CD_AUDIO_SINK.peek(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + scp = CoreComponentConnections.SCP.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + scheduler = CoreComponentConnections.SCHEDULER.resolve(); + } + + private static String getModeDescription(int mode) { + return "..."; + } + + private static synchronized void setCdMode(int newMode) { + if (traceCD && newMode != cdMode) { + log.trace("CD MODE: " + getModeDescription(cdMode)); + } + if (false && 0 != (newMode & CD_MODE_AUTO_PAUSE)) { + System.out.println("AutoPause"); + } + if (false && 0 != (newMode & CD_MODE_REPORT)) { + System.out.println("Report"); + } + cdMode = newMode; + } + + private static class CmdParameters { + private static final int MAX_PARAMS = 8; + private static final int params[] = new int[MAX_PARAMS]; + private static int count = 0; + + public void reset() { + count = 0; + } + + public void add(int b) { + if (traceCD) log.trace("CD: param " + count + " = " + MiscUtil.toHex(b, 2)); + params[count++] = b; + } + + public int get(int index) { + if (index < 0 || index > count) { + log.error("out of bounds in CD"); + throw new ArrayIndexOutOfBoundsException(index); + } + return params[index]; + } + } + + ; + + private static CmdParameters params = new CmdParameters(); + + private static class CmdResult { + private static final int MAX_RESULTS = 8; + + public static final int DATAREADY = 1; + public static final int COMPLETE = 2; + public static final int ACKNOWLEDGE = 3; + public static final int DATAEND = 4; + public static final int DISKERROR = 5; + + public int type; + public int[] results = new int[MAX_RESULTS]; + public int resultCount; + public int resultPos; + + public void add(int b) { + results[resultCount++] = b; + } + + public boolean remaining() { + return resultPos != resultCount; + } + + public int read() { + if (resultPos < resultCount) { + return results[resultPos++]; + } else { + throw new IllegalStateException("CD: read more results than available!"); + } + } + + public String toString() { + StringBuilder rc = new StringBuilder(); + for (int i = 0; i < resultCount; i++) { + rc.append(' '); + rc.append(MiscUtil.toHex(results[i], 2)); + } + return rc.toString(); + } + } + + private static CmdResult nullResult = new CmdResult(); + /** + * current result + */ + private static CmdResult currentResult = nullResult; + + // protected by CD.class monitor + private static CmdResult[] resultQueue = new CmdResult[16]; + // read==write implies empty; + private static int resultQueueNextRead = 0; + private static int resultQueueNextWrite = 0; + + private static class HeadLocation { + private int m, s, f; + + public HeadLocation() { + init(0); + } + + public void init(HeadLocation h) { + m = h.m; + s = h.s; + f = h.f; + } + + public void init(int m, int s, int f) { + this.m = m; + this.s = s; + this.f = f; + } + + public void init(int sec) { + sec += 150; + f = sec % 75; + sec /= 75; + s = sec % 60; + m = sec / 60; + } + + public int getM() { + return m; + } + + public int getS() { + return s; + } + + public int getF() { + return f; + } + + public int getSector() { + return CDUtil.toSector(m, s, f); + } + + /** + * simulate spinning of the CD in place + */ + public void nextSpin() { + f++; + if (f == 75) + f = 0; + } + + public void nextSequential() { + f++; + if (f == 75) { + f = 0; + s++; + if (s == 60) { + s = 0; + m++; + } + } + } + + public String toString() { + return MiscUtil.toHex(CDUtil.toBCD(m), 2) + "," + MiscUtil.toHex(CDUtil.toBCD(s), 2) + "," + MiscUtil.toHex(CDUtil.toBCD(f), 2); + } + } + + private static SectorThread sectorThread; + + private static HeadLocation lastSetLocation = new HeadLocation(); + private static boolean setLocDone; + private static HeadLocation currentLocation = new HeadLocation(); + + // commands + private static final int CdlNop = 1; + private static final int CdlSetLoc = 2; + private static final int CdlPlay = 3; + private static final int CdlFastForward = 4; + private static final int CdlRewind = 5; + private static final int CdlReadN = 6; + private static final int CdlStandby = 7; + private static final int CdlStop = 8; + private static final int CdlPause = 9; + private static final int CdlReset = 10; + private static final int CdlMute = 11; + private static final int CdlDemute = 12; + private static final int CdlSetFilter = 13; + private static final int CdlSetMode = 14; + private static final int CdlGetLocL = 16; + private static final int CdlGetLocP = 17; + private static final int CdlGetTN = 19; + private static final int CdlGetTD = 20; + private static final int CdlSeekL = 21; + private static final int CdlSeekP = 22; + private static final int CdlTest = 25; + private static final int CdlCheckID = 26; + private static final int CdlReadS = 27; + private static final int CdlHardReset = 28; + private static final int CdlReadTOC = 30; + + private static class CDDMAChannel extends DMAChannelOwnerBase { + public final int getDMAChannel() { + return DMAController.DMA_CD; + } + + static boolean first = true; + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if (false || traceCD) + log.trace("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + if (blocks == 0) blocks = 1; // ?? + int size = blocks * blockSize; + if (false || traceCD) + log.trace("size = " + (size * 4) + " remaining = " + (currentSectorEnd - currentSectorOffset)); + AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); + addressSpace.resolve(base, size * 4, true, rr); + if (0 != (base & 3) || 0 != (currentSectorOffset & 3)) { + throw new IllegalStateException("doh unaligned dma!"); + } + if (currentSectorOffset + (size * 4) > currentSectorEnd) { + throw new IllegalStateException("read off end of dma sector buffer"); + } + + int off = currentSectorOffset >> 2; + if (false && size == 8) { + log.trace(MiscUtil.toHex(currentSector[off], 8) + " " + + MiscUtil.toHex(currentSector[off + 1], 8) + " " + + MiscUtil.toHex(currentSector[off + 2], 8) + " " + + MiscUtil.toHex(currentSector[off + 3], 8) + " " + + MiscUtil.toHex(currentSector[off + 4], 8) + " " + + MiscUtil.toHex(currentSector[off + 5], 8) + " " + + MiscUtil.toHex(currentSector[off + 6], 8) + " " + + MiscUtil.toHex(currentSector[off + 7], 8)); + } + for (int i = 0; i < size; i++) { + rr.mem[rr.offset + i] = currentSector[off + i]; + } + currentSectorOffset += size << 2; + signalTransferComplete(); + setSomeDataRead(); + } + + public final String getName() { + return "CD"; + } + } + + public void registerAddresses(AddressSpaceRegistrar registration) { + registration.registerWrite8Callback(ADDR_CD_REG0, CD.class, "cdReg0Write"); + registration.registerWrite8Callback(ADDR_CD_REG1, CD.class, "cdReg1Write"); + registration.registerWrite8Callback(ADDR_CD_REG2, CD.class, "cdReg2Write"); + registration.registerWrite8Callback(ADDR_CD_REG3, CD.class, "cdReg3Write"); + registration.registerRead8Callback(ADDR_CD_REG0, CD.class, "cdReg0Read"); + registration.registerRead8Callback(ADDR_CD_REG1, CD.class, "cdReg1Read"); + registration.registerRead8Callback(ADDR_CD_REG2, CD.class, "cdReg2Read"); + registration.registerRead8Callback(ADDR_CD_REG3, CD.class, "cdReg3Read"); + } + + public void begin() { + sectorThread = new SectorThread(); + } + + // h/w access ----------------------------------------------------------------------------------- + + public static void cdReg0Write(int address, int value) { + if (traceCD) log.trace("CD_REG0_WRITE " + MiscUtil.toHex(value, 2)); + + regMode = (value & 3); + + //if (regMode==0) { + // if (traceCD) log.info("cdMode set to 0; reseting result ptr"); + // // reset the results pointer + // cdCurrentResultPos = 0; + //} + + if (0 != (value & 0xfc)) { + throw new IllegalStateException("CD: unknown reg0 write " + MiscUtil.toHex(value, 2)); + } + } + + public static int cdReg0Read(int address) { + + int rc = regMode; + + if (currentResult.remaining()) { + rc |= REG0_RESULTS_READY; + } + + if (currentSectorOffset != currentSectorEnd) { + rc |= REG0_DATA_READY; + } + + // todo, check this + rc |= REG0_UNKNOWN_READY3; // shell barfs early without this + rc |= REG0_UNKNOWN_READY4; // bios cannot read sector without this... + + if (traceCD) log.trace("CD_REG0_READ " + MiscUtil.toHex(rc, 2)); + return rc; + } + + public static void cdReg1Write(int address, int value) { + if (traceCD) log.trace("CD_REG1_WRITE " + MiscUtil.toHex(value, 2)); + + switch (regMode) { + case 0: + startCmd(value); + break; + case 3: + log.trace("CD set right volume " + MiscUtil.toHex(value, 2)); + if (cdAudioSink != null) { + cdAudioSink.setExternalCDAudioVolumeRight(value << 8); + } + break; + default: + throw new IllegalStateException("CD: unknown reg1 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); + } + } + + public static int cdReg1Read(int address) { + int rc = 0; + + switch (regMode) { + case 1: + rc = currentResult.read(); + break; + default: + throw new IllegalStateException("CD: unknown reg1 read: cdMode " + regMode); + } + if (traceCD) log.trace("CD_REG1_READ " + MiscUtil.toHex(rc, 2)); + return rc; + } + + public static void cdReg2Write(int address, int value) { + if (traceCD) log.trace("CD_REG2_WRITE " + MiscUtil.toHex(value, 2)); + + switch (regMode) { + case 0: + // writing command parameter + params.add(value); + break; + case 1: + // i think now that low bits are for IRQ (i.e. I know that 0x1f and 0x18 enable/disable + // interrupts, however I think the 0x18 do other stuff.. used mainly by bios/shell + // which are keen on 0x18 in all kinds of things :-) + if (0 == (value & 7)) { + if (traceCD) log.trace("CD: disabling interrupts"); + interruptEnabled = false; + } else if (7 == (value & 7)) { + if (traceCD) log.trace("CD: enabling interrupts"); + interruptEnabled = true; + } else { + throw new IllegalStateException("CD: unknown reg2 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); + } + + if (0 == (value & 0xf8)) { + } else if (0x18 == (value & 0xf8)) { + } else { + throw new IllegalStateException("CD: unknown reg2 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); + } + break; + case 2: + log.trace("CD set left volume " + MiscUtil.toHex(value, 2)); + if (cdAudioSink != null) { + cdAudioSink.setExternalCDAudioVolumeLeft(value << 8); + } + break; + default: + log.trace("CD ?set left volume low bits" + MiscUtil.toHex(value, 2)); + break; + } + } + + public static int cdReg2Read(int address) { + if (currentSectorOffset < currentSectorEnd) { + int val = currentSector[currentSectorOffset >> 2]; + switch (currentSectorOffset & 3) { + case 0: + val = val & 0xff; + break; + case 1: + val = (val >> 8) & 0xff; + break; + case 2: + val = (val >> 16) & 0xff; + break; + default: + val = (val >> 24) & 0xff; + break; + } + if (false || traceCD) log.trace("Read sector byte " + MiscUtil.toHex(val, 8)); + currentSectorOffset++; + setSomeDataRead(); + return val; + } else { + throw new IllegalStateException("read off end of sector buffer via reg2"); + } + } + + public static void cdReg3Write(int address, int value) { + if (traceCD) log.trace("CD_REG3_WRITE " + MiscUtil.toHex(value, 2)); + + switch (regMode) { + case 0: + if (value == 0x00) { + if (false || traceCD) { + log.trace("CD: dismiss sector"); + } + dismissSector(); + } else if (false || value == 0x80) { + if (false || traceCD) { + log.trace("CD: prepare sector results"); + } + prepareSector(); + } else { + throw new IllegalStateException("CD: unknown reg3 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); + } + break; + case 1: + if (7 == (value & 7)) { + if (traceCD) log.trace("CD: dismiss result"); + clearResult(); + } + if (0 != (value & 0x40)) { + // not sure what this does... + if (traceCD) log.trace("CD: 0140"); + } + if (0 != (value & 0xb8) && 0x18 != (value & 0xb8)) { + throw new IllegalStateException("CD: unknown reg3 write: cdMode " + regMode + " " + MiscUtil.toHex(value, 2)); + } + break; + case 2: + log.trace("CD ?set right volume low bits" + MiscUtil.toHex(value, 2)); + break; + default: + log.trace("CD ?commit volume"); + break; + } + } + + public static int cdReg3Read(int address) { + int rc = 0; + switch (regMode) { + case 0: + // todo figure out what this is + break; + case 1: + // to work around timing issues, we only make the result current when this register + // is read... + nextResult(); + rc = currentResult.type; + break; + default: + throw new IllegalStateException("CD: unknown reg3 read: cdMode " + regMode); + } + if (traceCD) log.trace("CD_REG3_READ " + MiscUtil.toHex(rc, 2)); + return rc; + } + + private static synchronized boolean resultQueueIsEmpty() { + return resultQueueNextWrite == resultQueueNextRead; + } + + private static synchronized void queueResult(CmdResult result) { + int write = resultQueueNextWrite; + + if (traceCD) log.trace("CD: queuing result " + result); + resultQueueNextWrite = (resultQueueNextWrite + 1) % resultQueue.length; + if (resultQueueNextWrite == resultQueueNextRead) { + throw new IllegalStateException("result queue full"); + } + + resultQueue[write] = result; + checkForIRQ(); + } + + private static synchronized void checkForIRQ() { + if (interruptEnabled && resultQueueNextRead != resultQueueNextWrite) { + if (false || traceCD) log.trace("CD: a result available; raising IRQ"); + irq.raiseIRQ(); + if (false || traceCD) log.trace("CD: done raising IRQ"); + } + } + + private static synchronized void clearResult() { + if (false || traceCD) log.trace("CD: clear result"); + resultCleared = true; + checkForIRQ(); + } + + private static synchronized void nextResult() { + if (!resultCleared) { + if (false || traceCD) log.trace("CD: nextResult: previous not reset, so not shifting"); + return; + } + if (resultQueueNextRead == resultQueueNextWrite) { + if (false || traceCD) log.trace("CD: nextResult: none"); + currentResult = nullResult; + resultCleared = true; + } else { + if (currentResult.type == CmdResult.DATAREADY && resultQueue[resultQueueNextRead].type == CmdResult.DATAREADY && irq.isSet()) { + if (false || traceCD) log.trace("CD: deferring sequential dataready with irq set"); + currentResult = nullResult; + resultCleared = true; + } else { + currentResult = resultQueue[resultQueueNextRead]; + resultQueue[resultQueueNextRead] = null; + resultQueueNextRead = (resultQueueNextRead + 1) % resultQueue.length; + resultCleared = false; + if (currentResult.type == CmdResult.DATAREADY) { + sectorReady = true; + } + if (false || traceCD) log.trace("CD: nextResult: " + currentResult); + } + } + } + + private static synchronized void clearResults() { + resultQueueNextRead = resultQueueNextWrite; + currentResult = nullResult; + } + + private static CmdResult newAckStatusResult() { + CmdResult res = new CmdResult(); + res.type = CmdResult.ACKNOWLEDGE; + res.add(getStatus()); + return res; + } + + private static CmdResult newDataReadyStatusResult() { + CmdResult res = new CmdResult(); + res.type = CmdResult.DATAREADY; + res.add(getStatus()); + return res; + } + + private static CmdResult newCompleteStatusResult() { + CmdResult res = new CmdResult(); + res.type = CmdResult.COMPLETE; + res.add(getStatus()); + return res; + } + + // this function called from r3000 thread; + private static void startCmd(int cmd) { + CmdResult res; + + switch (cmd) { + case CdlNop: + if (cmdLogDebug) cmdLog.debug("CdlNop"); + queueResult(newAckStatusResult()); + break; + + case CdlReset: + if (cmdLogDebug) cmdLog.debug("CdlReset"); + clearResults(); + // standby will abort any read etc. + setState(STATE_STANDBY); + setCdMode(0); + + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + + case CdlSetLoc: + // todo, check what to do if we're reading.. + lastSetLocation.init(CDUtil.fromBCD(params.get(0)), CDUtil.fromBCD(params.get(1)), CDUtil.fromBCD(params.get(2))); + setLocDone = true; + if (cmdLogDebug) cmdLog.debug("CdlSetLoc " + lastSetLocation); + queueResult(newAckStatusResult()); + break; + + case CdlTest: + switch (params.get(0)) { + case 0x20: + if (cmdLogDebug) cmdLog.debug("CdlTest: getVersion"); + res = new CmdResult(); + res.type = CmdResult.ACKNOWLEDGE; + res.add(0x98); + res.add(0x06); + res.add(0x10); + res.add(0xc3); + queueResult(res); + break; + default: + throw new IllegalStateException("Unknown CdlTest command 0x" + MiscUtil.toHex(params.get(0), 2)); + } + break; + + case CdlReadN: + if (cmdLogDebug) cmdLog.debug("CdlReadN"); + resetAudio(); + setState(STATE_READN); + queueResult(newAckStatusResult()); + break; + + case CdlStop: + if (cmdLogDebug) cmdLog.debug("CdlStop"); + setState(STATE_STOP); + clearResults(); + resetAudio(); + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + + case CdlStandby: + if (cmdLogDebug) cmdLog.debug("CdlStandby"); + setState(STATE_STANDBY); + clearResults(); + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + + case CdlPause: + if (cmdLogDebug) cmdLog.debug("CdlPause"); + setState(STATE_PAUSE); + clearResults(); + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + + case CdlSetMode: + if (cmdLogDebug) cmdLog.debug("CdlSetMode " + MiscUtil.toHex(params.get(0), 2)); + setCdMode(params.get(0)); + queueResult(newAckStatusResult()); + //if (true) throw new IllegalStateException("What?"); + break; + + case CdlCheckID: + // TODO, do this correctly; currently just saying we have a psx CD present + if (cmdLogDebug) cmdLog.debug("CdlCheckID"); + + queueResult(newAckStatusResult()); + + res = new CmdResult(); + res.type = CmdResult.ACKNOWLEDGE; + + int type = CDUtil.getMediaType(media); + + if (0 != (type & CDUtil.MEDIA_PRESENT)) { + boolean hasDataTracks = 0 != (type & CDUtil.MEDIA_HAS_DATA); + boolean hasAudioTracks = 0 != (type & CDUtil.MEDIA_HAS_AUDIO); + + boolean isPlayStationDisc = hasDataTracks; // duh clearly wrong + boolean genuinePlayStationDisc = isPlayStationDisc; + boolean isAudioDisk = hasAudioTracks && !hasDataTracks; + // todo figure out what happens if you put a copied PSX disc with audio in; should you be + // able to play the audio tracks? + + // bios always check [1] == 0x80... if so it'll try and boot as a playstation disc + // audio flag is only honored of [0] & 0x08 + // other flag of 0x40 means something else - perhaps disc with audio? + res.add(isAudioDisk ? 0x08 : 0x00); + res.add((isAudioDisk ? 0x10 : 0x00) | (genuinePlayStationDisc ? 0x00 : 0x80)); + res.add(0x00); + res.add(0x00); + res.type = CmdResult.COMPLETE; + } else { + res.type = CmdResult.DISKERROR; + // todo. check these + res.add(0); + res.add(0); + res.add(0); + res.add(0); + } + res.add('J'); + res.add('P'); + res.add('S'); + res.add('X'); + queueResult(res); + break; + + case CdlGetTN: + cmdLog.debug("CdlGetTN"); + + res = new CmdResult(); + // made up check + if (drive != null) { + res.type = CmdResult.ACKNOWLEDGE; + res.add(getStatus()); + res.add(CDUtil.toBCD(media.getFirstTrack())); + res.add(CDUtil.toBCD(media.getLastTrack())); + } else { + res.type = CmdResult.ACKNOWLEDGE; + } + queueResult(res); + break; + + case CdlGetTD: + int track = CDUtil.fromBCD(params.get(0)); + + if (traceCD) cmdLog.debug("CdlGetTD " + track); + + int msf = media.getTrackMSF(track); + + int m = (msf & 0xff0000) >> 16; + int s = (msf & 0xff00) >> 8; + int f = msf & 0xff; + + res = new CmdResult(); + res.type = CmdResult.ACKNOWLEDGE; + res.add(getStatus()); + res.add(m); + res.add(s); + res.add(f); + queueResult(res); + break; + + case CdlSeekL: + if (traceCD) cmdLog.debug("CdlSeekL"); + // what happens if we're playing + if (state == STATE_READN || state == STATE_READS) { + throw new IllegalStateException("SeekL while reading etc."); + //log.trace("seekl while reading!!!"); + } + + // i've seen seekl while playing; it.d have to close it. + setState(STATE_SEEKL); + queueResult(newAckStatusResult()); + break; + + case CdlSeekP: + if (traceCD) cmdLog.debug("CdlSeekP"); + // what happens if we're playing + if (false && state == STATE_PLAY || state == STATE_READN || state == STATE_READS) + throw new IllegalStateException("SeekP while playing/reading etc."); + setState(STATE_SEEKP); + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + + case CdlMute: + // todo implement + if (cmdLogDebug) cmdLog.debug("CdlMute"); + queueResult(newAckStatusResult()); + break; + + case CdlDemute: + // todo implement + if (cmdLogDebug) cmdLog.debug("CdlDemute"); + queueResult(newAckStatusResult()); + break; + + case CdlSetFilter: + filterFile = params.get(0); + filterChannel = params.get(1); + if (cmdLogDebug) cmdLog.debug("CdlSetFilter " + filterFile + " " + filterChannel); + queueResult(newAckStatusResult()); + break; + + case CdlPlay: + // todo check if this is always there + int tr = params.get(0); + if (cmdLogDebug) cmdLog.debug("CdlPlay " + tr); + if (media != null && tr >= media.getFirstTrack() && tr <= media.getLastTrack()) { + int playMSF = media.getTrackMSF(tr); + lastSetLocation.init(CDUtil.fromBCD((playMSF >> 16) & 0xff), CDUtil.fromBCD((playMSF >> 8) & 0xff), CDUtil.fromBCD(playMSF & 0xff)); + setLocDone = true; + } + resetAudio(); + setState(STATE_PLAY); + queueResult(newAckStatusResult()); + break; + case CdlFastForward: + // todo implement; note play needed to undo + if (cmdLogDebug) cmdLog.debug("CdlFastForward"); + queueResult(newAckStatusResult()); + break; + case CdlRewind: + // todo implement; note play needed to undo + if (cmdLogDebug) cmdLog.debug("CdlRewind"); + queueResult(newAckStatusResult()); + break; + case CdlGetLocL: + if (cmdLogDebug) cmdLog.debug("CdlGetLocL"); + queueResult(newAckStatusResult()); + // todo add 8 bytes of last read sector + break; + + case CdlGetLocP: + if (cmdLogDebug) cmdLog.debug("CdlGetLocP"); + //System.out.println("getlocl "+currentLocation); + // todo check this response; tombraider cares + // 5 bytes; tn, playing1/0 ?, m, s, f + res = new CmdResult(); + res.type = CmdResult.ACKNOWLEDGE; + track = getTrack(currentLocation.getM(), currentLocation.getS(), currentLocation.getF()); + res.add(CDUtil.toBCD(track)); + res.add(state == STATE_PLAY ? 1 : 0); + int trackMSF = track == 0 ? 0 : media.getTrackMSF(track); + int trackSector = CDUtil.toSector(CDUtil.fromBCD((trackMSF>>16)&0xff), CDUtil.fromBCD(((trackMSF)>>8)&0xff), CDUtil.fromBCD(trackMSF&0xff)); + int relativeSector = currentLocation.getSector() - trackSector; + res.add(relativeSector / (60*75)); + res.add((relativeSector / 75)%60); + res.add(relativeSector % 75); + res.add(CDUtil.toBCD(currentLocation.getM())); + res.add(CDUtil.toBCD(currentLocation.getS())); + res.add(CDUtil.toBCD(currentLocation.getF())); + queueResult(res); + //System.out.println(res); + break; + case CdlReadS: +// traceCD = true; + if (cmdLogDebug) cmdLog.debug("CdlReadS"); + resetAudio(); + setState(STATE_READS); + queueResult(newAckStatusResult()); + break; + case CdlReadTOC: + if (cmdLogDebug) cmdLog.debug("CdlReadTOC"); + drive.refreshMedia(); + media = drive.getCurrentMedia(); + queueResult(newAckStatusResult()); + queueResult(newCompleteStatusResult()); + break; + default: + throw new IllegalStateException("Unknown Cdl command " + cmd); + } + // doing this here for now... seems fair enough + params.reset(); + } + + private static int getStatus() { + int rc = 0; + + if (state != STATE_NONE) { + rc |= REG3_STANDBY; + } + + if (seeking) { + rc |= REG3_SEEKING; + } else { + if (state == STATE_PLAY) { + rc |= REG3_CDDA_PLAYING; + } + if (state == STATE_READN || state == STATE_READS) { + rc |= REG3_READING_DATA; + } + } + + //private static final int REG3_SHELL_OPEN = 0x10; + //private static final int REG3_SEEK_ERROR = 0x04; + //private static final int REG3_ERROR = 0x01; + return rc; + } + + private static synchronized void setState(int newState) { + log.trace("SET STATE " + newState); + state = newState; + substate = 0; + + if (setLocDone) { + currentLocation.init(lastSetLocation); + setLocDone = false; + } + sectorThread.newState(); + sectorReady = false; + sectorDismissed = true; + waitForDataReadCounter = 20; + someDataRead = true; + waitForDataRead = false; + // reset dma availability. + currentSectorOffset = currentSectorEnd = 0; + updateCallback(quartz.nanoTime()); + CD.class.notifyAll(); + } + + //private static int threes = 0; + + private static synchronized long updateCallback(long baseTime) { + long nextTime = 0L; + if (state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP) { + long period; + // note we + if (0 == (cdMode & CD_MODE_DOUBLE_SPEED)) { + period = Quartz.SEC / 150; + //if (threes != 0) period++; + } else { + period = Quartz.SEC / 300; + //if (threes == 2) period++; + } + //threes = threes++; + //if (threes == 3) threes = 0; + //if (0 != (cdMode & CD_MODE_XA)) period = ((period << 8) - period) >> 8; + + //if (state==STATE_READS) + // period = period * 300; + if (traceCD) log.info("adding clock callback"); + nextTime = baseTime + period; + if (!scheduler.isScheduled(sectorTick)) { + scheduler.schedule(baseTime + period, sectorTick); + } else { + if (traceCD) log.debug("clock callback already exists; skipping add"); + } + } + return nextTime; + } + + static int foobarCount = 0; + + static boolean toggle; + + private static synchronized long handleSectorTick(long currentTime) { + if (traceCD) log.info("enter callback; state=" + state); + switch (state) { + case STATE_SEEKL: + if (substate == 0) { + if (sectorThread.sectorsReady(true)) { + queueResult(newCompleteStatusResult()); + substate = 1; + } + } + break; + case STATE_SEEKP: + currentLocation.nextSpin(); + break; + case STATE_PLAY: + if (sectorThread.sectorsReady(substate == 0)) { + substate = 1; + if (sectorThread.filterDASector()) { + // todo maybe this should be result queue is not full + if (0 != (cdMode & CD_MODE_REPORT) && resultQueueIsEmpty()) { + CmdResult res = new CmdResult(); + + int track = getTrack(currentLocation.getM(), currentLocation.getS(), currentLocation.getF()); + int remainingM = 0; + int remainingS = 0; + if (media != null) { + if (track >= media.getFirstTrack() && track <= media.getLastTrack()) { + int endMSF = media.getTrackMSF(track == media.getLastTrack() ? 0 : track + 1); + int endM = CDUtil.fromBCD((endMSF >> 16) & 0xff); + int endS = CDUtil.fromBCD((endMSF >> 8) & 0xff); + int endF = CDUtil.fromBCD(endMSF & 0xff); + int remainingSectors = ((endM * 60) + endS) * 75 + endF - 150; + remainingSectors -= currentLocation.getSector(); + remainingSectors /= 75; + remainingS = remainingSectors % 60; + remainingM = remainingSectors / 60; + } + } + + // made up check + res.type = CmdResult.DATAREADY; + res.add(1); // ? + res.add(track); // track number + res.add(0); + toggle = !toggle; + if (toggle) { + res.add(CDUtil.toBCD(remainingM)); + res.add(CDUtil.toBCD(remainingS)); // ? + } else { + res.add(CDUtil.toBCD(currentLocation.getM())); + res.add(CDUtil.toBCD(currentLocation.getS()) | 0x80); + } + res.add(0); + res.add(0); + res.add(0); + queueResult(res); + } + } + } + break; + case STATE_READN: + // todo; end of file (or is dataend the end of the track?) + + // todo this can cause us to slow audio down, but that isn't our problem right now + if (sectorThread.sectorsReady(substate == 0)) { + substate = 1; + if (sectorThread.filterDataSector()) { + if (sectorDismissed) { + if (!checkSomeDataRead()) break; + if (rateLimit2Exceeded()) break; + if (rateLimit2) actualSectors++; + someDataRead = false; + sectorDismissed = false; + if (false || traceCD) log.trace("ah.. setting data ready"); + queueResult(newDataReadyStatusResult()); + } + } + } + break; + case STATE_READS: + // todo; end of file (or is dataend the end of the track?) + // todo, figure out what to do about sectorRequested... + if (sectorThread.sectorsReady(substate == 0)) { + substate = 1; + if (sectorThread.filterDataSector()) { + if (sectorDismissed) { + if (!checkSomeDataRead()) break; + if (rateLimit2Exceeded()) break; + if (rateLimit2) actualSectors++; + someDataRead = false; + sectorDismissed = false; + if (false || traceCD) log.trace("ah.. setting data ready"); + queueResult(newDataReadyStatusResult()); + } else { +// foobarCount++; + // if (0==(foobarCount&15)) + // log.trace("skipping sector ready for reads"); + } + } + } + break; + } + if (traceCD) log.trace("leave callback; state=" + state); + return updateCallback(currentTime); + } + + private static boolean checkSomeDataRead() { + if (waitForDataReadCounter > 0) { + waitForDataReadCounter--; + if (waitForDataReadCounter == 0) { + log.trace("DATA READ CHECK TIMEOUT!!!!!"); + } + return waitForDataReadCounter == 19; + } + return !(waitForDataRead && !someDataRead); + } + + private static void setSomeDataRead() { + if (waitForDataReadCounter > 0) { + if (SCP.EXCEPT_INTERRUPT == scp.currentExceptionType()) { + log.trace("DATA READ FROM IRQ - don't need hack"); + } else { + log.trace("DATA READ FROM non-IRQ - NEED HACK"); + waitForDataRead = true; + } + waitForDataReadCounter = 0; + } + someDataRead = true; + } + + private static void dismissSector() { + if (sectorDismissed || !sectorReady) + return; + + sectorThread.copySector(currentSector); + switch (cdMode & 0x30) { + case 0x00: + currentSectorOffset = 24; + currentSectorEnd = 24 + 2048; + break; + case 0x10: + currentSectorOffset = 12; + currentSectorEnd = 12 + 2328; + break; + case 0x20: + currentSectorOffset = 12; + currentSectorEnd = 12 + 2340; + break; + case 0x30: + currentSectorOffset = 24; + currentSectorEnd = 24 + 2328; + break; + } + sectorDismissed = true; + sectorReady = false; + } + + private static void prepareSector() { + if (currentSectorOffset == currentSectorEnd) { + dismissSector(); + } + } + + private static SectorTick sectorTick = new SectorTick(); + + private static class SectorTick implements ScheduledAction { + private int time; + + public void setTime(int t) { + time = t; + } + + public int getTime() { + return time; + } + + public long run(long currentTime) { + // long now = System.nanoTime(); + // double delta = (now-base)/1000000.0; + // log.info("CD time "+delta); + return handleSectorTick(currentTime); + } + } + + private static class SectorThread extends Thread { + private static final int SECTOR_BUFFERS = 32; + private static final int BUFFERS_BEFORE_READ = 8; + private static final int MIN_SECTOR_RUN = 8; // should always read this many sectors sequentially. + private HeadLocation[] sectorLocations = new HeadLocation[SECTOR_BUFFERS]; + private byte[][] sectorBuffers = new byte[SECTOR_BUFFERS][]; + private int sectorBufferNextRead; + private int sectorBufferNextWrite; + private HeadLocation readLocation = new HeadLocation(); + private boolean stateChanged; + private boolean locationChanged; + + public SectorThread() { + super("Sector read thread"); + for (int i = 0; i < SECTOR_BUFFERS; i++) { + sectorLocations[i] = new HeadLocation(); + sectorBuffers[i] = new byte[2352]; + } + + setPriority(NORM_PRIORITY + 2); + setDaemon(true); + start(); + } + + public void newState() { + assert Thread.holdsLock(CD.class); + stateChanged = true; + if (sectorBufferNextRead != sectorBufferNextWrite && sectorLocations[sectorBufferNextRead].getSector() == currentLocation.getSector()) { + if (traceCD) log.trace("CD: updateLocation is identical to old one, so nop"); + } else { + locationChanged = true; + readLocation.init(currentLocation); + // for now, clear buffer + sectorBufferNextRead = sectorBufferNextWrite; + } + seeking = state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP; + } + + public boolean filterDataSector() { + assert Thread.holdsLock(CD.class); + // todo filter! + assert sectorBufferNextRead != sectorBufferNextWrite; + + byte[] sector = sectorBuffers[sectorBufferNextRead]; + // xa audio submode == 0x64 +// log.trace( MiscUtil.toHex( (sector[4]>>16)&0xff, 8)); + //if (0!=(cdMode&CD_MODE_XA)) System.out.println(MiscUtil.toHex(sector[16],2)+" "+MiscUtil.toHex(sector[18],2)); + if (0x64 == sector[18]) { + if (0 != (cdMode & CD_MODE_XA)) { + if (0 == (cdMode & CD_MODE_FILTER) || (filterFile == (sector[16]) && filterChannel == (sector[17]))) { + if (!handleXASector(sector)) + return false; + } else { + // need to track that we've had a sector + if (rateLimit2) actualSectors++; + //log.trace("Skipping unfiltered sector "+(sector[4]&0xff)+" "+((sector[4]>>8)&0xff)); + } + } + currentLocation.init(sectorLocations[sectorBufferNextRead]); + //if (traceCD) log.info( "skipping XA audio sector"); + sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; + int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; + if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { + CD.class.notify(); + } + return false; + } + return true; + } + + public boolean filterDASector() { + assert Thread.holdsLock(CD.class); + // todo filter! + assert sectorBufferNextRead != sectorBufferNextWrite; + + byte[] sector = sectorBuffers[sectorBufferNextRead]; + + if (handleDASector(sector)) { + currentLocation.init(sectorLocations[sectorBufferNextRead]); + sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; + int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; + if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { + CD.class.notify(); + } + return true; + } + return false; + } + + public boolean sectorsReady(boolean seek) { + assert Thread.holdsLock(CD.class); + int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; + boolean rc = seek ? (sectors > BUFFERS_BEFORE_READ) : (sectors > 0); + if (traceCD) log.trace("sectors now: " + sectors); + seeking = !rc; + return rc; + } + + public void copySector(int[] target) { + synchronized (CD.class) { + byte[] byteBuf = sectorBuffers[sectorBufferNextRead]; + + for (int i = 0; i < 2352 / 4; i++) { + currentSector[i] = ((((int) byteBuf[i * 4 + 3]) & 0xff) << 24) | + ((((int) byteBuf[i * 4 + 2]) & 0xff) << 16) | + ((((int) byteBuf[i * 4 + 1]) & 0xff) << 8) | + ((((int) byteBuf[i * 4]) & 0xff)); + } + currentLocation.init(sectorLocations[sectorBufferNextRead]); + + if (traceCD) log.trace("COPY SECTOR " + MiscUtil.toHex(target[3], 6) + " " + currentLocation); + + // todo - this is only valid for data/xa sectors +// assert CDUtil.fromBCD( target[3] & 0xff ) == currentLocation.getM() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; +// assert CDUtil.fromBCD( (target[3] >> 8) & 0xff ) == currentLocation.getS() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; +// assert CDUtil.fromBCD( (target[3] >> 16) & 0xff ) == currentLocation.getF() : "sectors don't match " + MiscUtil.toHex( target[3], 6 ) + " " + currentLocation; + sectorBufferNextRead = (sectorBufferNextRead + 1) % SECTOR_BUFFERS; + int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; + if (sectors < SECTOR_BUFFERS - MIN_SECTOR_RUN - 2) { + CD.class.notify(); + } + } + } + + public void run() { + log.info("SectorThread starts"); + try { + while (true) { + boolean read; + synchronized (CD.class) { + read = state == STATE_READN || state == STATE_READS || (state == STATE_PLAY && softwareCDDA) || state == STATE_SEEKL || state == STATE_SEEKP; + int sectors = (sectorBufferNextWrite + SECTOR_BUFFERS - sectorBufferNextRead) % SECTOR_BUFFERS; + if (read) { + if (sectors != SECTOR_BUFFERS - 2) { + sectorLocations[sectorBufferNextWrite].init(readLocation); + read = true; + } else { + read = false; + } + } + locationChanged = false; + stateChanged = false; + } + + if (read) { + if (traceCD) log.trace("reading sector " + readLocation); + try { + media.readSector(readLocation.getSector(), sectorBuffers[sectorBufferNextWrite]); + } catch (MediaException e) { + } + if (traceCD) + log.trace("read sector complete " + MiscUtil.toHex(sectorBuffers[sectorBufferNextWrite][3], 6) + " " + readLocation); + } + + synchronized (CD.class) { + // only want to update stuff if we didn't change location in the interim + if (read && !locationChanged) { + sectorBufferNextWrite = (sectorBufferNextWrite + 1) % SECTOR_BUFFERS; + readLocation.nextSequential(); + } + // sleep if we had nothing to do, and noone issued a new command in the interim + if (!read && !stateChanged) { + try { + if (traceCD) log.trace("SectorThread sleeps"); + CD.class.wait(); + if (traceCD) log.trace("SectorThread wakes"); + } catch (InterruptedException e) { + } + } + } + } + } finally { + log.info("SectorThread ends"); + } + } + } + + private static void resetAudio() { + xaDecoder.reset(); + cdFreq = 0; + rateLimitEnabled = false; + } + + private static final byte[] audioBuffer = new byte[4032 * 4]; + + private static boolean handleXASector(byte[] sectorBuffer) { + int samples = 0; + if (cdFreq == 0) { + if (cdAudioSink != null) { + cdAudioSink.newCDAudio(); + } + // need to decode to find the frequency + samples = xaDecoder.decodeXAAudioSector(sectorBuffer, audioBuffer); + if (cdFreq != xaDecoder.getFrequency()) { + cdFreq = xaDecoder.getFrequency(); + if (cdAudioSink != null) { + cdAudioSink.setCDAudioRate(cdFreq); + } + } + } + + if (rateLimit1Exceeded()) return false; + if (rateLimit2Exceeded()) return false; + + if (cdAudioSink != null && cdAudioSink.isCDAudible()) { + if (samples == 0) samples = xaDecoder.decodeXAAudioSector(sectorBuffer, audioBuffer); + actualAudioBytes += samples * 4; + //samples = Resample.resample(audioBuffer,xaDecoder.getFrequency(),samples,audioBuffer2,44100); + //cdAudioSink.cdAudioData(audioBuffer2,0,samples*4); + // todo we might want to send data anyway? + boolean started = cdAudioSink.cdAudioData(audioBuffer, 0, samples * 4); + if (rateLimit1 || rateLimit2) { + if (started) { + if (!rateLimitEnabled) { + rateLimitEnabled = true; + if (rateLimit1) actualAudioBytes = 0; + if (rateLimit2) actualSectors = 0; + rateLimitStartTime = quartz.nanoTime(); + // todo should we rate limit anyway? + rateLimitEnabled = true; + } else { + if (rateLimit2) actualSectors++; + } + } + } + } + return true; + } + + private static boolean handleDASector(byte[] sectorBuffer) { + if (cdFreq == 0) { + cdFreq = 44100; + if (cdAudioSink != null) { + cdAudioSink.newCDAudio(); + cdAudioSink.setCDAudioRate(cdFreq); + } + } + + if (rateLimit1Exceeded()) return false; + if (rateLimit2Exceeded()) return false; + + if (cdAudioSink != null && cdAudioSink.isCDAudible()) { + boolean started = cdAudioSink.cdAudioData(sectorBuffer, 0, 2352); + if (rateLimit1 || rateLimit2) { + if (started) { + if (!rateLimitEnabled) { + rateLimitEnabled = true; + if (rateLimit1) actualAudioBytes = 0; + if (rateLimit2) actualSectors = 0; + rateLimitStartTime = quartz.nanoTime(); + // todo should we rate limit anyway? + rateLimitEnabled = true; + } else { + if (rateLimit2) actualSectors++; + } + } + } + } + return true; + } + + private static boolean rateLimit1Exceeded() { + if (!(rateLimitEnabled && rateLimit1)) return false; + long time = quartz.nanoTime(); + assert false; + int expectedAudioBytes = (int) ((cdFreq * (time - rateLimitStartTime)) / 4000L); + if (log.isDebugEnabled()) { + log.debug(expectedAudioBytes + " " + actualAudioBytes); + } + + return actualAudioBytes > expectedAudioBytes; + } + + private static boolean rateLimit2Exceeded() { + if (!(rateLimitEnabled && rateLimit2)) return false; + long time = quartz.nanoTime(); + int sps = (cdMode & CD_MODE_DOUBLE_SPEED) != 0 ? 150 : 75; + + int expectedSectors = (int) ((sps * (time - rateLimitStartTime)) / Quartz.SEC); + if (log.isDebugEnabled()) { +// log.debug(expectedSectors+" "+actualSectors); + } + + return actualSectors > expectedSectors; + } + + /** + * @param m + * @param s + * @param f + * @return + */ + private static int getTrack(int m, int s, int f) { + int MSF = CDUtil.toMSF(m, s, f); + if (media != null) { + int rc = 0; + for (int i = media.getFirstTrack(); i <= media.getLastTrack(); i++) { + int trackMSF = media.getTrackMSF(i); + if (MSF < trackMSF) return rc; + rc++; + } + if (MSF < media.getTrackMSF(0)) { + return rc; + } + } + return 0; + } +} + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java new file mode 100644 index 0000000..feaccaf --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.cd; + +import org.apache.log4j.Logger; + +// todo finish this +/** + * Based on Kazzuya - Audio XA decode + */ +public class XADecoder { + Logger log = Logger.getLogger("XADecode"); + private static int[] IK0 = new int[]{0, -60, -115, -98, -122}; + private static int[] IK1 = new int[]{0, 0, 52, 55, 60}; + + //private static int[] headTable = new int[] {0,2,8,10}; + private static int[] headTable = new int[]{4, 6, 8, 10}; + + private static class ChannelContext { + public int y0; + public int y1; + + public void reset() { + y0 = y1 = 0; + } + } + + private ChannelContext leftContext = new ChannelContext(); + private ChannelContext rightContext = new ChannelContext(); + private boolean firstSector = false; + private boolean invalid; + private int freq; + private int bps; + private boolean stereo; + + private static final int BLOCK_SIZE = 28; + + public XADecoder() { + reset(); + } + + public void reset() { + leftContext.reset(); + rightContext.reset(); + firstSector = true; + } + + private void decodeBlock16(ChannelContext context, int filterRange, int[] src, byte[] dest, int destOffset, int inc) { + int filterId = (filterRange >> 4) & 0x0f; + int range = (filterRange & 0x0f) + 12; + + filterId &= 3; + + int fy0, fy1; + fy0 = context.y0; + fy1 = context.y1; + + int ik0 = IK0[filterId]; + int ik1 = IK1[filterId]; + + int s = 0; + int d = destOffset; + for (int i = BLOCK_SIZE / 4; i > 0; i--) { + int x = src[s++]; + int x0 = (x << 28) >> range; + x0 -= (ik0 * fy0 + ik1 * fy1) >> 6; + if (x0 > 524072) x0 = 524072; + else if (x0 < -525088) x0 = 525088; + dest[d] = (byte) (x0 >> 4); + dest[d + 1] = (byte) (x0 >> 12); + d += inc; + + int x1 = ((x << 24) & 0xf0000000) >> range; + x1 -= (ik0 * x0 + ik1 * fy0) >> 6; + if (x1 > 524072) x1 = 524072; + else if (x1 < -525088) x1 = 525088; + dest[d] = (byte) (x1 >> 4); + dest[d + 1] = (byte) (x1 >> 12); + d += inc; + + int x2 = ((x << 20) & 0xf0000000) >> range; + x2 -= (ik0 * x1 + ik1 * x0) >> 6; + if (x0 > 524072) x2 = 524072; + else if (x2 < -525088) x2 = 525088; + dest[d] = (byte) (x2 >> 4); + dest[d + 1] = (byte) (x2 >> 12); + d += inc; + + int x3 = ((x << 16) & 0xf0000000) >> range; + x3 -= (ik0 * x2 + ik1 * x1) >> 6; + if (x0 > 524072) x3 = 524072; + else if (x3 < -525088) x3 = 525088; + dest[d] = (byte) (x3 >> 4); + dest[d + 1] = (byte) (x3 >> 12); + d += inc; + fy1 = x2; + fy0 = x3; + } + context.y0 = fy0; + context.y1 = fy1; + } + + private int encoded[] = new int[14]; + + private int decode(byte[] src, int srcOffset, byte[] dest, int destOffset) { + int sound_groupsp; + int sound_datap; + int sound_datap2; + int nbits = bps == 4 ? 4 : 2; + int sampleCount = 0; + + if (stereo) { + for (int j = 0; j < 18; j++) { + sound_groupsp = srcOffset + j * 128; + sound_datap = sound_groupsp + 16; + + for (int i = 0; i < nbits; i++) { + int datap = 0; + sound_datap2 = sound_datap + i; + if ((bps == 8) && (freq == 37800)) { // level A + for (int k = 0; k < 14; k++, sound_datap2 += 8) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | + ((((int) src[sound_datap2 + 4]) & 0xff) << 8); + } + } else { // level B/C + for (int k = 0; k < 7; k++, sound_datap2 += 16) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xf) | + ((((int) src[sound_datap2 + 4]) & 0xf) << 4) | + ((((int) src[sound_datap2 + 8]) & 0xf) << 8) | + ((((int) src[sound_datap2 + 12]) & 0xf) << 12); + } + } + decodeBlock16(leftContext, src[sound_groupsp + headTable[i]], encoded, dest, destOffset, 4); + + datap = 0; + sound_datap2 = sound_datap + i; + if ((bps == 8) && (freq == 37800)) { // level A + for (int k = 0; k < 14; k++, sound_datap2 += 8) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | + ((((int) src[sound_datap2 + 4]) & 0xff) << 8); + } + } else { // level B/C + for (int k = 0; k < 7; k++, sound_datap2 += 16) { + encoded[datap++] = ((((int) src[sound_datap2]) & 0xf0) | + ((((int) src[sound_datap2 + 4]) & 0xf0) << 4) | + ((((int) src[sound_datap2 + 8]) & 0xf0) << 8) | + ((((int) src[sound_datap2 + 12]) & 0xf0) << 12)) >> 4; + } + } + decodeBlock16(rightContext, src[sound_groupsp + headTable[i] + 1], encoded, dest, destOffset + 2, 4); + destOffset += 28 * 4; + sampleCount += 28; + } + } + } else { // mono + for (int j = 0; j < 18; j++) { + sound_groupsp = srcOffset + j * 128; + sound_datap = sound_groupsp + 16; + + for (int i = 0; i < nbits; i++) { + int datap = 0; + sound_datap2 = sound_datap + i; + if ((bps == 8) && (freq == 37800)) { // level A + for (int k = 0; k < 14; k++, sound_datap2 += 8) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | + ((((int) src[sound_datap2 + 4]) & 0xff) << 8); + } + } else { // level B/C + for (int k = 0; k < 7; k++, sound_datap2 += 16) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xf) | + ((((int) src[sound_datap2 + 4]) & 0xf) << 4) | + ((((int) src[sound_datap2 + 8]) & 0xf) << 8) | + ((((int) src[sound_datap2 + 12]) & 0xf) << 12); + } + } + decodeBlock16(leftContext, src[sound_groupsp + headTable[i]], encoded, dest, destOffset, 4); + destOffset += 28 * 4; + sampleCount += 28; + + datap = 0; + sound_datap2 = sound_datap + i; + if ((bps == 8) && (freq == 37800)) { // level A + for (int k = 0; k < 14; k++, sound_datap2 += 8) { + encoded[datap++] = (((int) src[sound_datap2]) & 0xff) | + ((((int) src[sound_datap2 + 4]) & 0xff) << 8); + } + } else { // level B/C + for (int k = 0; k < 7; k++, sound_datap2 += 16) { + encoded[datap++] = ((((int) src[sound_datap2]) & 0xf0) | + ((((int) src[sound_datap2 + 4]) & 0xf0) << 4) | + ((((int) src[sound_datap2 + 8]) & 0xf0) << 8) | + ((((int) src[sound_datap2 + 12]) & 0xf0) << 12)) >> 4; + } + } + decodeBlock16(leftContext, src[sound_groupsp + headTable[i] + 1], encoded, dest, destOffset, 4); + destOffset += 28 * 4; + sampleCount += 28; + } + } +/* for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + + */ +// throw new IllegalStateException("mono"); + } + return sampleCount; + } + + public int decodeXAAudioSector(byte[] sector, byte[] samples) { + if (firstSector) { + int coding = sector[19]; + switch ((coding >> 2) & 3) { + case 0: + freq = 37800; + break; + case 1: + freq = 18900; + break; + default: + invalid = true; + break; + } + switch ((coding >> 4) & 3) { + case 0: + bps = 4; + break; + case 1: + bps = 8; + break; + default: + invalid = true; + break; + } + switch (coding & 3) { + case 0: + stereo = false; + break; + case 1: + stereo = true; + break; + default: + invalid = true; + break; + } + if (invalid) { + log.debug("INVALID XA"); + } else { + log.debug("XA " + freq + "x" + bps + " " + (stereo ? "stereo" : "mono")); + } + reset(); + firstSector = false; + } + if (invalid) { + return 0; + } + return decode(sector, 24, samples, 0); + } + + public int getFrequency() { + return freq; + } +} \ No newline at end of file diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/counters/Counters.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/counters/Counters.java new file mode 100644 index 0000000..e98b1bf --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/counters/Counters.java @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.counters; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.ScheduledAction; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.api.components.hardware.cd.CDDrive; +import org.jpsx.api.components.hardware.cd.CDMedia; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.IRQOwnerBase; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.CDUtil; +import org.jpsx.runtime.util.MiscUtil; + +// todo pick NTSC or PAL other than by media. + +// todo IRQs for root counters +public class Counters extends SingletonJPSXComponent implements MemoryMapped { + public static final String CATEGORY = "Counters"; + public static final Logger log = Logger.getLogger(CATEGORY); + + public static final int ADDR_HARD_COUNTER0_COUNT = 0x1f801100; + public static final int ADDR_HARD_COUNTER1_COUNT = 0x1f801110; + public static final int ADDR_HARD_COUNTER2_COUNT = 0x1f801120; + public static final int ADDR_HARD_COUNTER0_MODE = 0x1f801104; + public static final int ADDR_HARD_COUNTER1_MODE = 0x1f801114; + public static final int ADDR_HARD_COUNTER2_MODE = 0x1f801124; + public static final int ADDR_HARD_COUNTER0_TARGET = 0x1f801108; + public static final int ADDR_HARD_COUNTER1_TARGET = 0x1f801118; + public static final int ADDR_HARD_COUNTER2_TARGET = 0x1f801128; + + private static final long CLOCK_FREQ = 33868800L; + + private static final int NTSC_VSYNC_FREQ = 60; + private static final int PAL_VSYNC_FREQ = 50; + private static long VSYNC_FREQ; + private static long HSYNC_FREQ; + private static long PIXEL_FREQ; + + private static long VSYNC_PERIOD; + + private static Counter[] counters; + + private static boolean bandicootUS; + private static IRQController irqController; + private static Quartz quartz; + private static Scheduler scheduler; + + public Counters() { + super("JPSX Hardware Counters"); + } + + public void init() { + super.init(); //To change body of overridden methods use File | Settings | File Templates. + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + // default to something + setNTSC(true); + bandicootUS = getBooleanProperty("bandicootUS", false); + log.info("Bandicoot = " + bandicootUS); + counters = new Counter[3]; + counters[0] = new Counter(0); + counters[1] = new Counter(1); + counters[2] = new Counter(2); + for (Counter counter : counters) { + CoreComponentConnections.IRQ_OWNERS.add(counter.getIrq()); + } + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + irqController = CoreComponentConnections.IRQ_CONTROLLER.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + scheduler = CoreComponentConnections.SCHEDULER.resolve(); + } + + public void begin() { + for (Counter counter : counters) { + counter.init(); + } + CDDrive drive = HardwareComponentConnections.CD_DRIVE.resolve(); + CDMedia media = drive == null ? null : drive.getCurrentMedia(); + + if (0 != (CDUtil.getMediaType(media) & CDUtil.MEDIA_REGION_EUROPE)) { + log.info("Picking PAL based on current media"); + setNTSC(false); + } else { + log.info("Picking NTSC based on current media"); + setNTSC(true); + } + new VSyncAction().start(); + } + + // todo, one shot? + static class Counter { + // psx + private int index; // counter num + private int mode; + private int target; + + // counting + private long freq; // incs per second + private int baseValue; + private long baseTime; + private long lastElapsed; + private int delta; + private boolean toggle; + + // irqs + private boolean irqsEnabled; + private long irqPeriod; // 1/4096 ms + + private IRQ irq; + + private class IRQ extends IRQOwnerBase { + public IRQ() { + super(4 + index, "COUNTER " + index); + } + } + + public IRQ getIrq() { + return irq; + } + + public Counter(int index) { + this.index = index; + irq = new IRQ(); + } + + public void init() { + setValue(0); + setTarget(0); + } + + public int getMode() { + return mode; + } + + public void setMode(int mode) { + if (log.isDebugEnabled()) { + log.debug("COUNTER " + index + " mode " + MiscUtil.toHex(mode, 8)); + } + this.mode = mode; + update(); + } + + public void setValue(int value) { + baseTime = quartz.nanoTime(); + lastElapsed = -1; + delta = 0; + baseValue = value; + //System.out.println("Set value "+value); + //System.out.println("COUNTER "+index+" setvalue = "+value+" pc="+MiscUtil.toHex(r3000.getPC(),8)); + } + + public int getValue() { + long elapsed = quartz.nanoTime() - baseTime; + int newValue = baseValue + (int) (elapsed * freq / Quartz.SEC); + /* - this should be irrelevent now we have nanoTime + if (elapsed == lastElapsed) { + // count up to the amount we'll reach on the next + // millisecond tick + if (toggle) { + toggle = !toggle; + } else { + if (delta < ((inc >> 12) - 1)) { + delta++; + } + newValue += delta; + } + } else { + lastElapsed = elapsed; + delta = 0; + } */ + // todo this looks wrong; since newValue may roll over. + int rc = newValue % (target + 1); + if (log.isTraceEnabled()) { + log.trace("read counter " + index + " " + rc + " " + MiscUtil.toHex(CoreComponentConnections.R3000.resolve().getPC(), 8)); + } + //System.out.println("counter "+index+" "+rc); + //System.out.println("COUNTER "+index+" getvalue = "+rc+" pc="+MiscUtil.toHex(r000.getPC(),8)); + return rc; + } + + public void setTarget(int target) { + target = target & 0xffff; + if (target == 0) { + target = 0x10000; + } + this.target = target; + update(); + } + + public int getTarget() { + return target & 0xffff; + } + + public void setTime(int previous) { + assert irqsEnabled; + //callbackTime = previous + irqPeriod; + } + + private synchronized void update() { + long newFreq = -1L; + switch (mode & 0x300) { + case 0: + newFreq = CLOCK_FREQ; + break; + case 0x100: + if (index == 0) { + // pixel + newFreq = PIXEL_FREQ; + } else if (index == 1) { + // horiz + newFreq = HSYNC_FREQ; + } + break; + case 0x200: + if (index == 2) { + // 1/8th system scheduler + newFreq = CLOCK_FREQ / 8; + } else { + newFreq = CLOCK_FREQ; + } + break; + case 0x300: + break; + } + if (newFreq == -1) { + log.warn("COUNTER " + index + " unknown clock rate; mode " + MiscUtil.toHex(mode, 4)); + newFreq = CLOCK_FREQ; + } + // note round up; for example Wipeout counts hsyncs, and does an extra + // vsync if we come in at 623 for two vsync rather than 624 + //freq = ((newFreq << 12) + 999) / 1000; + freq = newFreq + 1; + if (log.isDebugEnabled()) { + log.debug("COUNTER " + index + " frequency " + newFreq); + } + if ((mode & 0x50) == 0x50 && (index != 2 || (mode & 1) == 0)) { + long ips = newFreq / target; // Hz + log.info("REQUIRE COUNTER IRQ COUNTER " + index + " FREQ " + newFreq + " TARGET " + target + " IPS " + ips); + //irqPeriod = 4096000L/freq // microseconds + + if (!irqsEnabled) { + irqsEnabled = true; + } + //baseTime = MTScheduler.getTime(); + //setTime( baseTime); + //MTScheduler.addCallback( this); + } else { + irqsEnabled = false; + } + } + } + + public void registerAddresses(AddressSpaceRegistrar registrar) { + for (int i = 0; i <= 0x20; i += 0x10) { + registrar.registerRead32Callback(ADDR_HARD_COUNTER0_COUNT + i, Counters.class, "countRead32", true); + registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_COUNT + i, Counters.class, "countWrite32", true); + registrar.registerRead32Callback(ADDR_HARD_COUNTER0_MODE + i, Counters.class, "modeRead32", true); + registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_MODE + i, Counters.class, "modeWrite32", true); + registrar.registerRead32Callback(ADDR_HARD_COUNTER0_TARGET + i, Counters.class, "targetRead32", true); + registrar.registerWrite32Callback(ADDR_HARD_COUNTER0_TARGET + i, Counters.class, "targetWrite32", true); + } + } + + private static Counter getCounter(int address) { + return counters[(address & 0x30) >> 4]; + } + + public static int countRead32(int address) { + return getCounter(address).getValue(); + } + + public static void countWrite32(int address, int value, int mask) { + getCounter(address).setValue(value & 0xffff); + } + + public static int modeRead32(int address) { + return getCounter(address).getMode(); + } + + public static void modeWrite32(int address, int value, int mask) { + Counter c = getCounter(address); + c.setMode((c.getMode() & ~mask) | (value & mask)); + } + + public static int targetRead32(int address) { + return getCounter(address).getTarget(); + } + + public static void targetWrite32(int address, int value, int mask) { + Counter c = getCounter(address); + mask &= 0xffff; + c.setTarget((c.getTarget() & ~mask) | (value & mask)); + } + + public static void setNTSC(boolean NTSC) { + VSYNC_FREQ = NTSC ? NTSC_VSYNC_FREQ : PAL_VSYNC_FREQ; + VSYNC_PERIOD = Quartz.SEC / VSYNC_FREQ; + int scans = NTSC ? 525 : 625; + HSYNC_FREQ = VSYNC_FREQ * scans / 2; + // todo; does this change with the video mode? + // todo is this correct + PIXEL_FREQ = 3840L * HSYNC_FREQ; + if (log.isDebugEnabled()) { + log.debug("HSYNC FREQ: " + HSYNC_FREQ); + log.debug("PIXEL FREQ: " + PIXEL_FREQ); + } + } + + private static class VSyncAction implements ScheduledAction { + private long nextTime; + + public void start() { + nextTime = quartz.nanoTime() + VSYNC_PERIOD; + scheduler.schedule(nextTime, this); + } + + public long run(long currentTime) { + irqController.raiseIRQ(IRQController.IRQ_VSYNC); + // if we missed some vsyncs, then skip them + while (currentTime >= nextTime) { + if (bandicootUS && currentTime > Quartz.SEC * 22) { + try { + // bandicoot US + AddressSpace addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + addressSpace.write32(0x80034520, addressSpace.read32(0x80034520) + 17); + } catch (Throwable t) { + } + } + nextTime = nextTime + VSYNC_PERIOD; + } + return nextTime; + } + } +} + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java new file mode 100644 index 0000000..8ba1800 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.gpu; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.hardware.gpu.Display; +import org.jpsx.api.components.hardware.gpu.DisplayManager; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.util.Timing; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; + +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.*; + +/** + * Basic AWT Display implementation. There are other ways to do this, but this seems to work pretty at least as well + * as any other java2d method on most JDKs. + */ +public class AWTDisplay extends JPSXComponent implements Display, KeyListener { + private static final Logger log = Logger.getLogger("Display"); + + public static final String LOCATION_X_PROPERTY = "x"; + public static final String LOCATION_Y_PROPERTY = "y"; + + private Frame frame; + + private int[] ram; // video RAM + private BufferedImage bufferedImage; // image containing video RAM + private DisplayManager displayManager; + private int sourceWidth, sourceHeight; // the size of the source to be stretched to be displayed + + private boolean showBlitTime; + private boolean antiAlias; + + private boolean displayVRAM; + + private boolean funkyfudge; + + private ImageInfo[] imageInfoCache = new ImageInfo[]{ + new ImageInfo(), + new ImageInfo(), + new ImageInfo(), + new ImageInfo() + }; + + private int cacheReplaceIndex; + private VolatileImage volatileImage; + + private int MAX_X = 960; + private int MAX_Y = 512; + + private final int xres[] = new int[]{320, 640, 800, 960, 1024, 1280}; + private final int yres[] = new int[]{256, 512, 600, 768, 768, 1024}; + + private static final int BLIT_TIME_COUNT = 100; + private long blitTimeTotal; + private int blitTimeCount; + private boolean noStretch; + + int resindex = 1; + + public AWTDisplay() { + super("JPSX Default AWT Frame Display"); + } + + @Override + public void init() { + super.init(); + HardwareComponentConnections.DISPLAY.set(this); + RuntimeConnections.KEY_LISTENERS.add(this); + showBlitTime = Boolean.valueOf(getProperty("showBlitTime","true")); + antiAlias = Boolean.valueOf(getProperty("antiAlias","true")); + noStretch = Boolean.valueOf(getProperty("noStretch","false")); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + displayManager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); + } + + public void initDisplay() { + + // todo, make a new initialization state for this + frame = new Frame("JPSX") { + public void paint(Graphics g) { + stretchBlit(g); + } + }; + +// DirectColorModel model = new DirectColorModel( 24, 0x0000ff, 0x00ff00, 0xff0000); + DirectColorModel model = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); + WritableRaster raster = model.createCompatibleWritableRaster(1024, 513); + DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); + ram = db.getData(); + bufferedImage = new BufferedImage(model, raster, true, null); + int w = getIntProperty(LOCATION_X_PROPERTY, -1); + int h = getIntProperty(LOCATION_Y_PROPERTY, -1); + if (w != -1 && h != -1) frame.setLocation(w, h); + frame.show(); + frame.setResizable(false); + sizeframe(); + volatileImage = frame.createVolatileImage(MAX_X, MAX_Y); + frame.addKeyListener(RuntimeConnections.KEY_LISTENERS.resolve()); + frame.addWindowListener(new Closer()); + } + + protected class ImageInfo { + protected int x, y, w, h; + protected Image image; + + public boolean matches(int x, int y, int w, int h) { + return (this.x == x && this.y == y && this.w == w && this.h == h); + } + + public Image update(int x, int y, int w, int h) { + if (image != null) image.flush(); + image = bufferedImage.getSubimage(x, y, w, h); + this.x = x; + this.y = y; + this.w = w; + this.h = h; + return image; + } + + public Image getImage() { + return image; + } + } + +// public void setDisplayManager(DisplayManager manager) { +// displayManager = manager; +// refresh(); +// } + + public Image getImage(int x, int y, int w, int h) { + for (int i = 0; i < imageInfoCache.length; i++) { + if (imageInfoCache[i].matches(x, y, w, h)) { + return imageInfoCache[i].getImage(); + } + } + cacheReplaceIndex = (cacheReplaceIndex + 1) % imageInfoCache.length; + + // todo fix this - caused presumably by not displaying whole image! + if ((x + w) > 1024) { + w = 1024 - x; + } + if ((y + h) > 512) { + h = 512 - y; + } + if (log.isDebugEnabled()) { + log.debug("Creating new image at slot " + cacheReplaceIndex + " " + x + "," + y + " " + w + "," + h); + } + return imageInfoCache[cacheReplaceIndex].update(x, y, w, h); + } + + + protected void sizeframe() { + if (displayVRAM) + frame.setSize(new Dimension(1024 + frame.getInsets().left + frame.getInsets().right, 512 + frame.getInsets().top + frame.getInsets().bottom)); + else + frame.setSize(new Dimension(xres[resindex] + frame.getInsets().left + frame.getInsets().right, yres[resindex] + frame.getInsets().top + frame.getInsets().bottom)); + } + + protected void switchsize() { + resindex++; + if (resindex == xres.length) resindex = 0; + sizeframe(); + } + + // the display buffer should be at least 1024*512 + 192 (+192 due to current texture page problem in GPU). + public int[] acquireDisplayBuffer() { + return ram; + } + + public void releaseDisplayBuffer() { + } + + protected synchronized void stretchBlit(Graphics g) { + int l = frame.getInsets().left; + int t = frame.getInsets().top; + long timeBasis = 0; + if (showBlitTime) { + timeBasis = Timing.nanos(); + } + if (displayVRAM) { + if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + g.drawImage(bufferedImage, l, t, null); + } else { + if (volatileImage != null && !volatileImage.contentsLost()) { + if (antiAlias) ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + if (noStretch) { + g.drawImage(volatileImage, l, t, l + sourceWidth, t + sourceHeight, + 0, 0, sourceWidth, sourceHeight, null); + } else { + g.drawImage(volatileImage, l, t, l + xres[resindex], t + yres[resindex], + 0, 0, sourceWidth, sourceHeight, null); + } + } + } + if (showBlitTime) { + blitTimeTotal += Timing.nanos()-timeBasis; + if (BLIT_TIME_COUNT == ++blitTimeCount) { + double blitTimeMSRounded = (blitTimeTotal/(BLIT_TIME_COUNT*100000))/10.0; + frame.setTitle("JPSX awt - " + ((blitTimeMSRounded >= 1) ? "!SLOW! blit=" : "blit=") + blitTimeMSRounded + "ms"); + blitTimeCount = 0; + blitTimeTotal = 0; + } + } + } + + public synchronized void refresh() { + boolean rgb24 = displayManager.getRGB24(); + if (funkyfudge) { + GPU.setVRAMFormat(!rgb24); + funkyfudge = false; + } + GPU.setVRAMFormat(rgb24); + // for now we use default display size + sourceWidth = displayManager.getDefaultPixelWidth(); + if (rgb24) sourceWidth = (sourceWidth * 3) / 2; + sourceHeight = displayManager.getDefaultPixelHeight(); + if (volatileImage.contentsLost()) { + volatileImage.validate(null); + } + if (displayManager.getBlanked()) { + Graphics2D g2 = volatileImage.createGraphics(); + try { + g2.setColor(Color.BLACK); + g2.fillRect(0, 0, sourceWidth, sourceHeight); + } finally { + g2.dispose(); + } + } else { + Graphics2D g2 = volatileImage.createGraphics(); + int marginLeft = displayManager.getLeftMarginPixels(); + if (rgb24) marginLeft = (marginLeft * 3) / 2; + int marginTop = displayManager.getTopMarginPixels(); + int pixelWidth = displayManager.getPixelWidth(); + if (rgb24) pixelWidth = (pixelWidth * 3) / 2; + int pixelHeight = displayManager.getPixelHeight(); + int marginRight = sourceWidth - pixelWidth - marginLeft; + int marginBottom = sourceHeight - pixelHeight - marginTop; + try { + if (pixelWidth > 0 && pixelHeight > 0) { + g2.drawImage(getImage(displayManager.getXOrigin(), displayManager.getYOrigin(), pixelWidth, pixelHeight), + marginLeft, marginTop, null); + } + g2.setColor(Color.BLACK); + if (marginLeft > 0) { + // fill left + g2.fillRect(0, 0, marginLeft, sourceHeight); + } + if (marginRight > 0) { + // fill left + g2.fillRect(sourceWidth - marginRight, 0, marginRight, sourceHeight); + } + if (marginTop > 0) { + // fill top + g2.fillRect(0, 0, sourceWidth, marginTop); + } + if (marginBottom > 0) { + // fill top + g2.fillRect(0, sourceHeight - marginBottom, sourceWidth, marginBottom); + } + } finally { + g2.dispose(); + } + } + Graphics graphics = frame.getGraphics(); + if (graphics != null) { + try { + stretchBlit(graphics); + } finally { + graphics.dispose(); + } + } + } + + public void keyTyped(KeyEvent e) { + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_F12) { + switchsize(); + } + if (e.getKeyCode() == KeyEvent.VK_F11) { + refresh(); + } + if (e.getKeyCode() == KeyEvent.VK_F10) { + funkyfudge = true; + } + if (e.getKeyCode() == KeyEvent.VK_F9) { + displayVRAM = !displayVRAM; + sizeframe(); + refresh(); + } + if (e.getKeyCode() == KeyEvent.VK_F8) { + for (int i = 0; i < 1024 * 512; i++) { + ram[i] = ram[i] & 0x01ffffff; + } + } + if (e.getKeyCode() == KeyEvent.VK_F7) { + for (int i = 0; i < 1024 * 512; i++) { + ram[i] = ram[i] | 0xfe000000; + } + } + } + + public void keyReleased(KeyEvent e) { + } + + private static class Closer extends WindowAdapter { + public void windowClosing(WindowEvent e) { + RuntimeConnections.MACHINE.resolve().close(); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java new file mode 100644 index 0000000..9459205 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.gpu; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.hardware.gpu.Display; +import org.jpsx.api.components.hardware.gpu.DisplayManager; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; + +// todo change dirty code to only update every now and then... + +// todo this should be a component +public class DefaultDisplayManager extends JPSXComponent implements DisplayManager { + private static final Logger log = Logger.getLogger("Display"); + private long lastRefreshTime = 0; + private boolean hadDirty = false; + private static final long DIRTY_REFRESH_PERIOD = 100 * Quartz.MSEC; + private static final long AUTO_REFRESH_PERIOD = 200 * Quartz.MSEC; + + private Quartz quartz; + private Display display; + + public DefaultDisplayManager() { + super("JPSX Default GPU Display Manager"); + } + + + public void init() { + super.init(); + HardwareComponentConnections.DISPLAY_MANAGER.set(this); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + display = HardwareComponentConnections.DISPLAY.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + } + + private static boolean intersects(int x0, int y0, int w0, int h0, int x1, int y1, int w1, int h1) { + if (w0 == 0 || h0 == 0 || w1 == 0 || h1 == 0) return false; + w0 += x0; + w1 += x1; + h0 += y0; + h1 += y1; + return (w0 > x1) && (h0 > y1) && (w1 > x0) && (h1 > y0); + } + + private static class State { + public int hStart; + public int hEnd; + public int vStart; + public int vEnd; + public boolean blanked; + public boolean NTSC; + public boolean interlaced; + public boolean doubleY; + public boolean rgb24; + public int pixelDivider = 8; + + public int xOrigin; + public int yOrigin; + + public int x0Dirty; + public int y0Dirty; + public int x1Dirty; + public int y1Dirty; + + protected int getDefaultTimingLeft() { + return NTSC ? 608 : 628; + } + + protected int getDefaultTimingTop() { + return NTSC ? 16 : 40; + } + + protected int getDefaultTimingWidth() { + return 2560; + } + + protected int getDefaultTimingHeight() { + return NTSC ? 240 : 256; + } + + public int getDefaultPixelWidth() { + return getDefaultTimingWidth() / pixelDivider; + } + + public int getDefaultPixelHeight() { + int rc = getDefaultTimingHeight(); + if (doubleY) { + rc <<= 1; + } + return rc; + } + + public int getPixelWidth() { + return (hEnd - hStart) / pixelDivider; + } + + public int getPixelHeight() { + int rc = vEnd - vStart; + if (doubleY) { + rc <<= 1; + } + return rc; + } + + public int getLeftMargin() { + return hStart - getDefaultTimingLeft(); + } + + public int getLeftMarginPixels() { + return getLeftMargin() / pixelDivider; + } + + public int getRightMargin() { + return getDefaultTimingLeft() + getDefaultTimingWidth() - hEnd; + } + + public int getRightMarginPixels() { + return getRightMargin() / pixelDivider; + } + + public int getTopMargin() { + return vStart - getDefaultTimingTop(); + } + + public int getTopMarginPixels() { + int rc = getTopMargin(); + + if (doubleY) { + rc <<= 1; + } + return rc; + } + + public int getBottomMargin() { + return getDefaultTimingTop() + getDefaultTimingHeight() - vEnd; + } + + public int getBottomMarginPixels() { + int rc = getBottomMargin(); + + if (doubleY) { + rc <<= 1; + } + return rc; + } + + public boolean isDirty() { + if (x0Dirty == x1Dirty) return false; + //System.out.println("CHECKING DIRTY: disp "+xOrigin+","+yOrigin+" x "+getPixelWidth()+","+getPixelHeight()+"\n"+ + // "dirty "+x0Dirty+","+y0Dirty+" by "+(x1Dirty-x0Dirty)+","+(y1Dirty-y0Dirty)); + boolean rc = intersects(xOrigin, yOrigin, getPixelWidth(), getPixelHeight(), + x0Dirty, y0Dirty, x1Dirty - x0Dirty, y1Dirty - y0Dirty); + //if (rc) System.out.println(" INTERSECT DIRTY!"); + return rc; + } + + public void dirtyRectangle(int x, int y, int w, int h) { + int x1 = x + w; + int y1 = y + h; + if (x0Dirty == x1Dirty) { + x0Dirty = x; + y0Dirty = y; + x1Dirty = x1; + y1Dirty = y1; + } else { + if (x < x0Dirty) x0Dirty = x; + if (x1 > x1Dirty) x1Dirty = x1; + if (y < y0Dirty) y0Dirty = y; + if (y1 > y1Dirty) y1Dirty = y1; + } +// System.out.println("SET DIRTY: disp "+xOrigin+","+yOrigin+" x "+getPixelWidth()+","+getPixelHeight()+"\n"+ +// "dirty "+x0Dirty+","+y0Dirty+" by "+(x1Dirty-x0Dirty)+","+(y1Dirty-y0Dirty)); + } + + public void reset(State base) { + hStart = base.hStart; + hEnd = base.hEnd; + vStart = base.vStart; + vEnd = base.vEnd; + xOrigin = base.xOrigin; + yOrigin = base.yOrigin; + blanked = base.blanked; + NTSC = base.NTSC; + interlaced = base.interlaced; + rgb24 = base.rgb24; + pixelDivider = base.pixelDivider; + doubleY = base.doubleY; + + x0Dirty = x1Dirty; // empty dirty region + } + + public boolean matches(State other) { + return xOrigin == other.xOrigin && + yOrigin == other.yOrigin && + hStart == other.hStart && + hEnd == other.hEnd && + vStart == other.vStart && + vEnd == other.vEnd && + blanked == other.blanked && + NTSC == other.NTSC && + interlaced == other.interlaced && + doubleY == other.doubleY && + pixelDivider == other.pixelDivider && + rgb24 == other.rgb24; + } + + public String toString() { + String rc = getDefaultPixelWidth() + "x" + getDefaultPixelHeight() + "x" + (rgb24 ? "24" : "15"); + rc += " displayed: " + getPixelWidth() + "x" + getPixelHeight() + "x" + (rgb24 ? "24" : "15"); + rc += " offset: " + hStart + "," + vStart; + if (blanked) { + rc += " blanked"; + } + rc += NTSC ? " (NTSC)" : " (PAL)"; + rc += " origin " + xOrigin + "," + yOrigin; + return rc; + } + } + + protected State states[] = new State[]{new State(), new State()}; + protected int currentState = 0; + protected boolean interlaceField; + protected boolean forceUpdate; + + public void preAsync() { + updateState(); + } + + // called if a vsync has passed to make sure display is updated if necessary + // (e.g. drawing to display)... usually this does nothing, because setOrigin + // updates display if necessary + public void vsync() { + updateState(); + } + + public void setOrigin(int x, int y) { + // setting the origin takes effect immediately; we take + // any pending display changes + State s = getNextState(); + s.xOrigin = x; + s.yOrigin = y; + updateState(); + } + + protected State getState() { + return states[currentState]; + } + + protected State getNextState() { + return states[currentState ^ 1]; + } + + protected void updateState() { + currentState = currentState ^ 1; + State s = getState(); + boolean refresh = (forceUpdate || !states[0].matches(states[1])); + if (!refresh && s.isDirty()) { + hadDirty = true; + } + long time = quartz.nanoTime(); + if (!refresh && hadDirty && DIRTY_REFRESH_PERIOD < (time - lastRefreshTime)) { + if (log.isDebugEnabled()) { + log.debug("UPDATING DISPLAY BECAUSE DIRTY"); + } + refresh = true; + hadDirty = false; + } + if (!refresh && AUTO_REFRESH_PERIOD < (time - lastRefreshTime)) { + if (log.isDebugEnabled()) { + log.debug("UPDATING DISPLAY BECAUSE HAVEN'T HAD ONE"); + } + refresh = true; + } + if (refresh) { + lastRefreshTime = time; + //System.out.println("UPDATING DISPLAY: "+s.toString()); + forceUpdate = false; + display.refresh(); + } else { +// System.out.println("NOT UPDATING DISPLAY: "+s.toString()); + } + // next state should configure off as we are + getNextState().reset(s); + } + + public void toggleInterlaceField() { + interlaceField = !interlaceField; + forceUpdate = true; + } + + public boolean getInterlaceField() { + return interlaceField; + } + + // mark a display area as changed... if it intersects the next + // display region, then we will get an update at the next vsync, or + // display origin change + public void dirtyRectangle(int x, int y, int w, int h) { + // we only care about the next display state... + getNextState().dirtyRectangle(x, y, w, h); + } + + public void setPixelDivider(int divider) { + getNextState().pixelDivider = divider; + } + + public void setNTSC(boolean NTSC) { + getNextState().NTSC = NTSC; + } + + public boolean getNTSC() { + return getState().NTSC; + } + + public void setInterlaced(boolean interlaced) { + getNextState().interlaced = interlaced; + } + + public boolean getInterlaced() { + return getState().interlaced; + } + + public void setDoubleY(boolean doubleY) { + getNextState().doubleY = doubleY; + } + + public boolean getDoubleY() { + return getState().doubleY; + } + + public void setRGB24(boolean rgb24) { + getNextState().rgb24 = rgb24; + } + + public boolean getRGB24() { + return getState().rgb24; + } + + public void setBlanked(boolean blanked) { + getNextState().blanked = blanked; + } + + public boolean getBlanked() { + return getState().blanked; + } + + public void setHorizontalTiming(int hStart, int hEnd) { + State s = getNextState(); + s.hStart = hStart; + s.hEnd = hEnd; + } + + public void setVerticalTiming(int vStart, int vEnd) { + State s = getNextState(); + s.vStart = vStart; + s.vEnd = vEnd; + } + + public int getDefaultTimingWidth() { + return getState().getDefaultTimingWidth(); + } + + public int getDefaultTimingHeight() { + return getState().getDefaultTimingHeight(); + } + + public int getDefaultPixelWidth() { + return getState().getDefaultPixelWidth(); + } + + public int getDefaultPixelHeight() { + return getState().getDefaultPixelHeight(); + } + + public int getPixelWidth() { + return getState().getPixelWidth(); + } + + public int getPixelHeight() { + return getState().getPixelHeight(); + } + + public int getXOrigin() { + return getState().xOrigin; + } + + public int getYOrigin() { + return getState().yOrigin; + } + + public int getLeftMargin() { + return getState().getLeftMargin(); + } + + public int getLeftMarginPixels() { + return getState().getLeftMarginPixels(); + } + + public int getRightMargin() { + return getState().getRightMargin(); + } + + public int getRightMarginPixels() { + return getState().getRightMarginPixels(); + } + + public int getTopMargin() { + return getState().getTopMargin(); + } + + public int getTopMarginPixels() { + return getState().getTopMarginPixels(); + } + + public int getBottomMargin() { + return getState().getBottomMargin(); + } + + public int getBottomMarginPixels() { + return getState().getBottomMarginPixels(); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPU.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPU.java new file mode 100644 index 0000000..e305972 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPU.java @@ -0,0 +1,9260 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.gpu; + +import org.apache.bcel.classfile.ClassParser; +import org.apache.bcel.classfile.ConstantUtf8; +import org.apache.bcel.classfile.Field; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.generic.ClassGen; +import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.FieldGen; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.addressspace.Pollable; +import org.jpsx.api.components.core.cpu.PollBlockListener; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.api.components.hardware.gpu.Display; +import org.jpsx.api.components.hardware.gpu.DisplayManager; +import org.jpsx.bootstrap.classloader.ClassGenerator; +import org.jpsx.bootstrap.classloader.JPSXClassLoader; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.DMAChannelOwnerBase; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +// todo fix bit flags for 15 bit dma + +// todo convert subrange back to 16 bit. + +public class GPU extends SingletonJPSXComponent implements ClassGenerator, MemoryMapped, PollBlockListener, Pollable { + private static final boolean ignoreGPU = false; + private static final boolean dumpGPUD = false; + private static final boolean debugTransfers = false; + private static final boolean debugTexturePage = false; + private static final boolean rgb24conversion = true; + private static final boolean supportTextureWindow = true; + + private static final int ADDR_GPU_DATA = 0x1f801810; + private static final int ADDR_GPU_CTRLSTATUS = 0x1f801814; + + private static final int GPUD_CMD_NONE = 0; + private static final int GPUD_CMD_FILLING = 1; + private static final int GPUD_CMD_EXTRA = 2; + + private static final int DRAWMODE_SEMI_5P5 = 0x0000; + private static final int DRAWMODE_SEMI_10P10 = 0x0020; + private static final int DRAWMODE_SEMI_10M10 = 0x0040; + private static final int DRAWMODE_SEMI_10P25 = 0x0060; + + private static final int SEMI_NONE = 0; + private static final int SEMI_5P5 = 1; + private static final int SEMI_10P10 = 2; + private static final int SEMI_10M10 = 3; + private static final int SEMI_10P25 = 4; + + private static final int DRAWMODE_TEXTURE_4BIT = 0x0000; + private static final int DRAWMODE_TEXTURE_8BIT = 0x0080; + private static final int DRAWMODE_TEXTURE_16BIT = 0x0100; + // fake.. returned by getTextureMode() if a texture window is in effect + private static final int DRAWMODE_TEXTURE_4BITW = 0x8000; + private static final int DRAWMODE_TEXTURE_8BITW = 0x8080; + private static final int DRAWMODE_TEXTURE_16BITW = 0x8100; + + private static final int DRAWMODE_SET_MASK = 0x0800; + private static final int DRAWMODE_CHECK_MASK = 0x1000; + + private static final int TEXTURE_NONE = 0; + private static final int TEXTURE_4BIT = 1; + private static final int TEXTURE_8BIT = 2; + private static final int TEXTURE_16BIT = 3; + private static final int TEXTURE_4BITW = 4; + private static final int TEXTURE_8BITW = 5; + private static final int TEXTURE_16BITW = 6; + + //private static final int PIXEL_BREG_CLUT = 0x40000000; + private static final int PIXEL_SOLID_CLUT = 0x20000000; + private static final int PIXEL_SOLID_CLUT_CHECKED = 0x10000000; + private static final int PIXEL_RGB24 = 0x08000000; + + private static final int PIXEL_DMA_A = 0x02000000; + private static final int PIXEL_DMA_B = 0x04000000; + private static final int PIXEL_DMA_C = 0x06000000; + + + private static final int GPU_RGBXX_X_MASK = PIXEL_RGB24 | PIXEL_DMA_A | PIXEL_DMA_B | PIXEL_DMA_C; + + private static final int GPU_RGB24_A = PIXEL_RGB24 | PIXEL_DMA_A; + private static final int GPU_RGB24_B = PIXEL_RGB24 | PIXEL_DMA_B; + private static final int GPU_RGB24_C = PIXEL_RGB24 | PIXEL_DMA_C; + + private static final int GPU_RGB15_A = PIXEL_DMA_A; + private static final int GPU_RGB15_B = PIXEL_DMA_B; + private static final int GPU_RGB15_C = PIXEL_DMA_C; + + private static Display display; + + private static DisplayManager manager; + + private static final int[] dma16flags; + + private static AddressSpace addressSpace; + + public GPU() { + super("JPSX Software GPU"); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + display = HardwareComponentConnections.DISPLAY.resolve(); + manager = HardwareComponentConnections.DISPLAY_MANAGER.resolve(); + } + + + public void begin() { + display.initDisplay(); + gpusReset(0); + } + + static { + if (rgb24conversion) { + dma16flags = new int[]{GPU_RGB15_A, GPU_RGB15_B, GPU_RGB15_C, GPU_RGB15_A}; + } else { + dma16flags = new int[]{0, 0, 0, 0}; + } + } + + private static final int getTexturePage() { + return drawMode & 0x1f; + } + + private static final int getMaskModes() { + return drawMode & (DRAWMODE_SET_MASK | DRAWMODE_CHECK_MASK); + } + + /** + * accessor function for texture mode from m_drawMode + */ + private static final int getTextureMode() { + int rc = drawMode & 0x0180; + if (noTextureWindow) return rc; + return rc | 0x8000; + } + + /** + * accessor function for semi-transparency mode from m_drawMode + */ + private static final int getSemiMode() { + return drawMode & 0x0060; + } + + private static int displayMode; + private static int dmaMode; + private static int maskMode; + private static int drawMode; + + private static int cmdBufferUsed; + private static int cmdBufferTarget; + private static int m_gpudState; + + private static int m_drawOffsetX; + private static int m_drawOffsetY; + + private static int m_dmaRGB24Index; + private static int m_dmaRGB24LastPixel; + private static int m_dmaRGB24LastDWord; + private static int m_dmaX; + private static int m_dmaY; + private static int m_dmaOriginX; + private static int m_dmaOriginY; + private static int m_dmaW; + private static int m_dmaH; + private static int m_dmaDWordsRemaining; + private static int m_dmaWordsRemaining; + + private static boolean noTextureWindow = true; + + private static final int[] twuLookup = new int[32]; + private static final int[] twvLookup = new int[32]; + + private static boolean rgb24; + + private static int m_gpudCommand; + + //private static int[] m_extraCmdBuffer; + //private static int m_extraCmdOffset; + //private static int m_extraCmdSize; + + // clip + // for now non-zero +// private static int m_clipLeft=0; +// private static int m_clipRight=320; + // private static int m_clipTop=0; + // private static int m_clipBottom=512; + private static int m_clipLeft; + private static int m_clipRight; + private static int m_clipTop; + private static int m_clipBottom; + + private static final int CMD_BUFFER_SIZE = 16; + + private static final int[] m_cmdBuffer = new int[CMD_BUFFER_SIZE]; + + private static int[] videoRAM; + + private static final byte[][] _4bitTexturePages = new byte[32][]; + private static final byte[][] _8bitTexturePages = new byte[32][]; + + public void init() { + super.init(); + JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_T", this); + JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_L", this); + JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_S", this); + JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_Q", this); + JPSXClassLoader.registerClassGenerator("org.jpsx.runtime.components.hardware.gpu.GPUGenerated$_R", this); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + CoreComponentConnections.POLL_BLOCK_LISTENERS.add(this); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new GPUDMAChannel()); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new OTCDMAChannel()); + } + + private static int m_gpudFunctionArgumentCount[] = { + 1, // 00 + 1, // 01 + 3, // 02 + 1, // 03 + 1, // 04 + 1, // 05 + 1, // 06 + 1, // 07 + 1, // 08 + 1, // 09 + 1, // 0a + 1, // 0b + 1, // 0c + 1, // 0d + 1, // 0e + 1, // 0f + 1, // 10 + 1, // 11 + 1, // 12 + 1, // 13 + 1, // 14 + 1, // 15 + 1, // 16 + 1, // 17 + 1, // 18 + 1, // 19 + 1, // 1a + 1, // 1b + 1, // 1c + 1, // 1d + 1, // 1e + 1, // 1f + 4, // 20 + 4, // 21 + 4, // 22 + 4, // 23 + 7, // 24 + 7, // 25 + 7, // 26 + 7, // 27 + 5, // 28 + 5, // 29 + 5, // 2a + 5, // 2b + 9, // 2c + 9, // 2d + 9, // 2e + 9, // 2f + 6, // 30 + 6, // 31 + 6, // 32 + 6, // 33 + 9, // 34 + 9, // 35 + 9, // 36 + 9, // 37 + 8, // 38 + 8, // 39 + 8, // 3a + 8, // 3b + 12, // 3c + 12, // 3d + 12, // 3e + 12, // 3f + 3, // 40 + 1, // 41 + 3, // 42 + 1, // 43 + 1, // 44 + 1, // 45 + 1, // 46 + 1, // 47 + 3, // 48 + 1, // 49 + 3, // 4a + 1, // 4b + 1, // 4c + 1, // 4d + 1, // 4e + 1, // 4f + 4, // 50 + 1, + 4, + 1, + 1, // 54 + 1, // 55 + 1, // 56 + 1, // 57 + 4, // 58 + 1, + 4, + 1, + 1, // 5c + 1, // 5d + 1, // 5e + 1, // 5f + 3, // 60 + 3, + 3, + 3, + 4, // 64 + 4, + 4, + 4, + 2, + 2, + 2, + 2, + 1, // 6c + 1, // 6d + 1, // 6e + 1, // 6f + 2, // 70 + 2, + 2, + 2, + 3, // 74 + 3, + 3, + 3, + 2, // 78 + 2, + 2, + 2, + 3, // 7c + 3, + 3, + 3, + 4, // 80 + 1, // 81 + 1, // 82 + 1, // 83 + 1, // 84 + 1, // 85 + 1, // 86 + 1, // 87 + 1, // 88 + 1, // 89 + 1, // 8a + 1, // 8b + 1, // 8c + 1, // 8d + 1, // 8e + 1, // 8f + 1, // 90 + 1, // 91 + 1, // 92 + 1, // 93 + 1, // 94 + 1, // 95 + 1, // 96 + 1, // 97 + 1, // 98 + 1, // 99 + 1, // 9a + 1, // 9b + 1, // 9c + 1, // 9d + 1, // 9e + 1, // 9f + 3, // a0 + 1, // a1 + 1, // a2 + 1, // a3 + 1, // a4 + 1, // a5 + 1, // a6 + 1, // a7 + 1, // a8 + 1, // a9 + 1, // aa + 1, // ab + 1, // ac + 1, // ad + 1, // ae + 1, // af + 1, // b0 + 1, // b1 + 1, // b2 + 1, // b3 + 1, // b4 + 1, // b5 + 1, // b6 + 1, // b7 + 1, // b8 + 1, // b9 + 1, // ba + 1, // bb + 1, // bc + 1, // bd + 1, // be + 1, // bf + 3, // c0 + 1, // c1 + 1, // c2 + 1, // c3 + 1, // c4 + 1, // c5 + 1, // c6 + 1, // c7 + 1, // c8 + 1, // c9 + 1, // ca + 1, // cb + 1, // cc + 1, // cd + 1, // ce + 1, // cf + 1, // d0 + 1, // d1 + 1, // d2 + 1, // d3 + 1, // d4 + 1, // d5 + 1, // d6 + 1, // d7 + 1, // d8 + 1, // d9 + 1, // da + 1, // db + 1, // dc + 1, // dd + 1, // de + 1, // df + 1, // e0 + 1, // e1 + 1, // e2 + 1, // e3 + 1, // e4 + 1, // e5 + 1, // e6 + 1, // e7 + 1, // e8 + 1, // e9 + 1, // ea + 1, // eb + 1, // ec + 1, // ed + 1, // ee + 1, // ef + 1, // f0 + 1, // f1 + 1, // f2 + 1, // f3 + 1, // f4 + 1, // f5 + 1, // f6 + 1, // f7 + 1, // f8 + 1, // f9 + 1, // fa + 1, // fb + 1, // fc + 1, // fd + 1, // fe + 1, // ff + }; + + private static boolean m_displayEnabled; + + + public void registerAddresses(AddressSpaceRegistrar registrar) { + registrar.registerWrite32Callback(ADDR_GPU_CTRLSTATUS, GPU.class, "gpuCtrlWrite32"); + registrar.registerWrite32Callback(ADDR_GPU_DATA, GPU.class, "gpuDataWrite32"); + registrar.registerRead32Callback(ADDR_GPU_CTRLSTATUS, GPU.class, "gpuStatusRead32"); + registrar.registerRead32Callback(ADDR_GPU_DATA, GPU.class, "gpuDataRead32"); + + registrar.registerPoll32Callback(ADDR_GPU_CTRLSTATUS, this); + } + + static long baseTime = System.currentTimeMillis(); + static int counter = 0; + + private static void debuggo() { + System.out.println(counter + " " + (System.currentTimeMillis() - baseTime)); + counter++; + } + + public static void gpuCtrlWrite32(int address, int val) { + if (ignoreGPU) { + debuggo(); + return; + } +// ASSERT( SANITY_CHECK, address==ADDR_GPU_CTRLSTATUS, ""); + switch (val >> 24) { + case 0: + gpusReset(val); + break; + case 1: + gpusCmdReset(val); + break; + case 2: + gpusIRQReset(val); + break; + case 3: + gpusSetDispEnable(val); + break; + case 4: + gpusSetDataTransferMode(val); + break; + case 5: + gpusSetDisplayOrigin(val); + break; + case 6: + gpusSetMonitorLeftRight(val); + break; + case 7: + gpusSetMonitorTopBottom(val); + break; + case 8: + gpusSetDisplayMode(val); + break; + case 0x10: + gpusRequestInfo(val); + break; + } + } + + public static void gpuDataWrite32(int address, int val) { + if (ignoreGPU) { + debuggo(); + return; + } + videoRAM = display.acquireDisplayBuffer(); + try { + switch (m_gpudState) { + case GPUD_CMD_NONE: + m_gpudCommand = (val >> 24) & 0xff; + m_cmdBuffer[0] = val; + cmdBufferUsed = 1; + cmdBufferTarget = m_gpudFunctionArgumentCount[m_gpudCommand]; + m_gpudState = GPUD_CMD_FILLING; + break; + case GPUD_CMD_FILLING: + m_cmdBuffer[cmdBufferUsed++] = val; + break; + case GPUD_CMD_EXTRA: + m_cmdBuffer[0] = val; + int dwordsUsed = GPUDRouter.invoke(m_cmdBuffer, 0, 1); + assert (dwordsUsed == 1); + return; + } + assert (m_gpudState == GPUD_CMD_FILLING); + if (cmdBufferUsed == cmdBufferTarget) { + m_gpudState = GPUD_CMD_NONE; + GPUDRouter.invoke(m_cmdBuffer, 0, cmdBufferUsed); + } + } finally { + display.releaseDisplayBuffer(); + videoRAM = null; + } + } + + private static class TemplateQuadRenderer { + public static void render(PolygonRenderInfo info, Vertex v0, Vertex v1, Vertex v2, Vertex v3) { + if ((v3.x == v2.x && v0.x == v1.x && v0.y == v2.y && v1.y == v3.y) || + (v0.x == v2.x && v1.x == v3.x && v0.y == v1.y && v2.y == v3.y)) { + // this returns false if it detects non-linear gradients across the rectangle; + if (TemplateRectangleRenderer.render(info, v0, v1, v2, v3)) + return; + } + TemplateTriangleRenderer.render(info, v0, v1, v2); + TemplateTriangleRenderer.render(info, v2, v1, v3); + } + } + + private static byte[] get4BitTexturePage() { + int page = getTexturePage() & 0x1f; + byte[] rc = _4bitTexturePages[page]; + if (rc == null) { + assert !rgb24; + if (debugTexturePage) System.out.println("Generating 4 bit texture page"); + rc = new byte[0x10000]; + int offset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; + int destOffset = 0; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 64; x++) { + int val = unmakePixel(videoRAM[offset++]); + + rc[destOffset++] = (byte) (val & 0xf); + rc[destOffset++] = (byte) ((val & 0xf0) >> 4); + rc[destOffset++] = (byte) ((val & 0xf00) >> 8); + rc[destOffset++] = (byte) ((val & 0xf000) >> 12); + } + offset += 1024 - 64; + } + _4bitTexturePages[page] = rc; + } + return rc; + } + + private static byte[] get8BitTexturePage() { + int page = getTexturePage() & 0x1f; + byte[] rc = _8bitTexturePages[page]; + if (rc == null) { + assert !rgb24; + if (debugTexturePage) System.out.println("Generating 8 bit texture page"); + rc = new byte[0x10000]; + int offset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; + int destOffset = 0; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 128; x++) { + int val = unmakePixel(videoRAM[offset++]); + + rc[destOffset++] = (byte) (val & 0xff); + rc[destOffset++] = (byte) ((val & 0xff00) >> 8); + } + offset += 1024 - 128; + } + _8bitTexturePages[page] = rc; + } + return rc; + } + + public static class Vertex { + public int x, y, u, v, r, g, b; + + public final void init(Vertex vert) { + x = vert.x; + y = vert.y; + u = vert.u; + v = vert.v; + r = vert.r; + g = vert.g; + b = vert.b; + } + + public String toString() { + return "(" + x + "," + y + ")"; + } + } + + public static class Edge { + Vertex current = new Vertex(); + int dx, du, dv, dr, dg, db; + int endy; + } + + public static class LineRenderInfo { + int r0, g0, b0; + int r1, g1, b1; + int color; + } + + public static class PolygonRenderInfo { + int r, g, b; + int u, v; + int[] clut; + int clutOffset; + } + + + + private static class TemplateTriangleRenderer { + private static Vertex[] verts = new Vertex[3]; + private static Edge[] edges = new Edge[]{new Edge(), new Edge(), new Edge()}; + + // when we load the particular renderer class we make these final and + // give them a value... if we make them final at compile time, + // then the java compiler does optimizations on them... + private static int _renderSemiType; + private static int _renderTextureType; + private static boolean _renderBReg; + private static boolean _renderGouraud; + private static boolean _renderCheckMask; + private static boolean _renderSetMask; + private static boolean _renderSolid; + + public static void render(PolygonRenderInfo info, Vertex v0, Vertex v1, Vertex v2) { + // following is for spans + int color = 0; + int spanStart; // in m_ram + int count; // length + int u = 0, v = 0; + int du = 0, dv = 0; + int r = 0, g = 0, b = 0; + int dr = 0, dg = 0, db = 0; + int[] clut = null; + int clutOffset = 0; + byte[] byteTexturePage = null; + int tpOffset = 0; + + int src = 0; + + Edge e1, e2, e3; + + // TODO - loop? second for not writing to display? + // note most setup only done first time + + // want to work relative to draw origin + int clipLeft = m_clipLeft - m_drawOffsetX; + int clipRight = m_clipRight - m_drawOffsetX; + int clipTop = m_clipTop - m_drawOffsetY; + int clipBottom = m_clipBottom - m_drawOffsetY; + + boolean clippedX = false; + if (v0.x < clipLeft && v1.x < clipLeft && v2.x < clipLeft) + return; + if (v0.x >= clipRight && v1.x >= clipRight && v2.x >= clipRight) + return; + if (v0.y < clipTop && v1.y < clipTop && v2.y < clipTop) + return; + if (v0.y >= clipBottom && v1.y >= clipBottom && v2.y >= clipBottom) + return; + if (v0.x < clipLeft || v0.x >= clipRight || + v1.x < clipLeft || v1.x >= clipRight || + v2.x < clipLeft || v2.x >= clipRight) + clippedX = true; + + // y sort into vertex array + if (v0.y > v1.y) { + verts[0] = v1; + verts[1] = v0; + } else { + verts[0] = v0; + verts[1] = v1; + } + if (v2.y < verts[0].y) { + verts[2] = verts[1]; + verts[1] = verts[0]; + verts[0] = v2; + //return; + } else if (v2.y < verts[1].y) { + verts[2] = verts[1]; + verts[1] = v2; + } else { + verts[2] = v2; + } + + //ASSERT( SANITY_CHECK, verts[1].y>verts[0].y, ""); + //ASSERT( SANITY_CHECK, verts[2].y>verts[1].y, ""); + + // check for zero total height + int dy1 = verts[2].y - verts[0].y; + if (dy1 == 0) return; + + if (_renderTextureType != TEXTURE_NONE) { + // for 4 bit + if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { + byteTexturePage = get4BitTexturePage(); + } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { + byteTexturePage = get8BitTexturePage(); + } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { + int page = GPU.getTexturePage(); + tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; + } + clut = info.clut; + clutOffset = info.clutOffset; + } else { + if (!_renderGouraud) { + // need color + color = info.b | (info.g << 8) | (info.r << 16); + } + } + + e1 = edges[0]; + + // e1 is long edge from top to bottom + e1.current.init(verts[0]); + e1.dx = ((verts[2].x - verts[0].x) << 16) / dy1; + if (_renderTextureType != TEXTURE_NONE) { + e1.du = ((verts[2].u - verts[0].u) << 16) / dy1; + e1.dv = ((verts[2].v - verts[0].v) << 16) / dy1; + } + if (_renderGouraud) { + e1.dr = ((verts[2].r - verts[0].r) << 16) / dy1; + e1.dg = ((verts[2].g - verts[0].g) << 16) / dy1; + e1.db = ((verts[2].b - verts[0].b) << 16) / dy1; + } + + // e2 is short edge at top, unless flat topped + int dy2 = verts[1].y - verts[0].y; + if (dy2 != 0) { + e2 = edges[1]; + e2.current.init(verts[0]); + e2.dx = ((verts[1].x - verts[0].x) << 16) / dy2; + if (_renderTextureType != TEXTURE_NONE) { + e2.du = ((verts[1].u - verts[0].u) << 16) / dy2; + e2.dv = ((verts[1].v - verts[0].v) << 16) / dy2; + } + if (_renderGouraud) { + e2.dr = ((verts[1].r - verts[0].r) << 16) / dy2; + e2.dg = ((verts[1].g - verts[0].g) << 16) / dy2; + e2.db = ((verts[1].b - verts[0].b) << 16) / dy2; + } + e2.endy = verts[1].y; + } else { + e2 = null; + } + + // e2 is short edge at bottom, unless flat bottomed + int dy3 = verts[2].y - verts[1].y; + if (dy3 != 0) { + e3 = edges[2]; + e3.current.init(verts[1]); + e3.dx = ((verts[2].x - verts[1].x) << 16) / dy3; + e3.endy = verts[2].y; + if (_renderTextureType != TEXTURE_NONE) { + e3.du = ((verts[2].u - verts[1].u) << 16) / dy3; + e3.dv = ((verts[2].v - verts[1].v) << 16) / dy3; + } + if (_renderGouraud) { + e3.dr = ((verts[2].r - verts[1].r) << 16) / dy3; + e3.dg = ((verts[2].g - verts[1].g) << 16) / dy3; + e3.db = ((verts[2].b - verts[1].b) << 16) / dy3; + } + if (e2 == null) { + // in the case of flat-topped, we replace + // e2 with e3 + e2 = e3; + e3 = null; + } + } else { + e3 = null; + } + + int times = 2; + e1.current.x <<= 16; + e2.current.x <<= 16; + + int crossz = (verts[2].x - verts[0].x) * dy2 - (verts[1].x - verts[0].x) * dy1; + if (crossz == 0) + return; + + if (_renderTextureType != TEXTURE_NONE) { + e1.current.u <<= 16; + e1.current.v <<= 16; + e2.current.u <<= 16; + e2.current.v <<= 16; + long crosszu = (verts[2].u - verts[0].u) * (long) dy2 - (verts[1].u - verts[0].u) * dy1; + du = (int) ((crosszu << 16) / crossz); + long crosszv = (verts[2].v - verts[0].v) * (long) dy2 - (verts[1].v - verts[0].v) * dy1; + dv = (int) ((crosszv << 16) / crossz); + } + if (_renderGouraud) { + e1.current.r <<= 16; + e1.current.g <<= 16; + e1.current.b <<= 16; + e2.current.r <<= 16; + e2.current.g <<= 16; + e2.current.b <<= 16; + long crosszr = (verts[2].r - verts[0].r) * (long) dy2 - (verts[1].r - verts[0].r) * dy1; + dr = (int) ((crosszr << 16) / crossz); + long crosszg = (verts[2].g - verts[0].g) * (long) dy2 - (verts[1].g - verts[0].g) * dy1; + dg = (int) ((crosszg << 16) / crossz); + long crosszb = (verts[2].b - verts[0].b) * (long) dy2 - (verts[1].b - verts[0].b) * dy1; + db = (int) ((crosszb << 16) / crossz); + } + if (e3 != null) { + e3.current.x <<= 16; + if (_renderTextureType != TEXTURE_NONE) { + e3.current.u <<= 16; + e3.current.v <<= 16; + } + if (_renderGouraud) { + e3.current.r <<= 16; + e3.current.g <<= 16; + e3.current.b <<= 16; + } + } + + + do { + Edge el, er; + if (e1.current.x < e2.current.x) { + el = e1; + er = e2; + } else if (e1.current.x > e2.current.x) { + er = e1; + el = e2; + } else if ((e1.current.x + e1.dx) < (e2.current.x + e2.dx)) { + el = e1; + er = e2; + } else { + er = e1; + el = e2; + } + + if (e2.endy > clipBottom) { + e2.endy = clipBottom; + } + + if (e2.current.y < clipTop) { + int skipY; + if (e2.endy < clipTop) + skipY = e2.endy - e2.current.y; + else + skipY = clipTop - e2.current.y; + e1.current.x += e1.dx * skipY; + e2.current.x += e2.dx * skipY; + e2.current.y += skipY; + if (_renderTextureType != TEXTURE_NONE) { + e1.current.u += e1.du * skipY; + e1.current.v += e1.dv * skipY; + e2.current.u += e2.du * skipY; + e2.current.v += e2.dv * skipY; + } + if (_renderGouraud) { + e1.current.r += e1.dr * skipY; + e1.current.g += e1.dg * skipY; + e1.current.b += e1.db * skipY; + e2.current.r += e2.dr * skipY; + e2.current.g += e2.dg * skipY; + e2.current.b += e2.db * skipY; + } + } + int base = m_drawOffsetX + (e2.current.y + m_drawOffsetY) * 1024; + if (!clippedX) { + while (e2.current.y < e2.endy) { + int left = el.current.x >> 16; + int right = er.current.x >> 16; + + count = right - left; + if (count > 0) { + spanStart = base + left; + if (_renderTextureType != TEXTURE_NONE) { + u = el.current.u; + v = el.current.v; + } + if (_renderGouraud) { + r = el.current.r; + g = el.current.g; + b = el.current.b; + } + + // --- configure span + + //if (_renderTextureType == TEXTURE_NONE && !_renderGouraud) { + // color = color; + //} + + int target = spanStart + count; + int i = spanStart; + + for (; i < target; i++) { + // get source pixel + if (_renderTextureType == TEXTURE_NONE) { + if (!_renderGouraud) { + src = color; + } else { + src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); + } + } else if (_renderTextureType == TEXTURE_4BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BIT) { + int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); + src = videoRAM[tpOffset + offset]; + } else if (_renderTextureType == TEXTURE_4BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BITW) { + int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); + src = videoRAM[tpOffset + offset]; + } + + if (_renderBReg) { + int bb = (src & 0xff); + int gg = ((src >> 8) & 0xff); + int rr = ((src >> 16) & 0xff); + int mask = ((src & 0xffffff) == 0) ? 0 : 1; + rr = (rr * (r >> 16)) >> 7; + if (rr > 255) rr = 255; + gg = (gg * (g >> 16)) >> 7; + if (gg > 255) gg = 255; + bb = (bb * (b >> 16)) >> 7; + if (bb > 255) bb = 255; + src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; + //src = (src&0x01000000)|((b>>16)<<16)|((g>>16)<<8)|(r>>16)|mask; + } + + if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { + if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { + } else { + if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { + // semi transparency + int dest = videoRAM[i]; + int destB = dest & 0xff; + int destG = (dest >> 8) & 0xff; + int destR = (dest >> 16) & 0xff; + int srcB = src & 0xff; + int srcG = (src >> 8) & 0xff; + int srcR = (src >> 16) & 0xff; + int tmpR, tmpG, tmpB; + + if (_renderSemiType == SEMI_5P5) { + tmpR = (srcR + destR) >> 1; + tmpG = (srcG + destG) >> 1; + tmpB = (srcB + destB) >> 1; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P10) { + tmpR = srcR + destR; + tmpG = srcG + destG; + tmpB = srcB + destB; + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10M10) { + tmpR = destR - srcR; + tmpG = destG - srcG; + tmpB = destB - srcB; + if (tmpR < 0) tmpR = 0; + if (tmpG < 0) tmpG = 0; + if (tmpB < 0) tmpB = 0; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P25) { + tmpR = destR + (srcR >> 2); + tmpG = destG + (srcG >> 2); + tmpB = destB + (srcB >> 2); + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } + } + + // mask set + if (_renderSetMask) { + src |= 0x01000000; + } + videoRAM[i] = src; + } + } + if (_renderTextureType != TEXTURE_NONE) { + u += du; + v += dv; + } + if (_renderGouraud) { + r += dr; + g += dg; + b += db; + } + } + + // --- end span + } + e1.current.x += e1.dx; + e2.current.x += e2.dx; + if (_renderTextureType != TEXTURE_NONE) { + e1.current.u += e1.du; + e1.current.v += e1.dv; + e2.current.u += e2.du; + e2.current.v += e2.dv; + } + if (_renderGouraud) { + e1.current.r += e1.dr; + e1.current.g += e1.dg; + e1.current.b += e1.db; + e2.current.r += e2.dr; + e2.current.g += e2.dg; + e2.current.b += e2.db; + } + e2.current.y++; + base += 1024; + } + } else { + while (e2.current.y < e2.endy) { + int left = el.current.x >> 16; + int right = er.current.x >> 16; + + if (right > clipRight) + right = clipRight; + if (_renderTextureType != TEXTURE_NONE) { + u = el.current.u; + v = el.current.v; + } + if (_renderGouraud) { + r = el.current.r; + g = el.current.g; + b = el.current.b; + } + if (left < clipLeft) { + int skipX = clipLeft - left; + left = clipLeft; + if (_renderTextureType != TEXTURE_NONE) { + u += du * skipX; + v += dv * skipX; + } + if (_renderGouraud) { + r += dr * skipX; + g += dg * skipX; + b += db * skipX; + } + } + count = right - left; + if (count > 0) { + spanStart = base + left; + + // --- configure span + + //if (_renderTextureType == TEXTURE_NONE && !_renderGouraud) { + // color = color; + //} + + int target = spanStart + count; + int i = spanStart; + + for (; i < target; i++) { + // get source pixel + if (_renderTextureType == TEXTURE_NONE) { + if (!_renderGouraud) { + src = color; + } else { + src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); + } + } else if (_renderTextureType == TEXTURE_4BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BIT) { + int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); + src = videoRAM[tpOffset + offset]; + } else if (_renderTextureType == TEXTURE_4BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BITW) { + int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); + src = videoRAM[tpOffset + offset]; + } + + if (_renderBReg) { + int bb = (src & 0xff); + int gg = ((src >> 8) & 0xff); + int rr = ((src >> 16) & 0xff); + int mask = ((src & 0xffffff) == 0) ? 0 : 1; + rr = (rr * (r >> 16)) >> 7; + if (rr > 255) rr = 255; + gg = (gg * (g >> 16)) >> 7; + if (gg > 255) gg = 255; + bb = (bb * (b >> 16)) >> 7; + if (bb > 255) bb = 255; + src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; + } + + if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { + if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { + } else { + if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { + // semi transparency + int dest = videoRAM[i]; + int destB = dest & 0xff; + int destG = (dest >> 8) & 0xff; + int destR = (dest >> 16) & 0xff; + int srcB = src & 0xff; + int srcG = (src >> 8) & 0xff; + int srcR = (src >> 16) & 0xff; + int tmpR, tmpG, tmpB; + + if (_renderSemiType == SEMI_5P5) { + tmpR = (srcR + destR) >> 1; + tmpG = (srcG + destG) >> 1; + tmpB = (srcB + destB) >> 1; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P10) { + tmpR = srcR + destR; + tmpG = srcG + destG; + tmpB = srcB + destB; + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10M10) { + tmpR = destR - srcR; + tmpG = destG - srcG; + tmpB = destB - srcB; + if (tmpR < 0) tmpR = 0; + if (tmpG < 0) tmpG = 0; + if (tmpB < 0) tmpB = 0; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P25) { + tmpR = destR + (srcR >> 2); + tmpG = destG + (srcG >> 2); + tmpB = destB + (srcB >> 2); + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } + } + + // mask set + if (_renderSetMask) { + src |= 0x01000000; + } + videoRAM[i] = src; + } + } + if (_renderTextureType != TEXTURE_NONE) { + u += du; + v += dv; + } + if (_renderGouraud) { + r += dr; + g += dg; + b += db; + } + } + + // --- end span + + } + e1.current.x += e1.dx; + e2.current.x += e2.dx; + if (_renderTextureType != TEXTURE_NONE) { + e1.current.u += e1.du; + e1.current.v += e1.dv; + e2.current.u += e2.du; + e2.current.v += e2.dv; + } + if (_renderGouraud) { + e1.current.r += e1.dr; + e1.current.g += e1.dg; + e1.current.b += e1.db; + e2.current.r += e2.dr; + e2.current.g += e2.dg; + e2.current.b += e2.db; + } + e2.current.y++; + base += 1024; + } + ; + } + + e2 = e3; + times--; + } while (times != 0 && e2 != null); + } + } + + private static class TemplateRectangleRenderer { + private static Vertex[] verts = new Vertex[4]; + + // when we load the particular renderer class we make these final and + // give them a value... if we make them final at compile time, + // then the java compiler does optimizations on them... + private static int _renderSemiType; + private static int _renderTextureType; + private static boolean _renderBReg; + private static boolean _renderGouraud; + private static boolean _renderCheckMask; + private static boolean _renderSetMask; + private static boolean _renderSolid; + + public static boolean render(PolygonRenderInfo info, Vertex ve0, Vertex ve1, Vertex ve2, Vertex ve3) { + // following is for spans + int color = 0; + int spanStart; // in m_ram + int count; // length + + int u = 0, v = 0; + int u0 = 0, v0 = 0; + int du = 0, dv = 0; + int du0 = 0, dv0 = 0; + + int r = 0, g = 0, b = 0; + int r0 = 0, g0 = 0, b0 = 0; + int dr = 0, dg = 0, db = 0; + int dr0 = 0, dg0 = 0, db0 = 0; + + int[] clut = null; + int clutOffset = 0; + byte[] byteTexturePage = null; + int tpOffset = 0; + + int src = 0; + + verts[0] = ve0; + verts[1] = ve1; + verts[2] = ve2; + verts[3] = ve3; + + Vertex tmp; + + // sort to 0 - 1 + // | | + // 2 - 3 + if (verts[0].x == verts[1].x) { + tmp = verts[1]; + verts[1] = verts[2]; + verts[2] = tmp; + } + if (verts[0].x > verts[1].x) { + tmp = verts[1]; + verts[1] = verts[0]; + verts[0] = tmp; + } + if (verts[2].x > verts[3].x) { + tmp = verts[2]; + verts[2] = verts[3]; + verts[3] = tmp; + } + if (verts[0].y > verts[2].y) { + tmp = verts[0]; + verts[0] = verts[2]; + verts[2] = tmp; + } + if (verts[1].y > verts[3].y) { + tmp = verts[1]; + verts[1] = verts[3]; + verts[3] = tmp; + } + + int x = verts[0].x; + int y = verts[0].y; + int ww = verts[1].x - x; + int hh = verts[2].y - y; + + if (ww <= 0 || hh <= 0) + return true; + + int w = ww; + int h = hh; + + // TODO - loop? second for not writing to display? + // note most setup only done first time + + // want to work relative to draw origin + int clipLeft = m_clipLeft - m_drawOffsetX; + int clipRight = m_clipRight - m_drawOffsetX; + int clipTop = m_clipTop - m_drawOffsetY; + int clipBottom = m_clipBottom - m_drawOffsetY; + + if ((x + w) >= clipRight) + w = clipRight - x; + if ((y + h) >= clipBottom) + h = clipBottom - y; + + int skipX = 0; + int skipY = 0; + + if (x < clipLeft) { + skipX = clipLeft - x; + x = clipLeft; + w -= skipX; + } + if (y < clipTop) { + skipY = clipTop - y; + y = clipTop; + h -= skipY; + } + + if (w <= 0 || h <= 0) + return true; + + if (_renderTextureType != TEXTURE_NONE) { + // check for non-linear + if ((verts[1].u - verts[0].u) != (verts[3].u - verts[2].u) || + (verts[1].v - verts[0].v) != (verts[3].v - verts[2].v) || + (verts[2].u - verts[0].u) != (verts[3].u - verts[1].u) || + (verts[2].v - verts[0].v) != (verts[3].v - verts[1].v)) { + //System.out.println("non-linear quad texture!"); + return false; + } + u0 = verts[0].u << 16; + v0 = verts[0].v << 16; + du = ((verts[1].u << 16) - u0) / ww; + dv = ((verts[1].v << 16) - v0) / ww; + du0 = ((verts[2].u << 16) - u0) / hh; + dv0 = ((verts[2].v << 16) - v0) / hh; + + if (skipX != 0) { + u0 += skipX * du; + v0 += skipX + dv; + } + if (skipY != 0) { + u0 += skipY * du0; + v0 += skipY * dv0; + } + + // for 4 bit + if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { + byteTexturePage = get4BitTexturePage(); + } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { + byteTexturePage = get8BitTexturePage(); + } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { + int page = GPU.getTexturePage(); + tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; + } + clut = info.clut; + clutOffset = info.clutOffset; + if (_renderBReg) { + r = info.r; + g = info.g; + b = info.b; + } + } else { + color = info.b | (info.g << 8) | (info.r << 16); + } + + if (_renderGouraud) { + // check for non-linear + if ((verts[1].r - verts[0].r) != (verts[3].r - verts[2].r) || + (verts[1].g - verts[0].g) != (verts[3].g - verts[2].g) || + (verts[1].b - verts[0].b) != (verts[3].b - verts[2].b) || + (verts[2].r - verts[0].r) != (verts[3].r - verts[1].r) || + (verts[2].g - verts[0].g) != (verts[3].g - verts[1].g) || + (verts[2].b - verts[0].b) != (verts[3].b - verts[1].b)) { + //System.out.println("non-linear quad gouraud!"); + return false; + } + r0 = verts[0].r << 16; + g0 = verts[0].g << 16; + b0 = verts[0].b << 16; + + dr = ((verts[1].r << 16) - r0) / ww; + dg = ((verts[1].g << 16) - g0) / ww; + db = ((verts[1].b << 16) - b0) / ww; + dr0 = ((verts[2].r << 16) - r0) / hh; + dg0 = ((verts[2].g << 16) - g0) / hh; + db0 = ((verts[2].b << 16) - b0) / hh; + + if (skipX != 0) { + r0 += skipX * dr; + g0 += skipX + dg; + b0 += skipX + db; + } + if (skipY != 0) { + r0 += skipY * dr0; + g0 += skipY * dg0; + b0 += skipY * db0; + } + } + + int base = m_drawOffsetX + x + (y + m_drawOffsetY) * 1024; + outertmp: + for (; h > 0; h--) { + if (_renderTextureType != TEXTURE_NONE) { + u = u0; + v = v0; + } + if (_renderGouraud) { + r = r0; + g = g0; + b = b0; + } + for (int i = base; i < (base + w); i++) { + // get source pixel + if (_renderTextureType == TEXTURE_NONE) { + if (!_renderGouraud) { + src = color; + } else { + src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); + } + } else if (_renderTextureType == TEXTURE_4BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BIT) { + int offset = ((u >> 16) & 0xff) + ((v >> 8) & 0xff00); + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BIT) { + int offset = ((u >> 16) & 0xff) + (((v >> 16) & 0xff) << 10); + src = videoRAM[tpOffset + offset]; + } else if (_renderTextureType == TEXTURE_4BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BITW) { + int offset = ((u >> 16) & 0x07) | ((v >> 8) & 0x0700) | twuLookup[(u >> 19) & 0x1f] | twvLookup[(v >> 19) & 0x1f]; + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BITW) { + int offset = ((u >> 16) & 0x07) | twuLookup[(u >> 19) & 0x1f] | ((((v >> 8) & 0x0700) | twvLookup[(v >> 19) & 0x1f]) << 2); + src = videoRAM[tpOffset + offset]; + } + + if (_renderBReg) { + int bb = (src & 0xff); + int gg = ((src >> 8) & 0xff); + int rr = ((src >> 16) & 0xff); + int mask = ((src & 0xffffff) == 0) ? 0 : 1; + rr = (rr * (r >> 16)) >> 7; + if (rr > 255) rr = 255; + gg = (gg * (g >> 16)) >> 7; + if (gg > 255) gg = 255; + bb = (bb * (b >> 16)) >> 7; + if (bb > 255) bb = 255; + src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; + } + + if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { + if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { + } else { + if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { + // semi transparency + int dest = videoRAM[i]; + int destB = dest & 0xff; + int destG = (dest >> 8) & 0xff; + int destR = (dest >> 16) & 0xff; + int srcB = src & 0xff; + int srcG = (src >> 8) & 0xff; + int srcR = (src >> 16) & 0xff; + int tmpR, tmpG, tmpB; + + if (_renderSemiType == SEMI_5P5) { + tmpR = (srcR + destR) >> 1; + tmpG = (srcG + destG) >> 1; + tmpB = (srcB + destB) >> 1; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P10) { + tmpR = srcR + destR; + tmpG = srcG + destG; + tmpB = srcB + destB; + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10M10) { + tmpR = destR - srcR; + tmpG = destG - srcG; + tmpB = destB - srcB; + if (tmpR < 0) tmpR = 0; + if (tmpG < 0) tmpG = 0; + if (tmpB < 0) tmpB = 0; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P25) { + tmpR = destR + (srcR >> 2); + tmpG = destG + (srcG >> 2); + tmpB = destB + (srcB >> 2); + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } + } + + // mask set + if (_renderSetMask) { + src |= 0x01000000; + } + videoRAM[i] = src; + } + } + if (_renderTextureType != TEXTURE_NONE) { + u += du; + v += dv; + } + if (_renderGouraud) { + r += dr; + g += dg; + b += db; + } + } + base += 1024; + if (_renderTextureType != TEXTURE_NONE) { + u0 += du0; + v0 += dv0; + } + if (_renderGouraud) { + r0 += dr0; + g0 += dg0; + b0 += db0; + } + } + return true; + } + } + + private static class TemplateSpriteRenderer { + // when we load the particular renderer class we make these final and + // give them a value... if we make them final at compile time, + // then the java compiler does optimizations on them... + private static int _renderSemiType; + private static int _renderTextureType; + private static boolean _renderBReg; + private static boolean _renderGouraud; + private static boolean _renderCheckMask; + private static boolean _renderSetMask; + private static boolean _renderSolid; + + + public static void render(PolygonRenderInfo info, int x, int y, int w, int h) { +// System.out.println("Sprite renderer "+x+","+y+" "+w+","+h); + // following is for spans + int color = 0; + int u0 = 0, v = 0; + int r = 0, g = 0, b = 0; + int[] clut = null; + int clutOffset = 0; + byte[] byteTexturePage = null; + int tpOffset = 0; + + int src = 0; + + // TODO - loop? second for not writing to display? + // note most setup only done first time + + // want to work relative to draw origin + int clipLeft = m_clipLeft - m_drawOffsetX; + int clipRight = m_clipRight - m_drawOffsetX; + int clipTop = m_clipTop - m_drawOffsetY; + int clipBottom = m_clipBottom - m_drawOffsetY; + + if ((x + w) >= clipRight) + w = clipRight - x; + if ((y + h) >= clipBottom) + h = clipBottom - y; + + int skipX = 0; + int skipY = 0; + + if (x < clipLeft) { + skipX = clipLeft - x; + x = clipLeft; + w -= skipX; + } + if (y < clipTop) { + skipY = clipTop - y; + y = clipTop; + h -= skipY; + } + + if (w <= 0 || h <= 0) + return; + + if (_renderTextureType != TEXTURE_NONE) { + // shifted to avoid shifts in loop + u0 = info.u + skipX; + v = (info.v + skipY) << 8; + // for 4 bit + if (_renderTextureType == TEXTURE_4BIT || _renderTextureType == TEXTURE_4BITW) { + byteTexturePage = get4BitTexturePage(); + } else if (_renderTextureType == TEXTURE_8BIT || _renderTextureType == TEXTURE_8BITW) { + byteTexturePage = get8BitTexturePage(); + } else if (_renderTextureType == TEXTURE_16BIT || _renderTextureType == TEXTURE_16BITW) { + int page = GPU.getTexturePage(); + tpOffset = (page & 15) * 64 + (page & 0x10) * 1024 * 16; + } + clut = info.clut; + clutOffset = info.clutOffset; + if (_renderBReg) { + r = info.r; + g = info.g; + b = info.b; + } + } else { + color = info.b | (info.g << 8) | (info.r << 16); + } + + int base = m_drawOffsetX + x + (y + m_drawOffsetY) * 1024; + for (; h > 0; h--) { + int u = u0; + for (int i = base; i < (base + w); i++) { + //System.out.println(MiscUtil.toHex(u,4)+" "+MiscUtil.toHex(v,4)); + // get source pixel + if (_renderTextureType == TEXTURE_NONE) { + src = color; + } else if (_renderTextureType == TEXTURE_4BIT) { + int offset = (u & 0xff) | (v & 0xff00); + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BIT) { + int offset = (u & 0xff) | (v & 0xff00); + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BIT) { + int offset = (u & 0xff) | ((v & 0xff00) << 2); + src = videoRAM[tpOffset + offset]; + } else if (_renderTextureType == TEXTURE_4BITW) { + int offset = (u & 0x07) | (v & 0x0700) | twuLookup[(u >> 3) & 0x1f] | twvLookup[(v >> 11) & 0x1f]; + src = clut[clutOffset + byteTexturePage[offset]]; + } else if (_renderTextureType == TEXTURE_8BITW) { + int offset = (u & 0x07) | (v & 0x0700) | twuLookup[(u >> 3) & 0x1f] | twvLookup[(v >> 11) & 0x1f]; + src = clut[clutOffset + (((int) byteTexturePage[offset]) & 0xff)]; + } else if (_renderTextureType == TEXTURE_16BITW) { + int offset = (u & 0x07) | twuLookup[(u >> 3) & 0x1f] | (((v & 0x0700) | twvLookup[(v >> 11) & 0x1f]) << 2); + src = videoRAM[tpOffset + offset]; + } + + if (_renderBReg) { + int bb = (src & 0xff); + int gg = ((src >> 8) & 0xff); + int rr = ((src >> 16) & 0xff); + int mask = ((src & 0xffffff) == 0) ? 0 : 1; + rr = (rr * (r >> 16)) >> 7; + if (rr > 255) rr = 255; + gg = (gg * (g >> 16)) >> 7; + if (gg > 255) gg = 255; + bb = (bb * (b >> 16)) >> 7; + if (bb > 255) bb = 255; + src = (src & 0x01000000) | (rr << 16) | (gg << 8) | bb | mask; + //src = (src&0x01000000)|((b>>16)<<16)|((g>>16)<<8)|(r>>16)|mask; + } + if (_renderTextureType == TEXTURE_NONE || _renderSolid || (src & 0x1ffffff) != 0) { + if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { + } else { + if (_renderSemiType != SEMI_NONE && (_renderTextureType == TEXTURE_NONE || (src & 0x01000000) != 0)) { + // semi transparency + int dest = videoRAM[i]; + int destB = dest & 0xff; + int destG = (dest >> 8) & 0xff; + int destR = (dest >> 16) & 0xff; + int srcB = src & 0xff; + int srcG = (src >> 8) & 0xff; + int srcR = (src >> 16) & 0xff; + int tmpR, tmpG, tmpB; + + if (_renderSemiType == SEMI_5P5) { + tmpR = (srcR + destR) >> 1; + tmpG = (srcG + destG) >> 1; + tmpB = (srcB + destB) >> 1; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P10) { + tmpR = srcR + destR; + tmpG = srcG + destG; + tmpB = srcB + destB; + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10M10) { + tmpR = destR - srcR; + tmpG = destG - srcG; + tmpB = destB - srcB; + if (tmpR < 0) tmpR = 0; + if (tmpG < 0) tmpG = 0; + if (tmpB < 0) tmpB = 0; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P25) { + tmpR = destR + (srcR >> 2); + tmpG = destG + (srcG >> 2); + tmpB = destB + (srcB >> 2); + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } + } + + // mask set + if (_renderSetMask) { + src |= 0x01000000; + } + videoRAM[i] = src; + } + } + if (_renderTextureType != TEXTURE_NONE) { + u++; + } + } + base += 1024; + if (_renderTextureType != TEXTURE_NONE) { + v += 256; + } + } + } + } + + private static class TemplateLineRenderer { + // when we load the particular renderer class we make these final and + // give them a value... if we make them final at compile time, + // then the java compiler does optimizations on them... + private static int _renderSemiType; + private static int _renderTextureType; + private static boolean _renderBReg; + private static boolean _renderGouraud; + private static boolean _renderCheckMask; + private static boolean _renderSetMask; + private static boolean _renderSolid; + + public static void render(LineRenderInfo info, Vertex v0, Vertex v1) { + int clipLeft = m_clipLeft - m_drawOffsetX; + int clipRight = m_clipRight - m_drawOffsetX; + int clipTop = m_clipTop - m_drawOffsetY; + int clipBottom = m_clipBottom - m_drawOffsetY; + + int p0codes = 0; + int p1codes = 0; + + if (v0.x < clipLeft) p0codes |= 1; + if (v0.x >= clipRight) p0codes |= 2; + if (v0.y < clipTop) p0codes |= 4; + if (v0.y >= clipBottom) p0codes |= 8; + + if (v1.x < clipLeft) p1codes |= 1; + if (v1.x >= clipRight) p1codes |= 2; + if (v1.y < clipTop) p1codes |= 4; + if (v1.y >= clipBottom) p1codes |= 8; + + // trivial reject + if (0 != (p0codes & p1codes)) + return; + + // @@@ TMP + if (0 != (p0codes | p1codes)) + return; + + // TODO other code checks + + int color = 0; + int r = 0; + int g = 0; + int b = 0; + + if (!_renderGouraud) { + color = info.color; + } else { + r = info.r0 << 16; + g = info.g0 << 16; + b = info.b0 << 16; + } + + // todo clip + int dx = v1.x - v0.x; + int adx = dx > 0 ? dx : -dx; + int dy = v1.y - v0.y; + int ady = dy > 0 ? dy : -dy; + + if (adx == 0 && ady == 0) + return; + + int count; + int minor; + int dpMajor; + int dpMinor; + int dr = 0; + int dg = 0; + int db = 0; + if (adx > ady) { + // x is major + count = adx;//+1; // check the +1 + minor = ady; + dpMajor = dx > 0 ? 1 : -1; + dpMinor = dy > 0 ? 1024 : -1024; + if (_renderGouraud) { + dr = ((info.r1 - info.r0) << 16) / adx; + dg = ((info.g1 - info.g0) << 16) / adx; + db = ((info.b1 - info.b0) << 16) / adx; + } + } else { + // y is major + count = ady;//+1; // check the +1 + minor = adx; + dpMajor = dy > 0 ? 1024 : -1024; + dpMinor = dx > 0 ? 1 : -1; + if (_renderGouraud) { + dr = ((info.r1 - info.r0) << 16) / ady; + dg = ((info.g1 - info.g0) << 16) / ady; + db = ((info.b1 - info.b0) << 16) / ady; + } + } + + // --- configure span + + int i = m_drawOffsetX + v0.x + (v0.y + m_drawOffsetY) * 1024; + int src = color; + int line = count / 2; + int j = count; + + for (; j > 0; j--) { + if (_renderGouraud) { + src = (b >> 16) | ((g >> 8) & 0xff00) | (r & 0xff0000); + } + if (_renderCheckMask && (videoRAM[i] & 0x01000000) != 0) { + } else { + if (_renderSemiType != SEMI_NONE) { + // semi transparency + int dest = videoRAM[i]; + int destB = dest & 0xff; + int destG = (dest >> 8) & 0xff; + int destR = (dest >> 16) & 0xff; + int srcB = src & 0xff; + int srcG = (src >> 8) & 0xff; + int srcR = (src >> 16) & 0xff; + int tmpR, tmpG, tmpB; + + if (_renderSemiType == SEMI_5P5) { + tmpR = (srcR + destR) >> 1; + tmpG = (srcG + destG) >> 1; + tmpB = (srcB + destB) >> 1; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P10) { + tmpR = srcR + destR; + tmpG = srcG + destG; + tmpB = srcB + destB; + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10M10) { + tmpR = destR - srcR; + tmpG = destG - srcG; + tmpB = destB - srcB; + if (tmpR < 0) tmpR = 0; + if (tmpG < 0) tmpG = 0; + if (tmpB < 0) tmpB = 0; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } else if (_renderSemiType == SEMI_10P25) { + tmpR = destR + (srcR >> 2); + tmpG = destG + (srcG >> 2); + tmpB = destB + (srcB >> 2); + if (tmpR > 255) tmpR = 255; + if (tmpG > 255) tmpG = 255; + if (tmpB > 255) tmpB = 255; + src = (tmpR << 16) | (tmpG << 8) | tmpB; + } + } + + // mask set + if (_renderSetMask) { + src |= 0x01000000; + } + videoRAM[i] = src; + } + i += dpMajor; + line -= minor; + if (line < 0) { + line += count; + i += dpMinor; + } + + if (_renderGouraud) { + r += dr; + g += dg; + b += db; + } + + } + + // --- end span + + } + } + + private static class GPUDRouter { + public static int invoke(int[] data, int offset, int size) { + if (dumpGPUD) { + //System.out.println("GPUD Invoke "+MiscUtil.toHex(m_gpudCommand,8)); + } + + if (m_gpudCommand > 2 && m_gpudCommand < 0x80) { + // todo; dirty based on clip rect + } + + switch (m_gpudCommand & 0xe0) { + case 0x20: + // texture or semi; we should make sure were 16bit + if (0 != (m_gpudCommand & 6)) setVRAMFormat(false); + switch (m_gpudCommand) { + case 0x20: + return gpud3PointFlat(data, offset, size); + case 0x21: + return gpud3PointFlat(data, offset, size); + case 0x22: + return gpud3PointFlatSemi(data, offset, size); + case 0x23: + return gpud3PointFlatSemi(data, offset, size); + + case 0x24: + return gpud3PointTexture(data, offset, size); + case 0x25: + return gpud3PointTexture(data, offset, size); + case 0x26: + return gpud3PointTextureSemi(data, offset, size); + case 0x27: + return gpud3PointTextureSemi(data, offset, size); + + case 0x28: + return gpud4PointFlat(data, offset, size); + case 0x29: + return gpud4PointFlat(data, offset, size); + case 0x2a: + return gpud4PointFlatSemi(data, offset, size); + case 0x2b: + return gpud4PointFlatSemi(data, offset, size); + + case 0x2c: + return gpud4PointTexture(data, offset, size); + case 0x2d: + return gpud4PointTexture(data, offset, size); + case 0x2e: + return gpud4PointTextureSemi(data, offset, size); + case 0x2f: + return gpud4PointTextureSemi(data, offset, size); + + case 0x30: + return gpud3PointGouraud(data, offset, size); + case 0x31: + return gpud3PointGouraud(data, offset, size); + case 0x32: + return gpud3PointGouraudSemi(data, offset, size); + case 0x33: + return gpud3PointGouraudSemi(data, offset, size); + + case 0x34: + return gpud3PointTextureGouraud(data, offset, size); + case 0x35: + return gpud3PointTextureGouraud(data, offset, size); + case 0x36: + return gpud3PointTextureGouraudSemi(data, offset, size); + case 0x37: + return gpud3PointTextureGouraudSemi(data, offset, size); + + case 0x38: + return gpud4PointGouraud(data, offset, size); + case 0x39: + return gpud4PointGouraud(data, offset, size); + case 0x3a: + return gpud4PointGouraudSemi(data, offset, size); + case 0x3b: + return gpud4PointGouraudSemi(data, offset, size); + + case 0x3c: + return gpud4PointTextureGouraud(data, offset, size); + case 0x3d: + return gpud4PointTextureGouraud(data, offset, size); + case 0x3e: + return gpud4PointTextureGouraudSemi(data, offset, size); + case 0x3f: + return gpud4PointTextureGouraudSemi(data, offset, size); + } + break; + case 0x40: + if (0 == (m_gpudCommand & 2)) { + // nom-semi + if (0 == (m_gpudCommand & 8)) { + // non-poly + if (0 == (m_gpudCommand & 0x10)) { + // non-gouraud + return gpudLine(data, offset, size); + } else { + // gouraud + return gpudLineGouraud(data, offset, size); + } + } else { + // poly + if (0 == (m_gpudCommand & 0x10)) { + // non-gouraud + return gpudPolyLine(data, offset, size); + } else { + // gouraud + return gpudPolyLineGouraud(data, offset, size); + } + } + } else { + // semi + setVRAMFormat(false); + if (0 == (m_gpudCommand & 8)) { + // non-poly + if (0 == (m_gpudCommand & 0x10)) { + // non-gouraud + return gpudLineSemi(data, offset, size); + } else { + // gouraud + return gpudLineGouraudSemi(data, offset, size); + } + } else { + // poly + if (0 == (m_gpudCommand & 0x10)) { + // non-gouraud + return gpudPolyLineSemi(data, offset, size); + } else { + // gouraud + return gpudPolyLineGouraudSemi(data, offset, size); + } + } + } + case 0x60: + // texture or semi; we should make sure were 16bit + if (0 != (m_gpudCommand & 6)) setVRAMFormat(false); + switch (m_gpudCommand) { + case 0x60: + return gpudRectangle(data, offset, size); + case 0x61: + return gpudRectangle(data, offset, size); + case 0x62: + return gpudRectangleSemi(data, offset, size); + case 0x63: + return gpudRectangleSemi(data, offset, size); + + case 0x64: + return gpudSprite(data, offset, size); + case 0x65: + return gpudSprite(data, offset, size); + case 0x66: + return gpudSpriteSemi(data, offset, size); + case 0x67: + return gpudSpriteSemi(data, offset, size); + + case 0x68: + return gpudRectangle1x1(data, offset, size); + case 0x69: + return gpudRectangle1x1(data, offset, size); + case 0x6a: + return gpudRectangle1x1Semi(data, offset, size); + case 0x6b: + return gpudRectangle1x1Semi(data, offset, size); + + case 0x6c: + return gpudSprite1x1(data, offset, size); + case 0x6d: + return gpudSprite1x1(data, offset, size); + case 0x6e: + return gpudSprite1x1Semi(data, offset, size); + case 0x6f: + return gpudSprite1x1Semi(data, offset, size); + + case 0x70: + return gpudRectangle8x8(data, offset, size); + case 0x71: + return gpudRectangle8x8(data, offset, size); + case 0x72: + return gpudRectangle8x8Semi(data, offset, size); + case 0x73: + return gpudRectangle8x8Semi(data, offset, size); + + case 0x74: + return gpudSprite8x8(data, offset, size); + case 0x75: + return gpudSprite8x8(data, offset, size); + case 0x76: + return gpudSprite8x8Semi(data, offset, size); + case 0x77: + return gpudSprite8x8Semi(data, offset, size); + + case 0x78: + return gpudRectangle16x16(data, offset, size); + case 0x79: + return gpudRectangle16x16(data, offset, size); + case 0x7a: + return gpudRectangle16x16Semi(data, offset, size); + case 0x7b: + return gpudRectangle16x16Semi(data, offset, size); + + case 0x7c: + return gpudSprite16x16(data, offset, size); + case 0x7d: + return gpudSprite16x16(data, offset, size); + case 0x7e: + return gpudSprite16x16Semi(data, offset, size); + case 0x7f: + return gpudSprite16x16Semi(data, offset, size); + } + break; + default: + switch (m_gpudCommand) { + case 0x01: + return gpudCacheFlush(data, offset, size); + case 0x02: + return gpudClear(data, offset, size); + case 0x80: + return gpudVRAMtoVRAM(data, offset, size); + case 0xa0: + return gpudMemToVRAM(data, offset, size); + case 0xc0: + setVRAMFormat(false); + return gpudVRAMToMem(data, offset, size); + case 0xe1: + return gpudSetDrawMode(data, offset, size); + case 0xe2: + return gpudSetTextureWindow(data, offset, size); + case 0xe3: + return gpudSetClipTopLeft(data, offset, size); + case 0xe4: + return gpudSetClipBottomRight(data, offset, size); + case 0xe5: + return gpudSetDrawingOffset(data, offset, size); + case 0xe6: + return gpudSetMaskMode(data, offset, size); + } + break; + } + return 1; + } + } + + public static int gpudCacheFlush(int[] data, int offset, int size) { + //System.out.println("GPUD CacheFlush"); + return 0; + } + + public static int gpudClear(int[] data, int offset, int size) { + + int x = (data[offset + 1] << 20) >> 20; + int y = (data[offset + 1] << 4) >> 20; + int w = data[offset + 2] & 0xffff; + int h = data[offset + 2] >> 16; + int r = data[offset] & 0xff; + int g = (data[offset] >> 8) & 0xff; + int b = (data[offset] >> 16) & 0xff; + + //LOG7P( GPU_COMMAND, "gpudClear (%d,%d,%u,%u), color (%02x,%02x,%02x)\n",x, y, w, h, r, g, b); + if (dumpGPUD) System.out.println("GPUD clear " + x + "," + y + " " + w + "," + h + " " + colorString(r, g, b)); + + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if ((x + w) > 1024) { + w = 1024 - x; + } + if ((y + h) > 512) { + h = 512 - y; + } + + int base = x + y * 1024; + int color = b | (g << 8) | (r << 16); + for (; h > 0; h--) { + for (int i = base; i < base + w; i++) { + videoRAM[i] = color; + } + base += 1024; + } + return 0; + } + + public static int gpud3PointFlat(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + + v2.x = (data[offset + 3] << 20) >> 20; + v2.y = (data[offset + 3] << 4) >> 20; + + m_polygonInfo.r = data[offset] & 0xff; + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointFlat"); + } + + switch (getMaskModes()) { + case 0: + GPUGenerated._T000000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T000100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T000010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T000110.render(m_polygonInfo, v0, v1, v2); + break; + } + return 0; + } + + public static int gpud3PointFlatSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + + v2.x = (data[offset + 3] << 20) >> 20; + v2.y = (data[offset + 3] << 4) >> 20; + + m_polygonInfo.r = data[offset] & 0xff; + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointFlatSemi"); + } + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T001000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T002000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T003000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T004000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T001100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T002100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T003100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T004100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T001010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T002010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T003010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T004010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T001110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T002110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T003110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T004110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + return 0; + } + + private static Vertex m_v0 = new Vertex(); + private static Vertex m_v1 = new Vertex(); + private static Vertex m_v2 = new Vertex(); + private static Vertex m_v3 = new Vertex(); + + private static void drawModePacket(int packet) { + drawMode = (drawMode & ~0x1ff) | ((packet >> 16) & 0x1ff); + } + + private static PolygonRenderInfo m_polygonInfo = new PolygonRenderInfo(); + private static LineRenderInfo m_lineInfo = new LineRenderInfo(); + + public static int gpud3PointTexture(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + v1.u = data[offset + 4] & 0xff; + v1.v = (data[offset + 4] >> 8) & 0xff; + + drawModePacket(data[offset + 4]); + + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + v2.u = data[offset + 6] & 0xff; + v2.v = (data[offset + 6] >> 8) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointTexture"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T400001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T400101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T400011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T400111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T400000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T400100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T400010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T400110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T800001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T800101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T800011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T800111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T800000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T800100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T800010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T800110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud3PointTexture"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._T600000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T600100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T600010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T600110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T500001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T500101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T500011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T500111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T500000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T500100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T500010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T500110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T900001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T900101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T900011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T900111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T900000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T900100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T900010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T900110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud3PointTexture"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._T700000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T700100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T700010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T700110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + } + return 0; + } + + static int[] m_TempPalette = new int[256]; + + // todo check for cached palette + public static boolean getPalette4(int val) { + int[] src = m_polygonInfo.clut; + int srcIndex = m_polygonInfo.clutOffset; + int first = src[srcIndex]; + + // no breg required + if ((val & 0x01000000) != 0 || (val & 0xffffff) == 0x808080) { + if (0 != (first & PIXEL_SOLID_CLUT_CHECKED)) { + return (first & PIXEL_SOLID_CLUT) != 0; + } + boolean solid = true; + for (int i = 0; i < 16; i++) { + int current = src[srcIndex + i]; + if (0 == (current & 0x1ffffff)) { + solid = false; + break; + } + } +// System.out.println("checking solid 16 for "+MiscUtil.toHex( srcIndex, 5)+" "+solid); + if (solid) { + src[srcIndex] |= PIXEL_SOLID_CLUT | PIXEL_SOLID_CLUT_CHECKED; + } else { + src[srcIndex] = (src[srcIndex] & ~PIXEL_SOLID_CLUT) | PIXEL_SOLID_CLUT_CHECKED; + } + return solid; + } + //if (0==(first&PIXEL_BREG_CLUT)) { + // System.out.println("BREG CLUT 16 "+MiscUtil.toHex( srcIndex, 5)); + // src[srcIndex]|=PIXEL_BREG_CLUT; + //} + + int rmul = (val & 0xff); + int gmul = ((val >> 8) & 0xff); + int bmul = ((val >> 16) & 0xff); + int[] dest = m_TempPalette; + boolean solid = true; + for (int i = 0; i < 16; i++) { + int current = src[srcIndex + i]; + int b = (current & 0xff); + int g = ((current >> 8) & 0xff); + int r = ((current >> 16) & 0xff); + // we mustn't change pixel to a zero unless it was zero to configure with + int mask = ((current & 0xffffff) == 0) ? 0 : 1; + r = (r * rmul) >> 7; + if (r > 255) r = 255; + g = (g * gmul) >> 7; + if (g > 255) g = 255; + b = (b * bmul) >> 7; + if (b > 255) b = 255; + dest[i] = (current & 0x01000000) | (r << 16) | (g << 8) | b | mask; + if (dest[i] == 0) { + solid = false; + } + } + m_polygonInfo.clut = dest; + m_polygonInfo.clutOffset = 0; + return solid; + } + + // todo check for cached palette + public static boolean getPalette8(int val) { + int[] src = m_polygonInfo.clut; + int srcIndex = m_polygonInfo.clutOffset; + int first = src[srcIndex]; + // no breg required + if ((val & 0x01000000) != 0 || (val & 0xffffff) == 0x808080) { + if (0 != (first & PIXEL_SOLID_CLUT_CHECKED)) { + return (first & PIXEL_SOLID_CLUT) != 0; + } + boolean solid = true; + for (int i = 0; i < 256; i++) { + int current = src[srcIndex + i]; + if (0 == (current & 0x1ffffff)) { + solid = false; + break; + } + } +// System.out.println("checking solid 256 for "+MiscUtil.toHex( srcIndex, 5)+" "+solid); + if (solid) { + src[srcIndex] |= PIXEL_SOLID_CLUT | PIXEL_SOLID_CLUT_CHECKED; + } else { + src[srcIndex] = (src[srcIndex] & ~PIXEL_SOLID_CLUT) | PIXEL_SOLID_CLUT_CHECKED; + } + return solid; + } + //if (0==(first&PIXEL_BREG_CLUT)) { + // System.out.println("BREG CLUT 256 "+MiscUtil.toHex( srcIndex, 5)); + // src[srcIndex]|=PIXEL_BREG_CLUT; + //} + + // todo caching here! + boolean solid = true; + int rmul = (val & 0xff); + int gmul = ((val >> 8) & 0xff); + int bmul = ((val >> 16) & 0xff); + int[] dest = m_TempPalette; + for (int i = 0; i < 256; i++) { + int current = src[srcIndex + i]; + int b = (current & 0xff); + int g = ((current >> 8) & 0xff); + int r = ((current >> 16) & 0xff); + // we mustn't change pixel to a zero unless it was zero to start with + int mask = ((current & 0xffffff) == 0) ? 0 : 1; + r = (r * rmul) >> 7; + if (r > 255) r = 255; + g = (g * gmul) >> 7; + if (g > 255) g = 255; + b = (b * bmul) >> 7; + if (b > 255) b = 255; + dest[i] = (current & 0x01000000) | (r << 16) | (g << 8) | b | mask; + if (dest[i] == 0) { + solid = false; + } + } + m_polygonInfo.clut = dest; + m_polygonInfo.clutOffset = 0; + return solid; + } + + public static int gpud3PointTextureSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + v1.u = data[offset + 4] & 0xff; + v1.v = (data[offset + 4] >> 8) & 0xff; + + drawModePacket(data[offset + 4]); + + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + v2.u = data[offset + 6] & 0xff; + v2.v = (data[offset + 6] >> 8) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointTextureSemi"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T401110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T402110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T403110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T404110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T801110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T802110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T803110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T804110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud3PointTextureSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T601000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T602000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T603000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T604000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T601100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T602100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T603100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T604100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T601010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T602010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T603010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T604010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T601110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T602110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T603110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T604110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T501110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T502110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T503110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T504110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T901110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T902110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T903110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T904110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud3PointTextureSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T701000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T702000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T703000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T704000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T701100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T702100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T703100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T704100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T701010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T702010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T703010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T704010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T701110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T702110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T703110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T704110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + } + return 0; + } + + private static String colorString(int r, int g, int b) { + return "(" + MiscUtil.toHex(r, 2) + "," + MiscUtil.toHex(g, 2) + "," + MiscUtil.toHex(b, 2) + ")"; + } + + public static int gpud4PointFlat(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + + v2.x = (data[offset + 3] << 20) >> 20; + v2.y = (data[offset + 3] << 4) >> 20; + + v3.x = (data[offset + 4] << 20) >> 20; + v3.y = (data[offset + 4] << 4) >> 20; + + m_polygonInfo.r = data[offset] & 0xff; + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointFlat " + v0.x + "," + v0.y + " " + v1.x + "," + v1.y + " " + v2.x + "," + v2.y + " " + v3.x + "," + v3.y + " " + + colorString(m_polygonInfo.r, m_polygonInfo.g, m_polygonInfo.b)); + } + + switch (getMaskModes()) { + case 0: + GPUGenerated._Q000000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q000100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q000010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q000110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + return 0; + } + + public static int gpud4PointFlatSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + + v2.x = (data[offset + 3] << 20) >> 20; + v2.y = (data[offset + 3] << 4) >> 20; + + v3.x = (data[offset + 4] << 20) >> 20; + v3.y = (data[offset + 4] << 4) >> 20; + + m_polygonInfo.r = data[offset] & 0xff; + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointFlatSemi"); + } + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q001000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q002000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q003000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q004000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q001100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q002100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q003100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q004100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q001010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q002010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q003010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q004010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q001110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q002110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q003110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q004110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + return 0; + } + + public static int gpud4PointTexture(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + v1.u = data[offset + 4] & 0xff; + v1.v = (data[offset + 4] >> 8) & 0xff; + + drawModePacket(data[offset + 4]); + + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + v2.u = data[offset + 6] & 0xff; + v2.v = (data[offset + 6] >> 8) & 0xff; + + v3.x = (data[offset + 7] << 20) >> 20; + v3.y = (data[offset + 7] << 4) >> 20; + v3.u = data[offset + 8] & 0xff; + v3.v = (data[offset + 8] >> 8) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointTexture " + v0.x + "," + v0.y + " " + v1.x + "," + v1.y + " " + v2.x + "," + v2.y + " " + v3.x + "," + v3.y + " clut " + clx + "," + cly); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q400001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q400101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q400011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q400111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q400000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q400100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q400010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q400110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q800001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q800101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q800011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q800111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q800000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q800100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q800010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q800110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud4PointTexture"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._Q600000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q600100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q600010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q600110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q500001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q500101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q500011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q500111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q500000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q500100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q500010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q500110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q900001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q900101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q900011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q900111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q900000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q900100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q900010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q900110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud4PointTexture"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._Q700000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q700100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q700010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q700110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + } + return 0; + } + + public static int gpud4PointTextureSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + v1.u = data[offset + 4] & 0xff; + v1.v = (data[offset + 4] >> 8) & 0xff; + + drawModePacket(data[offset + 4]); + + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + v2.u = data[offset + 6] & 0xff; + v2.v = (data[offset + 6] >> 8) & 0xff; + + v3.x = (data[offset + 7] << 20) >> 20; + v3.y = (data[offset + 7] << 4) >> 20; + v3.u = data[offset + 8] & 0xff; + v3.v = (data[offset + 8] >> 8) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointTextureSemi"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q401110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q402110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q403110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q404110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q801110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q802110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q803110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q804110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud4PointTextureSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q601000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q602000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q603000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q604000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q601100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q602100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q603100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q604100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q601010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q602010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q603010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q604010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q601110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q602110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q603110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q604110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q501110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q502110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q503110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q504110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q901110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q902110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q903110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q904110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpud4PointTextureSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q701000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q702000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q703000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q704000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q701100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q702100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q703100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q704100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q701010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q702010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q703010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q704010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q701110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q702110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q703110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q704110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + } + return 0; + } + + public static int gpud3PointGouraud(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + + v1.r = data[offset + 2] & 0xff; + v1.g = (data[offset + 2] >> 8) & 0xff; + v1.b = (data[offset + 2] >> 16) & 0xff; + + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + + v2.r = data[offset + 4] & 0xff; + v2.g = (data[offset + 4] >> 8) & 0xff; + v2.b = (data[offset + 4] >> 16) & 0xff; + + //System.out.println("("+v0.r+","+v0.g+","+v0.b+") ("+v1.r+","+v1.g+","+v1.b+") ("+v2.r+","+v2.g+","+v2.b+")"); + if (dumpGPUD) { + System.out.println("gpud3PointGouraud"); + } + switch (getMaskModes()) { + case 0: + GPUGenerated._T010001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T010101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T010011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T010111.render(m_polygonInfo, v0, v1, v2); + break; + } + return 0; + } + + public static int gpud3PointGouraudSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.r = data[offset + 2] & 0xff; + v1.g = (data[offset + 2] >> 8) & 0xff; + v1.b = (data[offset + 2] >> 16) & 0xff; + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + + v2.r = data[offset + 4] & 0xff; + v2.g = (data[offset + 4] >> 8) & 0xff; + v2.b = (data[offset + 4] >> 16) & 0xff; + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + + if (dumpGPUD) { + System.out.println("gpud3PointGouraudSemi"); + } + // todo lots + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T011000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T012000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T013000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T014000.render(m_polygonInfo, v0, v1, v2); + break; + } + return 0; + } + + public static int gpud3PointTextureGouraud(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 4] << 20) >> 20; + v1.y = (data[offset + 4] << 4) >> 20; + v1.u = data[offset + 5] & 0xff; + v1.v = (data[offset + 5] >> 8) & 0xff; + v1.r = data[offset + 3] & 0xff; + v1.g = (data[offset + 3] >> 8) & 0xff; + v1.b = (data[offset + 3] >> 16) & 0xff; + + drawModePacket(data[offset + 5]); + + v2.x = (data[offset + 7] << 20) >> 20; + v2.y = (data[offset + 7] << 4) >> 20; + v2.u = data[offset + 8] & 0xff; + v2.v = (data[offset + 8] >> 8) & 0xff; + v2.r = data[offset + 6] & 0xff; + v2.g = (data[offset + 6] >> 8) & 0xff; + v2.b = (data[offset + 6] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointTextureGouraud"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T410001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T410101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T410011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T410111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T410000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T410100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T410010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T410110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T810001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T810101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T810011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T810111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T810000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T810100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T810010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T810110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: + switch (getMaskModes()) { + case 0: + GPUGenerated._T610000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T610100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T610010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T610110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T510001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T510101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T510011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T510111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T510000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T510100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T510010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T510110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._T910001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T910101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T910011.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T910111.render(m_polygonInfo, v0, v1, v2); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._T910000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T910100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T910010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T910110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: + switch (getMaskModes()) { + case 0: + GPUGenerated._T710000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._T710100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._T710010.render(m_polygonInfo, v0, v1, v2); + break; + default: + GPUGenerated._T710110.render(m_polygonInfo, v0, v1, v2); + break; + } + } + return 0; + } + + public static int gpud3PointTextureGouraudSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 4] << 20) >> 20; + v1.y = (data[offset + 4] << 4) >> 20; + v1.u = data[offset + 5] & 0xff; + v1.v = (data[offset + 5] >> 8) & 0xff; + v1.r = data[offset + 3] & 0xff; + v1.g = (data[offset + 3] >> 8) & 0xff; + v1.b = (data[offset + 3] >> 16) & 0xff; + + drawModePacket(data[offset + 5]); + + v2.x = (data[offset + 7] << 20) >> 20; + v2.y = (data[offset + 7] << 4) >> 20; + v2.u = data[offset + 8] & 0xff; + v2.v = (data[offset + 8] >> 8) & 0xff; + v2.r = data[offset + 6] & 0xff; + v2.g = (data[offset + 6] >> 8) & 0xff; + v2.b = (data[offset + 6] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud3PointTextureGouraudSemi"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T411110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T412110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T413110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T414110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T811110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T812110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T813110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T814110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T611000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T612000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T613000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T614000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T611100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T612100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T613100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T614100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T611010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T612010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T613010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T614010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T611110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T612110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T613110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T614110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + break; + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T511110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T512110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T513110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T514110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913001.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914001.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913101.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914101.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913011.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914011.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913111.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914111.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T911110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T912110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T913110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T914110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T711000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T712000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T713000.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T714000.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T711100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T712100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T713100.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T714100.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T711010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T712010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T713010.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T714010.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._T711110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._T712110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._T713110.render(m_polygonInfo, v0, v1, v2); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._T714110.render(m_polygonInfo, v0, v1, v2); + break; + } + break; + } + } + return 0; + } + + public static int gpud4PointGouraud(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.r = data[offset + 2] & 0xff; + v1.g = (data[offset + 2] >> 8) & 0xff; + v1.b = (data[offset + 2] >> 16) & 0xff; + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + + v2.r = data[offset + 4] & 0xff; + v2.g = (data[offset + 4] >> 8) & 0xff; + v2.b = (data[offset + 4] >> 16) & 0xff; + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + + v3.r = data[offset + 6] & 0xff; + v3.g = (data[offset + 6] >> 8) & 0xff; + v3.b = (data[offset + 6] >> 16) & 0xff; + v3.x = (data[offset + 7] << 20) >> 20; + v3.y = (data[offset + 7] << 4) >> 20; + + if (dumpGPUD) { + System.out.println("gpud4PointGouraud"); + } + GPUGenerated._Q010000.render(m_polygonInfo, v0, v1, v2, v3); + return 0; + } + + public static int gpud4PointGouraudSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + + v1.r = data[offset + 2] & 0xff; + v1.g = (data[offset + 2] >> 8) & 0xff; + v1.b = (data[offset + 2] >> 16) & 0xff; + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + + v2.r = data[offset + 4] & 0xff; + v2.g = (data[offset + 4] >> 8) & 0xff; + v2.b = (data[offset + 4] >> 16) & 0xff; + v2.x = (data[offset + 5] << 20) >> 20; + v2.y = (data[offset + 5] << 4) >> 20; + + v3.r = data[offset + 6] & 0xff; + v3.g = (data[offset + 6] >> 8) & 0xff; + v3.b = (data[offset + 6] >> 16) & 0xff; + v3.x = (data[offset + 7] << 20) >> 20; + v3.y = (data[offset + 7] << 4) >> 20; + + if (dumpGPUD) { + System.out.println("gpud4PointGouraudSemi"); + } + // todo lots + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q011000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q012000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q013000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q014000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + return 0; + } + + public static int gpud4PointTextureGouraud(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 4] << 20) >> 20; + v1.y = (data[offset + 4] << 4) >> 20; + v1.u = data[offset + 5] & 0xff; + v1.v = (data[offset + 5] >> 8) & 0xff; + v1.r = data[offset + 3] & 0xff; + v1.g = (data[offset + 3] >> 8) & 0xff; + v1.b = (data[offset + 3] >> 16) & 0xff; + + drawModePacket(data[offset + 5]); + + v2.x = (data[offset + 7] << 20) >> 20; + v2.y = (data[offset + 7] << 4) >> 20; + v2.u = data[offset + 8] & 0xff; + v2.v = (data[offset + 8] >> 8) & 0xff; + v2.r = data[offset + 6] & 0xff; + v2.g = (data[offset + 6] >> 8) & 0xff; + v2.b = (data[offset + 6] >> 16) & 0xff; + + v3.x = (data[offset + 10] << 20) >> 20; + v3.y = (data[offset + 10] << 4) >> 20; + v3.u = data[offset + 11] & 0xff; + v3.v = (data[offset + 11] >> 8) & 0xff; + v3.r = data[offset + 9] & 0xff; + v3.g = (data[offset + 9] >> 8) & 0xff; + v3.b = (data[offset + 9] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointTextureGouraud"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q410001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q410101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q410011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q410111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q410000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q410100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q410010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q410110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q810001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q810101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q810011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q810111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q810000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q810100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q810010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q810110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: + switch (getMaskModes()) { + case 0: + GPUGenerated._Q610000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q610100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q610010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q610110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q510001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q510101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q510011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q510111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q510000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q510100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q510010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q510110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q910001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q910101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q910011.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q910111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._Q910000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q910100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q910010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q910110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: + switch (getMaskModes()) { + case 0: + GPUGenerated._Q710000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._Q710100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._Q710010.render(m_polygonInfo, v0, v1, v2, v3); + break; + default: + GPUGenerated._Q710110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + } + return 0; + } + + public static int gpud4PointTextureGouraudSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + Vertex v2 = m_v2; + Vertex v3 = m_v3; + + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v0.u = data[offset + 2] & 0xff; + v0.v = (data[offset + 2] >> 8) & 0xff; + v0.r = data[offset] & 0xff; + v0.g = (data[offset] >> 8) & 0xff; + v0.b = (data[offset] >> 16) & 0xff; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + v1.x = (data[offset + 4] << 20) >> 20; + v1.y = (data[offset + 4] << 4) >> 20; + v1.u = data[offset + 5] & 0xff; + v1.v = (data[offset + 5] >> 8) & 0xff; + v1.r = data[offset + 3] & 0xff; + v1.g = (data[offset + 3] >> 8) & 0xff; + v1.b = (data[offset + 3] >> 16) & 0xff; + + drawModePacket(data[offset + 5]); + + v2.x = (data[offset + 7] << 20) >> 20; + v2.y = (data[offset + 7] << 4) >> 20; + v2.u = data[offset + 8] & 0xff; + v2.v = (data[offset + 8] >> 8) & 0xff; + v2.r = data[offset + 6] & 0xff; + v2.g = (data[offset + 6] >> 8) & 0xff; + v2.b = (data[offset + 6] >> 16) & 0xff; + + v3.x = (data[offset + 10] << 20) >> 20; + v3.y = (data[offset + 10] << 4) >> 20; + v3.u = data[offset + 11] & 0xff; + v3.v = (data[offset + 11] >> 8) & 0xff; + v3.r = data[offset + 9] & 0xff; + v3.g = (data[offset + 9] >> 8) & 0xff; + v3.b = (data[offset + 9] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpud4PointTextureGouraudSemi"); + } + // TODO texturepage + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q411110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q412110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q413110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q414110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q811110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q812110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q813110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q814110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q611000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q612000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q613000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q614000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q611100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q612100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q613100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q614100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q611010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q612010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q613010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q614010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q611110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q612110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q613110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q614110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + break; + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q511110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q512110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q513110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q514110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset] | 0x01000000)) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913001.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914001.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913101.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914101.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913011.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914011.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913111.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914111.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q911110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q912110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q913110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q914110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q711000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q712000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q713000.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q714000.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q711100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q712100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q713100.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q714100.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q711010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q712010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q713010.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q714010.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._Q711110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._Q712110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._Q713110.render(m_polygonInfo, v0, v1, v2, v3); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._Q714110.render(m_polygonInfo, v0, v1, v2, v3); + break; + } + break; + } + } + return 0; + } + + public static int gpudLine(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + m_lineInfo.color = makePixel(data[offset] & 0xff, (data[offset] >> 8) & 0xff, (data[offset] >> 16) & 0xff, 0); + + if (dumpGPUD) { + System.out.println("gpudLine (" + v0.x + "," + v0.y + ") -> (" + v1.x + "," + v1.y + ")"); + } + switch (getMaskModes()) { + case 0: + GPUGenerated._L000000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._L000100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._L000010.render(m_lineInfo, v0, v1); + break; + default: + GPUGenerated._L000110.render(m_lineInfo, v0, v1); + break; + } + return 0; + } + + public static int gpudLineSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v1.x = (data[offset + 2] << 20) >> 20; + v1.y = (data[offset + 2] << 4) >> 20; + m_lineInfo.color = makePixel(data[offset] & 0xff, (data[offset] >> 8) & 0xff, (data[offset] >> 16) & 0xff, 0); + + if (dumpGPUD) { + System.out.println("gpudLineSemi"); + } + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L001000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L002000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L003000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L004000.render(m_lineInfo, v0, v1); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L001100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L002100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L003100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L004100.render(m_lineInfo, v0, v1); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L001010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L002010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L003010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L004010.render(m_lineInfo, v0, v1); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L001110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L002110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L003110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L004110.render(m_lineInfo, v0, v1); + break; + } + break; + } + return 0; + } + + public static int gpudPolyLine(int[] data, int offset, int size) { + if (m_gpudState != GPUD_CMD_EXTRA) { + // Draw the first line segment. + gpudLine(data, offset, 3); + polyLineCmdBuffer[0] = data[offset]; // Color for whole polyline. + polyLineCmdBuffer[1] = data[offset + 2]; // v1 for next line segment. + m_gpudState = GPUD_CMD_EXTRA; + return 0; + } else { + // todo; do this more efficiently! + // NOTE: While most games use 0x55555555, Wild Arms uses 0x50005000. + // http://problemkaputt.de/psx-spx.htm#gpurenderlinecommands + if ((data[offset] & 0xf000f000 ) == 0x50005000) { + // End of the polyline! + m_gpudState = GPUD_CMD_NONE; + } else { + // Draw the next line segment. + polyLineCmdBuffer[2] = data[offset]; + gpudLine(polyLineCmdBuffer, 0, 3); + // Buffer entry 0 [color data] doesn't need to be rewritten. + polyLineCmdBuffer[1] = data[offset]; // v1 for next line segment. + } + return 1; + } + } + + public static int gpudPolyLineSemi(int[] data, int offset, int size) { + System.out.println("GPUD PolyLineSemi"); + if (true) throw new IllegalStateException(); + return 0; + } + + public static int gpudLineGouraudSemi(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + m_lineInfo.r0 = data[offset] & 0xff; + m_lineInfo.g0 = (data[offset] >> 8) & 0xff; + m_lineInfo.b0 = (data[offset] >> 16) & 0xff; + m_lineInfo.r1 = data[offset + 2] & 0xff; + m_lineInfo.g1 = (data[offset + 2] >> 8) & 0xff; + m_lineInfo.b1 = (data[offset + 2] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpudLineGouraudSemi"); + } + + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L011000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L012000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L013000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L014000.render(m_lineInfo, v0, v1); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L011100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L012100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L013100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L014100.render(m_lineInfo, v0, v1); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L011010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L012010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L013010.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L014010.render(m_lineInfo, v0, v1); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._L011110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._L012110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._L013110.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._L014110.render(m_lineInfo, v0, v1); + break; + } + break; + } + return 0; + } + + public static int gpudLineGouraud(int[] data, int offset, int size) { + Vertex v0 = m_v0; + Vertex v1 = m_v1; + v0.x = (data[offset + 1] << 20) >> 20; + v0.y = (data[offset + 1] << 4) >> 20; + v1.x = (data[offset + 3] << 20) >> 20; + v1.y = (data[offset + 3] << 4) >> 20; + m_lineInfo.r0 = data[offset] & 0xff; + m_lineInfo.g0 = (data[offset] >> 8) & 0xff; + m_lineInfo.b0 = (data[offset] >> 16) & 0xff; + m_lineInfo.r1 = data[offset + 2] & 0xff; + m_lineInfo.g1 = (data[offset + 2] >> 8) & 0xff; + m_lineInfo.b1 = (data[offset + 2] >> 16) & 0xff; + + if (dumpGPUD) { + System.out.println("gpudLineGouraud"); + } + switch (getMaskModes()) { + case 0: + GPUGenerated._L010000.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._L010100.render(m_lineInfo, v0, v1); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._L010010.render(m_lineInfo, v0, v1); + break; + default: + GPUGenerated._L010110.render(m_lineInfo, v0, v1); + break; + } + return 0; + } + + public static int gpudPolyLineGouraud(int[] data, int offset, int size) { + System.out.println("GPUD PolyLineGouraud"); + if (true) throw new IllegalStateException(); + return 0; + } + + private static int[] polyLineCmdBuffer = new int[4]; + + public static int gpudPolyLineGouraudSemi(int[] data, int offset, int size) { + if (m_gpudState != GPUD_CMD_EXTRA) { + gpudLineGouraudSemi(data, offset, 4); + polyLineCmdBuffer[0] = data[offset + 2]; // color1 + polyLineCmdBuffer[1] = data[offset + 3]; // v1 + polyLineCmdBuffer[2] = 0x55555555; + m_gpudState = GPUD_CMD_EXTRA; + return 0; + } else { + // todo; do this more efficiently! + // NOTE: While most games use 0x55555555, Wild Arms uses 0x50005000. + // http://problemkaputt.de/psx-spx.htm#gpurenderlinecommands + if ((data[offset] & 0xf000f000 ) == 0x50005000) { + m_gpudState = GPUD_CMD_NONE; + return 1; + } + if (polyLineCmdBuffer[2] == 0x55555555) { + polyLineCmdBuffer[2] = data[offset]; + } else { + polyLineCmdBuffer[3] = data[offset + 1]; + gpudLineGouraudSemi(polyLineCmdBuffer, 0, 4); + polyLineCmdBuffer[0] = polyLineCmdBuffer[2]; + polyLineCmdBuffer[1] = polyLineCmdBuffer[3]; + polyLineCmdBuffer[2] = 0x55555555; + } + return 1; + } + } + + public static int gpudRectangle(int[] data, int offset, int size) { + + m_polygonInfo.r = (data[offset] & 0xff); + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + int x = (data[offset + 1] << 20) >> 20; + int y = (data[offset + 1] << 4) >> 20; + + int w = data[offset + 2] & 0xffff; + int h = data[offset + 2] >> 16; + + if (dumpGPUD) { + System.out.println("gpudRectangle " + x + "," + y + " " + w + "," + h); + } + switch (getMaskModes()) { + case 0: + GPUGenerated._S000000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S000100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S000010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S000110.render(m_polygonInfo, x, y, w, h); + break; + } + return 0; + } + + public static int gpudRectangleSemi(int[] data, int offset, int size) { + + m_polygonInfo.r = (data[offset] & 0xff); + m_polygonInfo.g = (data[offset] >> 8) & 0xff; + m_polygonInfo.b = (data[offset] >> 16) & 0xff; + + int x = (data[offset + 1] << 20) >> 20; + int y = (data[offset + 1] << 4) >> 20; + + int w = data[offset + 2] & 0xffff; + int h = data[offset + 2] >> 16; + + if (dumpGPUD) { + System.out.println("gpudRectangleSemi " + x + "," + y + " " + w + "," + h); + } + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S001000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S002000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S003000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S004000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S001100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S002100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S003100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S004100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S001010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S002010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S003010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S004010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S001110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S002110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S003110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S004110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + return 0; + } + + public static int gpudSprite(int[] data, int offset, int size) { + + + int x = (data[offset + 1] << 20) >> 20; + int y = (data[offset + 1] << 4) >> 20; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.u = data[offset + 2] & 0xff; + m_polygonInfo.v = (data[offset + 2] >> 8) & 0xff; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + int w = data[offset + 3] & 0x1ff; + int h = data[offset + 3] >> 16; + + if (dumpGPUD) { + System.out.println("gpudSprite " + x + "," + y + " " + w + "," + h + " tm " + getTextureMode() + " mm " + getMaskModes()); + } + if (false && x == -48 && y == 96 && w == 16 && h == 16) { + try { + java.io.FileOutputStream fos = new java.io.FileOutputStream("vram.dat"); + for (int i = 0; i < 1024 * 512; i++) { + int b = videoRAM[i]; + fos.write(b & 0xff); + fos.write((b >> 8) & 0xff); + fos.write((b >> 16) & 0xff); + fos.write((b >> 24) & 0x01); + } + } catch (Throwable t) { + + } + System.exit(0); + } + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._S400001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S400101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S400011.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S400111.render(m_polygonInfo, x, y, w, h); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._S400000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S400100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S400010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S400110.render(m_polygonInfo, x, y, w, h); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._S800001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S800101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S800011.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S800111.render(m_polygonInfo, x, y, w, h); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._S800000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S800100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S800010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S800110.render(m_polygonInfo, x, y, w, h); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpudSprite"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._S600000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S600100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S600010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S600110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._S500001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S500101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S500011.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S500111.render(m_polygonInfo, x, y, w, h); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._S500000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S500100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S500010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S500110.render(m_polygonInfo, x, y, w, h); + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + GPUGenerated._S900001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S900101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S900011.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S900111.render(m_polygonInfo, x, y, w, h); + break; + } + } else { + switch (getMaskModes()) { + case 0: + GPUGenerated._S900000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S900100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S900010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S900110.render(m_polygonInfo, x, y, w, h); + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpudSprite"); + } + // todo breg + switch (getMaskModes()) { + case 0: + GPUGenerated._S700000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SET_MASK: + GPUGenerated._S700100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_CHECK_MASK: + GPUGenerated._S700010.render(m_polygonInfo, x, y, w, h); + break; + default: + GPUGenerated._S700110.render(m_polygonInfo, x, y, w, h); + break; + } + } + } + return 0; + + + } + + public static int gpudSpriteSemi(int[] data, int offset, int size) { + + int x = (data[offset + 1] << 20) >> 20; + int y = (data[offset + 1] << 4) >> 20; + + int cly = (data[offset + 2] >> 22) & 0x1ff; + int clx = (data[offset + 2] & 0x3f0000) >> 12; + m_polygonInfo.u = data[offset + 2] & 0xff; + m_polygonInfo.v = (data[offset + 2] >> 8) & 0xff; + m_polygonInfo.clut = videoRAM; + m_polygonInfo.clutOffset = cly * 1024 + clx; + + int w = data[offset + 3] & 0x1ff; + int h = data[offset + 3] >> 16; + + if (dumpGPUD) { + System.out.println("gpudSpriteSemi " + x + "," + y + " " + w + "," + h); + } + switch (getTextureMode()) { + case DRAWMODE_TEXTURE_4BIT: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404001.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404101.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404011.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404111.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S401110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S402110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S403110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S404110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BIT: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804001.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804101.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804011.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804111.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S801110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S802110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S803110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S804110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BIT: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpudSpriteSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S601000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S602000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S603000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S604000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S601100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S602100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S603100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S604100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S601010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S602010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S603010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S604010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S601110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S602110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S603110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S604110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + break; + } + case DRAWMODE_TEXTURE_4BITW: + if (getPalette4(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504001.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504101.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504011.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504111.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S501110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S502110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S503110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S504110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_8BITW: + if (getPalette8(data[offset])) { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903001.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904001.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903101.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904101.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903011.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904011.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903111.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904111.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } else { + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S901110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S902110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S903110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S904110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } + break; + case DRAWMODE_TEXTURE_16BITW: { + boolean nobreg = false; + if (((data[offset] & 0x01000000) != 0) || ((data[offset] & 0xffffff) == 0x808080)) { + nobreg = true; + } else { + missing("16 bit breg gpudSpriteSemi"); + } + // todo breg + switch (getMaskModes()) { + case 0: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S701000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S702000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S703000.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S704000.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_SET_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S701100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S702100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S703100.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S704100.render(m_polygonInfo, x, y, w, h); + break; + } + break; + case DRAWMODE_CHECK_MASK: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S701010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S702010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S703010.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S704010.render(m_polygonInfo, x, y, w, h); + break; + } + break; + default: + switch (getSemiMode()) { + case DRAWMODE_SEMI_5P5: + GPUGenerated._S701110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P10: + GPUGenerated._S702110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10M10: + GPUGenerated._S703110.render(m_polygonInfo, x, y, w, h); + break; + case DRAWMODE_SEMI_10P25: + GPUGenerated._S704110.render(m_polygonInfo, x, y, w, h); + break; + } + break; + } + } + } + return 0; + } + + public static int gpudRectangle1x1(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00010001; + int rc = gpudRectangle(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudRectangle1x1Semi(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00010001; + int rc = gpudRectangleSemi(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudSprite1x1(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00010001; + int rc = gpudSprite(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudSprite1x1Semi(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00010001; + int rc = gpudSpriteSemi(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudRectangle8x8(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00080008; + int rc = gpudRectangle(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudRectangle8x8Semi(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00080008; + int rc = gpudRectangleSemi(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudSprite8x8(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00080008; + int rc = gpudSprite(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudSprite8x8Semi(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00080008; + int rc = gpudSpriteSemi(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudRectangle16x16(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00100010; + int rc = gpudRectangle(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudRectangle16x16Semi(int[] data, int offset, int size) { + int tmp = data[offset + 2]; + data[offset + 2] = 0x00100010; + int rc = gpudRectangleSemi(data, offset, size); + data[offset + 2] = tmp; + return rc; + } + + public static int gpudSprite16x16(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00100010; + int rc = gpudSprite(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudSprite16x16Semi(int[] data, int offset, int size) { + int tmp = data[offset + 3]; + data[offset + 3] = 0x00100010; + int rc = gpudSpriteSemi(data, offset, size); + data[offset + 3] = tmp; + return rc; + } + + public static int gpudVRAMtoVRAM(int[] data, int offset, int size) { + // todo check sizes + int sx = data[offset + 1] & 0x3ff; + int sy = (data[offset + 1] >> 16) & 0x1ff; + int dx = data[offset + 2] & 0x3ff; + int dy = (data[offset + 2] >> 16) & 0x1ff; + + if (sx == dx && sy == dy) { + if (false) + System.out.println("??? " + MiscUtil.toHex(data[offset], 8) + " " + + MiscUtil.toHex(data[offset + 1], 8) + " " + + MiscUtil.toHex(data[offset + 2], 8) + " " + + MiscUtil.toHex(data[offset + 3], 8)); + return 0; + } + int w = data[offset + 3] & 0x3ff; + int h = (data[offset + 3] >> 16) & 0x1ff; + // todo is this slow? + if (dumpGPUD) + System.out.println("GPUD VRAMToVRAM " + sx + "," + sy + " " + w + "," + h + " -> " + dx + "," + dy); + + if (w > 0) { + int src = sx + sy * 1024; + int dest = dx + dy * 1024; + // system.arraycopy? + if (dest < src) { + for (; h > 0; h--) { + for (int x = 0; x < w; x++) { + videoRAM[dest + x] = videoRAM[src + x]; + } + src += 1024; + dest += 1024; + } + } else { + src += (h - 1) * 1024; + dest += (h - 1) * 1024; + for (; h > 0; h--) { + for (int x = w - 1; x >= 0; x--) { + videoRAM[dest + x] = videoRAM[src + x]; + } + src -= 1024; + dest -= 1024; + } + } + } + manager.dirtyRectangle(dx, dy, w, h); + return 0; + } + + public static int gpudMemToVRAM(int[] data, int offset, int size) { + if (m_gpudState != GPUD_CMD_EXTRA) { + int x = data[offset + 1] & 0x3ff; + int y = (data[offset + 1] >> 16) & 0x1ff; + int w = data[offset + 2] & 0x7ff; + int h = (data[offset + 2] >> 16) & 0x3ff; + int dwordSize = (w * h + 1) >> 1; + + m_dmaRGB24Index = 0; + m_dmaX = x; + m_dmaY = y; + m_dmaOriginX = x; + m_dmaOriginY = y; + m_dmaW = w; + m_dmaH = h; + if (dumpGPUD) System.out.println("GPUD MemToVRAM " + x + "," + y + " " + w + "," + h); + if (dwordSize > 0) { + m_gpudState = GPUD_CMD_EXTRA; + m_dmaDWordsRemaining = dwordSize; + } + return 0; + } else { + //System.out.println("Avail: "+count); + //System.out.println("MemToVRAM remaining: "+m_dmaDWordsRemaining); + if (size > m_dmaDWordsRemaining) { + size = m_dmaDWordsRemaining; + } + int rc = size; + m_dmaDWordsRemaining -= size; + + size *= 2; + + int[] ram; + + try { + ram = display.acquireDisplayBuffer(); + + // TODO this is woefully inefficient :-) + if (rgb24conversion && rgb24 && (m_dmaW % 6) == 0) { + // todo graham 12/21/14 - I realized while debugging the intro screen of spyro + // that I actually thought the B and the R were the other way around on the PSX + // curiously that works for other things. Frankly at this point I don't think + // the work of doing the conversion to a separate 24 bit display buffer at display time + // is that bad and will gain us some simplification - probably worth a fork of the GPU/Display though + + // we convert dwords from: + // B1R0G0B0 G2B2R1G1 R3G3B3R2 + // to + // A_R0G0B0 B_R0G0B1 C_R1G1B1 A_R2G2B2 B_R2G2B3 C_R3G3B3 + + // consider words, we pick the internal representation, such that + // we can convert a single pixel without knowing where it came from + // i.e. A_ pixels do one thing, B_ another, and C_ a third. + + // G0B0 B1R0 R1G1 G2B2 B3R2 R3G3 + // to: + // A_R0G0B0 B_R0G0B1 C_R1G1B1 A_R2G2B2 B_R2G2B3 C_R3G3B3 + // to: + // G0B0 B1R0 R1G1 G2B2 B3R2 R3G3 + + while (size > 0) { + int dword = data[offset++]; + switch (m_dmaRGB24Index) { + case 0: + m_dmaRGB24LastPixel = (dword & 0xffffff); + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_A | m_dmaRGB24LastPixel; + m_dmaRGB24LastDWord = dword; + m_dmaX++; + m_dmaRGB24Index = 1; + break; + case 1: + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_B | (m_dmaRGB24LastPixel & 0xffff00) | (m_dmaRGB24LastDWord >>> 24); + m_dmaX++; + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_C | (m_dmaRGB24LastDWord >>> 24) | ((dword << 8) & 0xffff00); + m_dmaRGB24LastDWord = dword; + m_dmaX++; + m_dmaRGB24Index = 2; + break; + case 2: + m_dmaRGB24LastPixel = (m_dmaRGB24LastDWord >>> 16) | ((dword & 0xff) << 16); + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_A | m_dmaRGB24LastPixel; + m_dmaX++; + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_B | (m_dmaRGB24LastPixel & 0xffff00) | ((dword >> 8) & 0xff); + m_dmaX++; + ram[m_dmaX + m_dmaY * 1024] = GPU_RGB24_C | ((dword >> 8) & 0xffffff); + m_dmaX++; + m_dmaRGB24Index = 0; + break; + } + if (m_dmaX == (m_dmaOriginX + m_dmaW)) { + m_dmaX = m_dmaOriginX; + m_dmaY++; + m_dmaRGB24Index = 0; + if (m_dmaY == (m_dmaOriginY + m_dmaH)) { + break; + } + } + size -= 2; + } + } else { + // 16 bit + while (size > 0) { + int dword = data[offset++]; + int val = dword >>> 16; + ram[m_dmaX + m_dmaY * 1024] = dma16flags[m_dmaRGB24Index] | makePixel((dword & 0x1f) << 3, (dword & 0x3e0) >> 2, (dword & 0x7c00) >> 7, (dword & 0x8000) >> 15); + m_dmaX++; + m_dmaRGB24Index++; + if (m_dmaX == (m_dmaOriginX + m_dmaW)) { + m_dmaX = m_dmaOriginX; + m_dmaY++; + if (m_dmaY == (m_dmaOriginY + m_dmaH)) { + break; + } + m_dmaRGB24Index = 0; + } + size--; + + ram[m_dmaX + m_dmaY * 1024] = dma16flags[m_dmaRGB24Index] | makePixel((val & 0x1f) << 3, (val & 0x3e0) >> 2, (val & 0x7c00) >> 7, (val & 0x8000) >> 15); + m_dmaX++; + m_dmaRGB24Index++; + if (m_dmaX == (m_dmaOriginX + m_dmaW)) { + m_dmaX = m_dmaOriginX; + m_dmaY++; + if (m_dmaY == (m_dmaOriginY + m_dmaH)) { + break; + } + m_dmaRGB24Index = 0; + } + size--; + if (m_dmaRGB24Index >= 3) m_dmaRGB24Index -= 3; + } + } + } finally { + display.releaseDisplayBuffer(); + } + + if (m_dmaDWordsRemaining == 0) { + int x = m_dmaOriginX; + int y = m_dmaOriginY; + int w = m_dmaW; + int h = m_dmaH; + // todo clear the cache better + for (int page = 0; page < 0x20; page++) { + int px = (page & 0x0f) * 64; + int py = (page & 0x10) * 16; + if (intersects(x, y, w, h, px, py, 64, 256)) { + if (dumpGPUD) { + if (_4bitTexturePages[page] != null) + System.out.println("Zapping 4bit tpage " + page); + } + _4bitTexturePages[page] = null; + } + if (intersects(x, y, w, h, px, py, 128, 256)) { + if (dumpGPUD) { + if (_8bitTexturePages[page] != null) + System.out.println("Zapping 8bit tpage " + page); + } + _8bitTexturePages[page] = null; + } + } + manager.dirtyRectangle(x, y, w, h); + m_gpudState = GPUD_CMD_NONE; + } + return rc; + } + } + + private static boolean intersects(int x0, int y0, int w0, int h0, int x1, int y1, int w1, int h1) { + if (w0 == 0 || h0 == 0 || w1 == 0 || h1 == 0) return false; + w0 += x0; + w1 += x1; + h0 += y0; + h1 += y1; + return (w0 > x1) && (h0 > y1) && (w1 > x0) && (h1 > y0); + } + +/* private static boolean intersectsDisplay( int x, int y, int w, int h) + { + int dx = m_displayX; + int dy = m_displayY; + int dw = m_displayWidth; + int dh = m_displayHeight; + + // todo display configure/end + + if (0!=(m_displayMode&0x0040) && h==1) { + if ((!interlace && 0!=((dy+y)&1)) || + (interlace && 0==((dy+y)&1))) { + //System.out.println("Detected non-intersect in interlaced mode"); + return false; + } + } + return intersects( x, y, w, h, dx, dy, dw, dh); + }*/ + + public static int gpudVRAMToMem(int[] data, int offset, int size) { + int x = data[offset + 1] & 0x3ff; + int y = (data[offset + 1] >> 16) & 0x1ff; + int w = data[offset + 2] & 0x7ff; + int h = (data[offset + 2] >> 16) & 0x3ff; + + m_dmaX = x; + m_dmaY = y; + m_dmaOriginX = x; + m_dmaOriginY = y; + m_dmaW = w; + m_dmaH = h; + m_dmaWordsRemaining = w * h; + if (dumpGPUD) System.out.println("GPUD VRAMtoMem " + x + "," + y + " " + w + "," + h); + assert !rgb24; + return 0; + } + + private static int readPixel() { + if (m_dmaWordsRemaining > 0) { + m_dmaWordsRemaining--; + int rc = unmakePixel(videoRAM[m_dmaX + m_dmaY * 1024]); + m_dmaX++; + if (m_dmaX == m_dmaOriginX + m_dmaW) { + m_dmaX = m_dmaOriginX; + m_dmaY++; + } + return rc; + } + return 0; + } + + public static int gpudSetDrawMode(int[] data, int offset, int size) { + drawMode = data[offset] & 0x7ff; + return 0; + } + + public static int gpudSetTextureWindow(int[] data, int offset, int size) { + if (!supportTextureWindow) { + noTextureWindow = true; + return 0; + } + noTextureWindow = 0 == (data[offset] & 0xfffff); + if (!noTextureWindow) { + int twy = (data[offset] >> 15) & 0x1f; + int twx = (data[offset] >> 10) & 0x1f; + int twh = 32 - ((data[offset] >> 5) & 0x1f); + int tww = 32 - ((data[offset]) & 0x1f); + + // todo cache recent? + int val = twx << 3; + int w = 0; + for (int i = twx; i < 32 + twx; i++) { + twuLookup[i & 0x1f] = val; + val += 1 << 3; + w++; + if (w == tww) { + w = 0; + val = twx << 3; + } + } + + val = twy << 11; + int h = 0; + for (int i = twy; i < 32 + twy; i++) { + twvLookup[i & 0x1f] = val; + val += 1 << 11; + h++; + if (h == twh) { + h = 0; + val = twy << 11; + } + } + + if (dumpGPUD) { + System.out.println("GPUD SetTextureWindow " + (twx * 8) + "," + (twy * 8) + " " + (tww * 8) + "," + (twh * 8)); + } + } + return 0; + } + + public static int gpudSetClipTopLeft(int[] data, int offset, int size) { + m_clipLeft = data[offset] & 0x3ff; + m_clipTop = (data[offset] >> 10) & 0x3ff; + // System.out.println("GPUD SetClipTopLeft "+m_clipLeft+","+m_clipTop); + return 0; + } + + public static int gpudSetClipBottomRight(int[] data, int offset, int size) { + // note addition of (1,1) to co-ords, since we do non-inclusive bottom-right, + // but PSX doesn't. + m_clipRight = (data[offset] & 0x3ff) + 1; + m_clipBottom = ((data[offset] >> 10) & 0x3ff) + 1; + // System.out.println("GPUD SetClipBottomRight "+m_clipRight+","+m_clipBottom); + return 0; + } + + public static int gpudSetDrawingOffset(int[] data, int offset, int size) { + m_drawOffsetX = ((data[offset] & 0x7ff) << 21) >> 21; + m_drawOffsetY = ((data[offset] & 0x3ff800) << 10) >> 21; + // System.out.println("GPUD SetDrawingOfffset "+m_drawOffsetX+","+m_drawOffsetY); + return 0; + } + + public static int gpudSetMaskMode(int[] data, int offset, int size) { + // store the mask settings where they go + + // TODO ? more efficient to keep in low bits because of switch + drawMode = (drawMode & ~(DRAWMODE_SET_MASK | DRAWMODE_CHECK_MASK)) | ((data[offset] & 0x1800) >> 11); + return 0; + } + + public static int gpuStatusRead32(int address) { +// ASSERT( SANITY_CHECK, address==ADDR_GPU_CTRLSTATUS, ""); + int rc = 0; + + // ----------------------------------------------------------------------------- + // |1f |1e 1d|1c |1b |1a |19 18|17 |16 |15 |14 |13 |12 11 |10 | + // |lcf|dma |com|img|busy| ? ?|den|isinter|isrgb24|Video|Height|Width0|Width1| + // ----------------------------------------------------------------------------- + + // ---------------------------------------------------- + // |0f 0e 0d|0c|0b|0a |09 |08 07|06 05|04|03 02 01 00| + // | ? ? ?|me|md|dfe |dtd|tp |abr |ty|tx | + // ---------------------------------------------------- + + // 0000 0000 0000 0000 0000 0111 1111 1111 +// rc |= getRenderer()->getDrawMode(); + rc |= drawMode; + + // TODO don't need this since it is part of draw mode ??? + // 0000 0000 0000 0000 0001 1000 0000 0000 + //rc |= m_maskMode<<11; + + // 0000 0000 0000 0000 1110 0000 0000 0000 + // 0000 0000 0111 1111 0000 0000 0000 0000 + rc |= displayMode << 16; + + // 0000 0000 1000 0000 0000 0000 0000 0000 + if (!m_displayEnabled) + rc |= 0x00800000; + + // 0000 0011 0000 0000 0000 0000 0000 0000 + // 0000 0100 0000 0000 0000 0000 0000 0000 + rc |= 0x04000000; // gpu idle + + // TODO turn this off at some point + // 0000 1000 0000 0000 0000 0000 0000 0000 + rc |= 0x08000000; // ready to receive img + + // 0001 0000 0000 0000 0000 0000 0000 0000 + rc |= 0x10000000; // ready to receive cmds + + // 0110 0000 0000 0000 0000 0000 0000 0000 + rc |= dmaMode << 29; + + // 1000 0000 0000 0000 0000 0000 0000 0000 + + if (manager.getInterlaceField()) + rc |= 0x80000000; //for interlace + + // The poll detection code does not always work, so as a temporary workaround, add another backstop here to catch + // vsync timeouts that never end + if (0 != (displayMode & 0x0040)) { + if (++pollHackStatusReadCount >= 1000) { + _poll(ADDR_GPU_CTRLSTATUS,4); + } + } else { + if (++pollHackStatusReadCount >= 1000000) { + // TonyHawk is still rarely (possibly race) waiting for this to change even in non interlace mode. + // If something is waiting forever, this will at least wake it up + manager.toggleInterlaceField(); + pollHackStatusReadCount = 0; + } + } + + return rc; + } + + static int pollHackStatusReadCount; + + public void aboutToBlock() { + manager.preAsync(); + } + + public void poll(int address, int size) { + _poll(address, size); + } + + protected static void _poll(int address, int size) { + pollHackStatusReadCount = 0; + assert address == ADDR_GPU_CTRLSTATUS; + if (0 != (displayMode & 0x0040)) { + //System.out.println("flicking interlace because of 1814 poll in interlaced mode"); + manager.toggleInterlaceField(); + } + // note, this may not actually update anything... it will update anything if the mode has + // changed, or someone has dirtied the visible display + manager.vsync(); + } + + public static int gpuDataRead32(int address) { + videoRAM = display.acquireDisplayBuffer(); + try { + // used if we're doing vram to mem... these will + // return 0 if we're not currently doing a vram to mem + return readPixel() + (readPixel() << 16); +// return (readPixel()<<16)+readPixel(); + } finally { + display.releaseDisplayBuffer(); + videoRAM = null; + } + } + + private static class GPUDMAChannel extends DMAChannelOwnerBase { + public final int getDMAChannel() { + return DMAController.DMA_GPU; + } + + public final String getName() { + return "GPU"; + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if ((ctrl & 0x200) != 0) { + int size = blocks * blockSize; // in dwords + if (debugTransfers) System.out.println("*** LINEAR GPU DMA FROM VRAM *** size=" + (size * 4)); + try { + addressSpace.resolve(base, size * 4, true, m_resolveResult); + if (m_resolveResult.mem != null) { + videoRAM = display.acquireDisplayBuffer(); + try { + // todo, do this more efficiently + int end = m_resolveResult.offset + size; + for (int i = m_resolveResult.offset; i < end; i++) { + //m_resolveResult.mem[i] = (readPixel()<<16)+readPixel(); + m_resolveResult.mem[i] = readPixel() + (readPixel() << 16); + } + } finally { + display.releaseDisplayBuffer(); + videoRAM = null; + } + } + } finally { + signalTransferComplete(); + } + } else { + throw new IllegalStateException("not implemented"); + } + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + try { + if (ignoreGPU) { + debuggo(); + return; + } + if ((ctrl & 0x200) != 0) { + if (debugTransfers) System.out.println("*** LINEAR GPU DMA ***"); + // linear DMA + //LOG3P( GPU_COMMAND, "Linear DMA %08x %04x * %04x\n", base, blocks, blockSize); + //uint32 size = blocks*blockSize; + //uint32 *addr = (uint32 *)m_gpu->getAddressSpace()->resolve( base, size*4); + // TODO check alignment + //if (addr) { + // m_gpu->handleGPUData( addr, size); + //} + int size = blocks * blockSize; + addressSpace.resolve(base, size, false, m_resolveResult); + if (m_resolveResult.mem != null) { + videoRAM = display.acquireDisplayBuffer(); + try { + handleGPUData(m_resolveResult.mem, m_resolveResult.offset, size); + } finally { + display.releaseDisplayBuffer(); + videoRAM = null; + } + } + } else if ((ctrl & 0x400) != 0) { + if (debugTransfers) System.out.println("*** LINKED LIST GPU DMA ***"); + // linked list DMA + // TODO check alignment + //int timeBefore = MTScheduler.getTime(); + videoRAM = display.acquireDisplayBuffer(); + try { + handleGPUDataChain(base); + } finally { + display.releaseDisplayBuffer(); + videoRAM = null; + } + //System.out.println("chain time "+((MTScheduler.getTime()-timeBefore)>>4)); + } + // TODO for now only + } finally { + signalTransferComplete(); + } + } + } + + private static class OTCDMAChannel extends DMAChannelOwnerBase { + public final int getDMAChannel() { + return DMAController.DMA_GPU_OTC; + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if (ctrl == 0x11000002) { + int count = blockSize; + + // we know that linked list must be in main RAM, + // since addresses are only 24 bits. + + // todo clamp this to ram size? + base &= 0xffffff; + int end = base >> 2; + int addr = end - count + 1; + int[] mainRAM = addressSpace.getMainRAM(); + mainRAM[addr] = 0x00ffffff; + while (addr < end) { + int tmp = addr; + mainRAM[++addr] = (tmp << 2); + } + + } + signalTransferComplete(); + } + + + public final String getName() { + return "GPU OTClear"; + } + } + + public static void gpusReset(int val) { + //System.out.println("GPUS RESET"); + gpusSetDispEnable(1); + gpusSetDisplayMode(0); + gpusSetDisplayOrigin(0); + maskMode = 0; + m_gpudState = GPUD_CMD_NONE; + // todo, check this sets status to 14802000 + } + + private static void gpusCmdReset(int val) { + //System.out.println("GPUS CMD RESET"); + m_gpudState = GPUD_CMD_NONE; + } + + private static void gpusIRQReset(int val) { + //System.out.println("GPUS IRQ RESET"); + } + + private static void gpusSetDispEnable(int val) { + m_displayEnabled = ((val & 1) == 0) ? true : false; + manager.setBlanked(!m_displayEnabled); + //System.out.println("GPUS SET DISP ENABLE "+m_displayEnabled); + } + + private static void gpusSetDataTransferMode(int val) { + dmaMode = val & 3; + //System.out.println("GPUS SET DATA TRANSFER MODE "+m_dmaMode); + } + + private static void gpusSetDisplayOrigin(int val) { + int originX = val & 0x3ff; + int originY = (val >> 10) & 0x1ff; + manager.setOrigin(originX, originY); + } + + private static void gpusSetMonitorLeftRight(int val) { + int l = val & 0xfff; + int r = (val >> 12) & 0xfff; + manager.setHorizontalTiming(l, r); + } + + private static void gpusSetMonitorTopBottom(int val) { + int t = val & 0x3ff; + int b = (val >> 10) & 0x3ff; + manager.setVerticalTiming(t, b); + } + + private static void gpusSetDisplayMode(int val) { + displayMode = ((val & 0x3f) << 1) | ((val & 0x40 >> 6)); + + boolean doubleY = 0 != (val & 0x4); + boolean pal = 0 != (val & 8); + boolean rgb24 = 0 != (val & 0x10); + boolean interlace = 0 != (val & 0x20); + int divider = 8; + + // int isMystery = !!(data&0x80); + switch (val & 0x43) { + case 0: + divider = 10; + break; + case 1: + divider = 8; + break; + case 2: + divider = 5; + break; + case 3: + divider = 4; + break; + case 0x40: + divider = 7; + break; + } + if (dumpGPUD) { + System.out.println("begin set display mode: div="+divider+" depth="+((rgb24)?24:16)+" intl="+interlace+" dbly="+doubleY+" pal="+pal); + } + manager.setPixelDivider(divider); + manager.setRGB24(rgb24); + manager.setInterlaced(interlace); + manager.setDoubleY(doubleY); + manager.setNTSC(!pal); + if (dumpGPUD) { + System.out.println("end set display mode"); + } + } + + private static void gpusRequestInfo(int val) { + val &= 0xffffffL; + switch (val) { + case 3: + //LOG( GPU_COMMAND, "gpusRequestInfo - 3 old top left\n"); + //_gpu_data = 0; + break; + case 4: + //LOG( GPU_COMMAND, "gpusRequestInfo - 4 old bottom right\n"); + //_gpu_data = 0xffffffff; + break; + case 5: + //LOG( GPU_COMMAND, "gpusRequestInfo - 5 draw offset\n"); + //_gpu_data = 0x0; + break; + case 7: + //System.out.println( "GET CPU VERSION" ); + addressSpace.internalWrite32(ADDR_GPU_DATA, 2); + break; + default: + //LOG1P( GPU_COMMAND, "gpusRequestInfo - %d (unknown)\n", data); + break; + } + } + +/* + private static void handleGPUData( int[] mem, int offset, int size) + { + while (size>0) { + if (m_gpudState == GPUD_EXTRA_COMMAND_DATA) { +// ASSERT( SANITY_CHECK, m_currentGPUDFunction!=0, ""); + int dwordsUsed = handleGPUDFunction( mem, offset, size); +// ASSERT( SANITY_CHECK, dwordsUsed<=size, ""); + offset+=dwordsUsed; + size-=dwordsUsed; + } else { + // TODO do better than this later + gpuDataWrite32Internal( ADDR_GPU_DATA, mem[offset]); + offset++; + size--; + } + } + } + */ + + private static void handleGPUData(int[] mem, int offset, int size) { + int origOffset = offset; + if (debugTransfers) System.out.println("HandleGPUData " + size + " dwords"); + while (size > 0) { + switch (m_gpudState) { + case GPUD_CMD_NONE: + m_gpudCommand = (mem[offset] >> 24) & 0xff; + if (debugTransfers) + System.out.println("New command at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); + int count = m_gpudFunctionArgumentCount[m_gpudCommand]; + if (size >= count) { + GPUDRouter.invoke(mem, offset, count); + offset += count; + size -= count; + } else { + // use cmdBuffer for filling + for (int i = 0; i < size; i++) { + m_cmdBuffer[i++] = mem[offset++]; + } + cmdBufferUsed = size; + cmdBufferTarget = count; + m_gpudState = GPUD_CMD_EXTRA; + size = 0; + } + break; + case GPUD_CMD_FILLING: + if (debugTransfers) + System.out.println("Next byte main command data at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); + m_cmdBuffer[cmdBufferUsed++] = mem[offset++]; + size--; + if (cmdBufferUsed == cmdBufferTarget) { + m_gpudState = GPUD_CMD_NONE; + GPUDRouter.invoke(m_cmdBuffer, 0, cmdBufferUsed); + } + break; + case GPUD_CMD_EXTRA: + if (debugTransfers) + System.out.println("extra command data at " + (offset - origOffset) + ": " + MiscUtil.toHex(m_gpudCommand, 2)); + int dwordsUsed = GPUDRouter.invoke(mem, offset, size); + assert (dwordsUsed <= size); + if (debugTransfers) System.out.println("consumed " + dwordsUsed); + size -= dwordsUsed; + offset += dwordsUsed; + break; + } + } + } + + private static AddressSpace.ResolveResult m_resolveResult = new AddressSpace.ResolveResult(); + + private static void handleGPUDataChain(int address) { + address &= 0xffffff; + int[] mainRAM = addressSpace.getMainRAM(); + while (address < AddressSpace.RAM_SIZE) { + int head = mainRAM[address >> 2]; + //System.out.println("HEAD "+MiscUtil.toHex( head, 8)); + int count = (head >> 24) & 0xff; + if (count > 0) { + handleGPUData(mainRAM, (address >> 2) + 1, count); + } + address = head & 0xffffff; + // TODO: maybe a temp thing + if ((address & 0xffffff) == 0) + break; + } + } + + public static final int makePixel(int val) { + // todo inline this + return makePixel((val & 0x1f) << 3, (val & 0x3e0) >> 2, (val & 0x7c00) >> 7, (val & 0x8000) >> 15); + } + + public static final int makePixel(int r, int g, int b, int mask) { + return (r << 16) | (g << 8) | b | (mask << 24); + } + + public static final int unmakePixel(int pixel) { + return ((pixel & 0xf8) << 7) | ((pixel & 0xf800) >> 6) | ((pixel & 0xf80000) >> 19) | ((pixel & 0x1000000) >> 9); + } + + private static JavaClass m_TemplateTClass; + private static JavaClass m_TemplateLClass; + private static JavaClass m_TemplateSClass; + private static JavaClass m_TemplateQClass; + private static JavaClass m_TemplateRClass; + + private JavaClass getTemplateTClass() { + if (m_TemplateTClass == null) { + String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer.class"; + final URL url = getClass().getClassLoader().getResource(filename); + try { + InputStream stream = url.openStream(); + try { + m_TemplateTClass = (new ClassParser(stream, filename)).parse(); + } finally { + stream.close(); + } + } catch (IOException e) { + } + } + return m_TemplateTClass.copy(); + } + + private JavaClass getTemplateSClass() { + if (m_TemplateSClass == null) { + String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateSpriteRenderer.class"; + final URL url = getClass().getClassLoader().getResource(filename); + try { + InputStream stream = url.openStream(); + try { + m_TemplateSClass = (new ClassParser(stream, filename)).parse(); + } finally { + stream.close(); + } + } catch (IOException e) { + } + } + return m_TemplateSClass.copy(); + } + + private JavaClass getTemplateQClass() { + if (m_TemplateQClass == null) { + String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateQuadRenderer.class"; + final URL url = getClass().getClassLoader().getResource(filename); + try { + InputStream stream = url.openStream(); + try { + m_TemplateQClass = (new ClassParser(stream, filename)).parse(); + } finally { + stream.close(); + } + } catch (IOException e) { + } + } + return m_TemplateQClass.copy(); + } + + private JavaClass getTemplateRClass() { + if (m_TemplateRClass == null) { + String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateRectangleRenderer.class"; + final URL url = getClass().getClassLoader().getResource(filename); + try { + InputStream stream = url.openStream(); + try { + m_TemplateRClass = (new ClassParser(stream, filename)).parse(); + } finally { + stream.close(); + } + } catch (IOException e) { + } + } + return m_TemplateRClass.copy(); + } + + private JavaClass getTemplateLClass() { + if (m_TemplateLClass == null) { + String filename = "org/jpsx/runtime/components/hardware/gpu/GPU$TemplateLineRenderer.class"; + final URL url = getClass().getClassLoader().getResource(filename); + try { + InputStream stream = url.openStream(); + try { + m_TemplateLClass = (new ClassParser(stream, filename)).parse(); + } finally { + stream.close(); + } + } catch (IOException e) { + } + } + return m_TemplateLClass.copy(); + } + + // _T + // 0 no tex + // 4 4bit tex + // 8 8bit tex + // 6 16bit tex + // 0 non gouraud + // 1 gouraud + // 0 non-semi + // 1 5 plus 5 + // 2 10 plus 10 + // 3 10 minus 10 + // 4 10 plus 25 + // 0 no mask set + // 1 mask set + // 0 no mask check + // 1 mask check + // 0 non solid + // 1 solid + // TODO replace other occurences of field with their value + public ClassGen generateClass(String classname) { + ClassGen cgen; + String suffix = classname.substring(classname.indexOf("$_") + 2); + if (suffix.charAt(0) == 'T' || suffix.charAt(0) == 'L' || suffix.charAt(0) == 'S' || suffix.charAt(0) == 'Q' || suffix.charAt(0) == 'R') { + int targetTextureType; + switch (suffix.charAt(1)) { + case'0': + targetTextureType = TEXTURE_NONE; + break; + case'4': + targetTextureType = TEXTURE_4BIT; + break; + case'8': + targetTextureType = TEXTURE_8BIT; + break; + case'6': + targetTextureType = TEXTURE_16BIT; + break; + case'5': + targetTextureType = TEXTURE_4BITW; + break; + case'9': + targetTextureType = TEXTURE_8BITW; + break; + case'7': + targetTextureType = TEXTURE_16BITW; + break; + default: + throw new IllegalStateException("Unknown texture type " + suffix.charAt(1)); + } + boolean targetGouraud; + switch (suffix.charAt(2)) { + case'0': + targetGouraud = false; + break; + case'1': + targetGouraud = true; + break; + default: + throw new IllegalStateException("Unknown gouraud flag " + suffix.charAt(2)); + } + int targetSemi; + switch (suffix.charAt(3)) { + case'0': + targetSemi = SEMI_NONE; + break; + case'1': + targetSemi = SEMI_5P5; + break; + case'2': + targetSemi = SEMI_10P10; + break; + case'3': + targetSemi = SEMI_10M10; + break; + case'4': + targetSemi = SEMI_10P25; + break; + default: + throw new IllegalStateException("Unknown semi flag " + suffix.charAt(3)); + } + boolean targetMaskSet; + switch (suffix.charAt(4)) { + case'0': + targetMaskSet = false; + break; + case'1': + targetMaskSet = true; + break; + default: + throw new IllegalStateException("Unknown mask set flag " + suffix.charAt(4)); + } + boolean targetMaskCheck; + switch (suffix.charAt(5)) { + case'0': + targetMaskCheck = false; + break; + case'1': + targetMaskCheck = true; + break; + default: + throw new IllegalStateException("Unknown mask check flag " + suffix.charAt(5)); + } + boolean targetSolid; + switch (suffix.charAt(6)) { + case'0': + targetSolid = false; + break; + case'1': + targetSolid = true; + break; + default: + throw new IllegalStateException("Unknown solid flag " + suffix.charAt(6)); + } + + JavaClass jclass; + if (suffix.charAt(0) == 'T') { + jclass = getTemplateTClass(); + } else if (suffix.charAt(0) == 'L') { + jclass = getTemplateLClass(); + } else if (suffix.charAt(0) == 'S') { + jclass = getTemplateSClass(); + } else if (suffix.charAt(0) == 'R') { + jclass = getTemplateRClass(); + } else { + jclass = getTemplateQClass(); + } + String origClassName = jclass.getClassName(); + jclass.setFileName(JPSXClassLoader.getClassFilename(classname)); + cgen = new ClassGen(jclass); + ConstantPoolGen cp = cgen.getConstantPool(); + + // note for some reason this messes up jad + cgen.setClassName(classname); + if (suffix.charAt(0) == 'Q') { + int utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer"); + cp.setConstant(utfIndex, new ConstantUtf8(classname.replace('Q', 'T').replace('.', '/'))); + utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateRectangleRenderer"); + cp.setConstant(utfIndex, new ConstantUtf8(classname.replace('Q', 'R').replace('.', '/'))); + } else { + // replace the string constant itself + //int utfIndex = cp.lookupUtf8("org/jpsx/runtime/components/hardware/gpu/GPU$TemplateTriangleRenderer"); + //cp.setConstant( utfIndex, new ConstantUtf8( classname.replace('.','/'))); + + + Field field = cgen.containsField("_renderTextureType"); + FieldGen fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetTextureType); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderSemiType"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetSemi); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderBReg"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetGouraud && (targetTextureType != TEXTURE_NONE)); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderGouraud"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetGouraud); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderCheckMask"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetMaskCheck); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderSetMask"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetMaskSet); + cgen.replaceField(field, fg.getField()); + + field = cgen.containsField("_renderSolid"); + fg = new FieldGen(field, cp); + fg.isFinal(true); + fg.cancelInitValue(); + fg.setInitValue(targetSolid); + cgen.replaceField(field, fg.getField()); + } + + // replace the class constant for the original class with our one, since it is used + // in GETSTATIC methods + cp.setConstant(cp.lookupClass(origClassName), cp.getConstant(cp.lookupClass(classname))); + return cgen; + } + throw new IllegalStateException("Unknown inner class to generate " + classname); + } + + // 0000 tiim rrrr rrrr gggg gggg bbbb bbbb + + public static void setVRAMFormat(boolean rgb24) { + if (!rgb24conversion) return; + if (rgb24 != GPU.rgb24) { + //System.out.println( "Convert VRAM to " + ((rgb24) ? "24 bit" : "15 bit") ); + GPU.rgb24 = rgb24; + int[] ram = display.acquireDisplayBuffer(); + if (rgb24) { + // G0B0 B1R0 R1G1 + // to: + // A_R0G0B0 B_R0G0B1 C_R1G1B1 + int last = 0; + for (int i = 0; i < 1024 * 512; i++) { + int pixel = ram[i]; + switch (pixel & GPU_RGBXX_X_MASK) { + case GPU_RGB15_A: { + int decoded = unmakePixel(pixel); + int decoded2 = unmakePixel(ram[i + 1]); + ram[i] = GPU_RGB24_A | decoded | ((decoded2 & 0xff) << 16); + last = decoded; + break; + } + case GPU_RGB15_B: { + int decoded = unmakePixel(pixel); + int pp = last | ((decoded & 0xff) << 16); + ram[i] = GPU_RGB24_B | (pp & 0xffff00) | ((decoded >> 8) & 0xff); + last = decoded; + break; + } + case GPU_RGB15_C: { + int decoded = unmakePixel(pixel); + ram[i] = GPU_RGB24_C | (decoded << 8) | ((last >> 8) & 0xff); + break; + } + } + } + } else { + // A_R0G0B0 B_R0G0B1 C_R1G1B1 + // to: + // G0B0 B1R0 R1G1 + for (int i = 0; i < 1024 * 512; i++) { + int pixel = ram[i]; + switch (pixel & GPU_RGBXX_X_MASK) { + case GPU_RGB24_A: { + ram[i] = GPU_RGB15_A | makePixel((pixel & 0xffff)); + break; + } + case GPU_RGB24_B: { + ram[i] = GPU_RGB15_B | makePixel(((pixel & 0xff) << 8) | ((pixel >> 16) & 0xff)); + break; + } + case GPU_RGB24_C: { + ram[i] = GPU_RGB15_C | makePixel(((pixel >> 8) & 0xffff)); + break; + } + } + } + } + display.releaseDisplayBuffer(); + } + } + + // Temporary hack to show stuff that is missing - we shoud do this with a system wide log4j channel + static int maxMissing = 10; + private static void missing(String s) { + if (maxMissing > 0) { + maxMissing --; + System.out.println("Missing "+s); + } + } +} + + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java new file mode 100644 index 0000000..78a14e2 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java @@ -0,0 +1,5599 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */package org.jpsx.runtime.components.hardware.gpu; + +/** + * Placeholder class enclosing rendering classes that are dynamically generated as needed at runtime. + * + * Each class represents a (quad/triangle/line/sprite) representer with one set of rendering options (e.g. + * palette size, semi-transparency, gouraud-ness, masking etc.) + * + * To save space the compiled class files are actually deleted by the build + */ +public class GPUGenerated { + + public static class _Q400000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q400111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q401111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q402111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q403111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q404111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q500111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q501111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q502111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q503111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q504111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q800111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q801111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q802111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q803111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q804111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q900111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q901111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q902111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q903111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q904111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q600000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q600010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q600100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q600110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q601000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q601010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q601100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q601110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q602000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q602010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q602100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q602110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q603000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q603010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q603100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q603110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q604000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q604010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q604100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q604110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q700000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q700010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q700100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q700110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q701000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q701010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q701100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q701110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q702000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q702010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q702100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q702110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q703000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q703010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q703100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q703110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q704000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q704010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q704100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q704110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q410111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q411111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q412111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q413111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q414111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q510111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q511111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q512111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q513111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q514111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q810111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q811111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q812111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q813111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q814111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q910111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q911111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q912111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q913111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q914111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q610000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q610010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q610100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q610110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q611000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q611010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q611100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q611110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q612000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q612010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q612100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q612110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q613000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q613010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q613100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q613110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q614000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q614010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q614100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q614110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q710000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q710010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q710100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q710110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q711000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q711010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q711100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q711110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q712000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q712010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q712100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q712110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q713000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q713010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q713100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q713110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q714000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q714010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q714100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q714110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q000000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q000010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q000100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q000110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q001000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q001010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q001100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q001110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q002000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q002010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q002100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q002110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q003000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q003010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q003100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q003110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q004000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q004010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q004100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q004110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q010000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q011000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q012000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q013000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _Q014000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2, GPU.Vertex v3) { + } + } + + public static class _T010001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T010011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T010101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T010111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T400111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T401111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T402111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T403111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T404111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T410111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T411111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T412111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T413111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T414111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T500111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T501111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T502111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T503111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T504111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T510111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T511111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T512111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T513111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T514111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T000000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T000010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T000100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T000110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T001000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T001010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T001100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T001110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T002000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T002010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T002100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T002110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T003000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T003010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T003100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T003110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T004000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T004010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T004100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T004110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T010000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T011000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T012000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T013000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T014000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T800111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T801111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T802111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T803111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T804111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T810111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T811111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T812111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T813111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T814111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T900111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T901111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T902111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T903111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T904111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T910111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T911111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T912111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T913111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914001 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914011 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914101 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T914111 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T600000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T600010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T600100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T600110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T601000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T601010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T601100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T601110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T602000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T602010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T602100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T602110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T603000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T603010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T603100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T603110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T604000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T604010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T604100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T604110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T610000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T610010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T610100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T610110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T611000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T611010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T611100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T611110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T612000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T612010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T612100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T612110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T613000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T613010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T613100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T613110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T614000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T614010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T614100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T614110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T700000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T700010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T700100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T700110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T701000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T701010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T701100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T701110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T702000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T702010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T702100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T702110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T703000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T703010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T703100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T703110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T704000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T704010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T704100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T704110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T710000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T710010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T710100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T710110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T711000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T711010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T711100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T711110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T712000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T712010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T712100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T712110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T713000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T713010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T713100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T713110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T714000 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T714010 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T714100 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _T714110 { + public static void render(GPU.PolygonRenderInfo info, GPU.Vertex v0, GPU.Vertex v1, GPU.Vertex v2) { + } + } + + public static class _S000000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S000010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S000100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S000110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S001000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S001010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S001100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S001110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S002000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S002010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S002100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S002110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S003000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S003010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S003100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S003110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S004000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S004010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S004100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S004110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S400111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S401111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S402111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S403111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S404111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S500111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S501111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S502111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S503111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S504111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S800111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S801111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S802111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S803111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S804111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S900111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S901111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S902111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S903111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904001 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904011 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904101 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S904111 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S600000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S600010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S600100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S600110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S601000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S601010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S601100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S601110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S602000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S602010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S602100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S602110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S603000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S603010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S603100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S603110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S604000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S604010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S604100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S604110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S700000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S700010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S700100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S700110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S701000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S701010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S701100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S701110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S702000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S702010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S702100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S702110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S703000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S703010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S703100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S703110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S704000 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S704010 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S704100 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _S704110 { + public static void render(GPU.PolygonRenderInfo info, int x, int y, int w, int h) { + } + } + + public static class _L010000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L010010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L010100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L010110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L000000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L000010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L000100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L000110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L001000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L001010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L001100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L001110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L002000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L002010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L002100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L002110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L003000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L003010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L003100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L003110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L004000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L004010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L004100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L004110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L011000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L011010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L011100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L011110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L012000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L012010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L012100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L012110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L013000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L013010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L013100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L013110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L014000 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L014010 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L014100 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } + + public static class _L014110 { + public static void render(GPU.LineRenderInfo info, GPU.Vertex v0, GPU.Vertex v1) { + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gte/GTE.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gte/GTE.java new file mode 100644 index 0000000..5cb7d56 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/gte/GTE.java @@ -0,0 +1,3585 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.gte; + +import org.apache.bcel.generic.*; +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.*; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.util.ClassUtil; +import org.jpsx.runtime.util.MiscUtil; + +// TODO should vz be 16 bits only when read? + +public final class GTE extends JPSXComponent implements InstructionProvider { + private static final boolean debugLimit = false; + private static final boolean debugLimitB = false; + private static final boolean debugLimitG = false; + private static final boolean debugLimitD = false; + private static final Logger log = Logger.getLogger("GTE"); + private static final String CLASS = GTE.class.getName(); + private static final String VECTOR_CLASS = Vector.class.getName(); + private static final String VECTOR_SIGNATURE = ClassUtil.signatureOfClass(VECTOR_CLASS); + private static final String MATRIX_CLASS = Matrix.class.getName(); + private static final String MATRIX_SIGNATURE = ClassUtil.signatureOfClass(MATRIX_CLASS); + + private static final int R_VXY0 = 0; + private static final int R_VZ0 = 1; + private static final int R_VXY1 = 2; + private static final int R_VZ1 = 3; + private static final int R_VXY2 = 4; + private static final int R_VZ2 = 5; + private static final int R_RGB = 6; + private static final int R_OTZ = 7; + private static final int R_IR0 = 8; + private static final int R_IR1 = 9; + private static final int R_IR2 = 10; + private static final int R_IR3 = 11; + private static final int R_SXY0 = 12; + private static final int R_SXY1 = 13; + private static final int R_SXY2 = 14; + private static final int R_SXYP = 15; + private static final int R_SZX = 16; + private static final int R_SZ0 = 17; + private static final int R_SZ1 = 18; + private static final int R_SZ2 = 19; + private static final int R_RGB0 = 20; + private static final int R_RGB1 = 21; + private static final int R_RGB2 = 22; + private static final int R_RES1 = 23; + private static final int R_MAC0 = 24; + private static final int R_MAC1 = 25; + private static final int R_MAC2 = 26; + private static final int R_MAC3 = 27; + private static final int R_IRGB = 28; + private static final int R_ORGB = 29; + private static final int R_LZCS = 30; + private static final int R_LZCR = 31; + private static final int R_R11R12 = 32; + private static final int R_R13R21 = 33; + private static final int R_R22R23 = 34; + private static final int R_R31R32 = 35; + private static final int R_R33 = 36; + private static final int R_TRX = 37; + private static final int R_TRY = 38; + private static final int R_TRZ = 39; + private static final int R_L11L12 = 40; + private static final int R_L13L21 = 41; + private static final int R_L22L23 = 42; + private static final int R_L31L32 = 43; + private static final int R_L33 = 44; + private static final int R_RBK = 45; + private static final int R_GBK = 46; + private static final int R_BBK = 47; + private static final int R_LR1LR2 = 48; + private static final int R_LR3LG1 = 49; + private static final int R_LG2LG3 = 50; + private static final int R_LB1LB2 = 51; + private static final int R_LB3 = 52; + private static final int R_RFC = 53; + private static final int R_GFC = 54; + private static final int R_BFC = 55; + private static final int R_OFX = 56; + private static final int R_OFY = 57; + private static final int R_H = 58; + private static final int R_DQA = 59; + private static final int R_DQB = 60; + private static final int R_ZSF3 = 61; + private static final int R_ZSF4 = 62; + private static final int R_FLAG = 63; + + private static final int GTE_SF_MASK = 0x80000; + + private static final int GTE_MX_MASK = 0x60000; + private static final int GTE_MX_ROTATION = 0x00000; + private static final int GTE_MX_LIGHT = 0x20000; + private static final int GTE_MX_COLOR = 0x40000; + + private static final int GTE_V_MASK = 0x18000; + private static final int GTE_V_V0 = 0x00000; + private static final int GTE_V_V1 = 0x08000; + private static final int GTE_V_V2 = 0x10000; + private static final int GTE_V_IR = 0x18000; + + private static final int GTE_CV_MASK = 0x06000; + private static final int GTE_CV_TR = 0x00000; + private static final int GTE_CV_BK = 0x02000; + private static final int GTE_CV_FC = 0x04000; + private static final int GTE_CV_NONE = 0x06000; + + private static final int GTE_LM_MASK = 0x00400; + + private static final int GTE_ALL_MASKS = (GTE_SF_MASK | GTE_MX_MASK | GTE_V_MASK | GTE_CV_MASK | GTE_LM_MASK); + +// public static void setFlag( int bits) +// { +// reg_flag |= bits; +// +// // TODO check these flags! +// // CHK is set if any flag in 0x7FC7E000 is set +// // (A1-A3 B1-B3 D E FP FN G1 G2) +// +// if (0!=(bits & 0x7fc7e000)) { +// reg_flag|=FLAG_CHK; +// } +// } + +// removed above, and rolled FLAG_CHK into them automatically + + private static final int FLAG_CHK = 0x80000000; + private static final int FLAG_A1P = 0x40000000 | FLAG_CHK; + private static final int FLAG_A2P = 0x20000000 | FLAG_CHK; + private static final int FLAG_A3P = 0x10000000 | FLAG_CHK; + private static final int FLAG_A1N = 0x08000000 | FLAG_CHK; + private static final int FLAG_A2N = 0x04000000 | FLAG_CHK; + private static final int FLAG_A3N = 0x02000000 | FLAG_CHK; + private static final int FLAG_B1 = 0x01000000 | FLAG_CHK; + private static final int FLAG_B2 = 0x00800000 | FLAG_CHK; + private static final int FLAG_B3 = 0x00400000; + private static final int FLAG_C1 = 0x00200000; + private static final int FLAG_C2 = 0x00100000; + private static final int FLAG_C3 = 0x00080000; + private static final int FLAG_D = 0x00040000 | FLAG_CHK; + private static final int FLAG_E = 0x00020000 | FLAG_CHK; + private static final int FLAG_FP = 0x00010000 | FLAG_CHK; + private static final int FLAG_FN = 0x00008000 | FLAG_CHK; + private static final int FLAG_G1 = 0x00004000 | FLAG_CHK; + private static final int FLAG_G2 = 0x00002000 | FLAG_CHK; + private static final int FLAG_H = 0x00001000; + + private static final long BIT43 = 0x80000000000L; + private static final long BIT31 = 0x80000000L; + private static final long BIT47 = 0x800000000000L; + + public static class Vector { + public int x, y, z; + } + + public static class Matrix { + public int m11, m12, m13, m21, m22, m23, m31, m32, m33; + } + + /** + * Note with respect to internal registers that aren't signed 32 bit values on the playstation: + * + * All internal registers here are kept as signed 32 bit values. If the actual register on PSX is say a 16 bit signed value + * it is sign extended to 32 bits as part of the register write. If it is a 16 bit unsigned value, it is zero extended to 32 bits as + * part of the register write. + * + * Equally the reverse is done when reading GTE regs (i.e. a signed 32 bit internal value may only have 16 bits exposed) + */ + + public static Vector reg_v0 = new Vector(); + public static Vector reg_v1 = new Vector(); + public static Vector reg_v2 = new Vector(); + + public static int reg_rgb; + public static int reg_otz; + + public static int reg_ir0; + public static int reg_ir1; + public static int reg_ir2; + public static int reg_ir3; + + public static int reg_sx0; // checked + public static int reg_sy0; // checked + public static int reg_sx1; // checked + public static int reg_sy1; // checked + public static int reg_sx2; // checked + public static int reg_sy2; // checked + public static int reg_sxp; // checked + public static int reg_syp; // checked + + public static int reg_szx; // checked + public static int reg_sz0; // checked + public static int reg_sz1; // checked + public static int reg_sz2; // checked + public static int reg_rgb0; + public static int reg_rgb1; + public static int reg_rgb2; + public static int reg_res1; + public static int reg_mac0; + public static int reg_mac1; + public static int reg_mac2; + public static int reg_mac3; +// public static int reg_irgb; // checked +// public static int reg_orgb; // checked + public static int reg_lzcr; // checked + public static int reg_lzcs; // checked + + public static Matrix reg_rot = new Matrix(); + + public static int reg_trx; + public static int reg_try; + public static int reg_trz; + + public static Matrix reg_ls = new Matrix(); + public static int reg_rbk; + public static int reg_gbk; + public static int reg_bbk; + + public static Matrix reg_lc = new Matrix(); + public static int reg_rfc; + public static int reg_gfc; + public static int reg_bfc; + + public static int reg_ofx; + public static int reg_ofy; + public static int reg_h; + public static int reg_dqa; + public static int reg_dqb; + + public static int reg_zsf3; + public static int reg_zsf4; + public static int reg_flag; + + public GTE() { + super("JPSX Geometry Transform Engine"); + } + + private static AddressSpace addressSpace; + private static R3000 r3000; + private static int[] r3000regs; + + private static void emitReadReg(InstructionList il, CompilationContext context, int reg) { + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (reg < 32) { + switch (reg) { + case R_VXY0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_VZ0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_VXY1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_VZ1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_VXY2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_VZ2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_RGB: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb", "I"))); + break; + case R_OTZ: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_otz", "I"))); + break; + case R_IR0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir0", "I"))); + break; + case R_IR1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir1", "I"))); + break; + case R_IR2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir2", "I"))); + break; + case R_IR3: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir3", "I"))); + break; + case R_SXY0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx0", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy0", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_SXY1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx1", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy1", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_SXY2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx2", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy2", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_SXYP: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sxp", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_syp", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_SZX: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_szx", "I"))); + break; + case R_SZ0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz0", "I"))); + break; + case R_SZ1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz1", "I"))); + break; + case R_SZ2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz2", "I"))); + break; + case R_RGB0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb0", "I"))); + break; + case R_RGB1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb1", "I"))); + break; + case R_RGB2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb2", "I"))); + break; + case R_RES1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_res1", "I"))); + break; + case R_MAC0: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac0", "I"))); + break; + case R_MAC1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac1", "I"))); + break; + case R_MAC2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac2", "I"))); + break; + case R_MAC3: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac3", "I"))); + break; + case R_IRGB: + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "readIORGB", "()V"))); + break; + case R_ORGB: + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "readIORGB", "()V"))); + break; + case R_LZCS: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lzcs", "I"))); + break; + case R_LZCR: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lzcr", "I"))); + break; + } + } else { + switch (reg) { + case R_R11R12: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_R13R21: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_R22R23: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_R31R32: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_R33: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + break; + case R_TRX: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trx", "I"))); + break; + case R_TRY: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_try", "I"))); + break; + case R_TRZ: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trz", "I"))); + break; + case R_L11L12: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_L13L21: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_L22L23: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_L31L32: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_L33: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + break; + case R_RBK: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rbk", "I"))); + break; + case R_GBK: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gbk", "I"))); + break; + case R_BBK: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bbk", "I"))); + break; + case R_LR1LR2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_LR3LG1: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_LG2LG3: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_LB1LB2: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new IOR()); + break; + case R_LB3: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new GETFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + break; + case R_RFC: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rfc", "I"))); + break; + case R_GFC: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gfc", "I"))); + break; + case R_BFC: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bfc", "I"))); + break; + case R_OFX: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofx", "I"))); + break; + case R_OFY: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofy", "I"))); + break; + case R_H: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_h", "I"))); + // this is according to docs that it is accidentally sign extended + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + break; + case R_DQA: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqa", "I"))); + break; + case R_DQB: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqb", "I"))); + break; + case R_ZSF3: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf3", "I"))); + break; + case R_ZSF4: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf4", "I"))); + break; + case R_FLAG: + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_flag", "I"))); + break; + } + } + } + + private static void emitWriteReg(InstructionList il, CompilationContext context, int reg) { + ConstantPoolGen cp = context.getConstantPoolGen(); + int temp = context.getTempLocal(0); + + if (reg < 32) { + switch (reg) { + case R_VXY0: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + break; + case R_VZ0: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v0", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_VXY1: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + break; + case R_VZ1: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v1", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_VXY2: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "x", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "y", "I"))); + break; + case R_VZ2: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_v2", VECTOR_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(VECTOR_CLASS, "z", "I"))); + break; + case R_RGB: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb", "I"))); + break; + case R_OTZ: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_otz", "I"))); + break; + case R_IR0: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir0", "I"))); + break; + case R_IR1: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir1", "I"))); + break; + case R_IR2: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir2", "I"))); + break; + case R_IR3: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ir3", "I"))); + break; + case R_SXY0: + il.append(new ISTORE(temp)); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx0", "I"))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy0", "I"))); + break; + case R_SXY1: + il.append(new ISTORE(temp)); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx1", "I"))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy1", "I"))); + break; + case R_SXY2: + il.append(new ISTORE(temp)); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sx2", "I"))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sy2", "I"))); + break; + case R_SZX: + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_szx", "I"))); + break; + case R_SZ0: + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz0", "I"))); + break; + case R_SZ1: + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz1", "I"))); + break; + case R_SZ2: + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_sz2", "I"))); + break; + case R_RGB0: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb0", "I"))); + break; + case R_RGB1: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb1", "I"))); + break; + case R_RGB2: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rgb2", "I"))); + break; + case R_RES1: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_res1", "I"))); + break; + case R_MAC0: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac0", "I"))); + break; + case R_MAC1: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac1", "I"))); + break; + case R_MAC2: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac2", "I"))); + break; + case R_MAC3: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_mac3", "I"))); + break; + case R_IRGB: + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeIRGB", "(I)V"))); + break; + case R_ORGB: + il.append(new POP()); // read only + break; + case R_LZCR: + il.append(new POP()); // read only + break; +// case R_LZCS: +// fall thru for writeRegister +// case R_SXYP: +// fall thru for writeRegister + default: + il.append(new ISTORE(temp)); + il.append(new PUSH(cp, reg)); + il.append(new ILOAD(temp)); +// il.append(new PUSH(cp, reg)); +// il.append(new SWAP()); + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeRegister", "(II)V"))); + break; + } + } else { + switch (reg) { + case R_R11R12: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + break; + case R_R13R21: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + break; + case R_R22R23: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + break; + case R_R31R32: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + break; + case R_R33: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rot", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); + break; + case R_TRX: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trx", "I"))); + break; + case R_TRY: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_try", "I"))); + break; + case R_TRZ: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_trz", "I"))); + break; + case R_L11L12: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + break; + case R_L13L21: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + break; + case R_L22L23: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + break; + case R_L31L32: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + break; + case R_L33: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ls", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); + break; + case R_RBK: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rbk", "I"))); + break; + case R_GBK: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gbk", "I"))); + break; + case R_BBK: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bbk", "I"))); + break; + case R_LR1LR2: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m11", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m12", "I"))); + break; + case R_LR3LG1: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m13", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m21", "I"))); + break; + case R_LG2LG3: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m22", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m23", "I"))); + break; + case R_LB1LB2: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m31", "I"))); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m32", "I"))); + break; + case R_LB3: + il.append(new ISTORE(temp)); + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_lc", MATRIX_SIGNATURE))); + il.append(new ILOAD(temp)); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTFIELD(context.getConstantPoolGen().addFieldref(MATRIX_CLASS, "m33", "I"))); + break; + case R_RFC: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_rfc", "I"))); + break; + case R_GFC: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_gfc", "I"))); + break; + case R_BFC: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_bfc", "I"))); + break; + case R_OFX: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofx", "I"))); + break; + case R_OFY: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_ofy", "I"))); + break; + case R_H: + il.append(new PUSH(cp, 0xffff)); + il.append(new IAND()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_h", "I"))); + break; + case R_DQA: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqa", "I"))); + break; + case R_DQB: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_dqb", "I"))); + break; + case R_ZSF3: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf3", "I"))); + break; + case R_ZSF4: + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_zsf4", "I"))); + break; + case R_FLAG: + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(CLASS, "reg_flag", "I"))); + break; + default: + il.append(new ISTORE(temp)); + il.append(new PUSH(cp, reg)); + il.append(new ILOAD(temp)); + il.append(new INVOKESTATIC(cp.addMethodref(CLASS, "writeRegister", "(II)V"))); + break; + } + } + } + + public void init() { + super.init(); + CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + r3000 = CoreComponentConnections.R3000.resolve(); + r3000regs = r3000.getInterpreterRegs(); + } + + public void addInstructions(InstructionRegistrar registrar) { + log.info("Adding COP2 instructions..."); + i_mfc2 = new CPUInstruction("mfc2", GTE.class, 0, CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = R3000.Util.bits_rd(ci); + int rt = R3000.Util.bits_rt(ci); + + if (rt != 0) { + emitReadReg(il, context, rd); + context.emitSetReg(il, rt); + } + } + }; + i_cfc2 = new CPUInstruction("cfc2", GTE.class, 0, CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = R3000.Util.bits_rd(ci); + int rt = R3000.Util.bits_rt(ci); + + if (rt != 0) { + emitReadReg(il, context, rd + 32); + context.emitSetReg(il, rt); + } + } + }; + + i_mtc2 = new CPUInstruction("mtc2", GTE.class, 0, CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + emitWriteReg(il, context, rd); + } + }; + + i_ctc2 = new CPUInstruction("ctc2", GTE.class, 0, CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + emitWriteReg(il, context, rd + 32); + } + }; + i_lwc2 = new CPUInstruction("lwc2", GTE.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = R3000.Util.bits_rs(ci); + int rt = R3000.Util.bits_rt(ci); + int offset = R3000.Util.sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem32(il, context.getRegValue(base) + offset, false); + } else { + context.emitReadMem32(il, base, offset, false); + } + emitWriteReg(il, context, rt); + } + }; + i_swc2 = new CPUInstruction("swc2", GTE.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = R3000.Util.bits_rs(ci); + int rt = R3000.Util.bits_rt(ci); + int offset = R3000.Util.sign_extend(ci); + + InstructionList il2 = new InstructionList(); + emitReadReg(il2, context, rt); + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitWriteMem32(il, context.getRegValue(base) + offset, il2, false); + } else { + context.emitWriteMem32(il, base, offset, il2, false); + } + il2.dispose(); + } + }; + i_rtpt = new CPUInstruction("rtpt", GTE.class, 0, 0); + i_rtps = new CPUInstruction("rtps", GTE.class, 0, 0); + i_mvmva = new CPUInstruction("mvmva", GTE.class, 0, 0); + i_op = new CPUInstruction("op", GTE.class, 0, 0); + i_avsz3 = new CPUInstruction("avsz3", GTE.class, 0, 0); + i_avsz4 = new CPUInstruction("avsz4", GTE.class, 0, 0); + i_nclip = new CPUInstruction("nclip", GTE.class, 0, 0); + i_ncct = new CPUInstruction("ncct", GTE.class, 0, 0); + i_gpf = new CPUInstruction("gpf", GTE.class, 0, 0); + i_dcpl = new CPUInstruction("dcpl", GTE.class, 0, 0); + i_dpcs = new CPUInstruction("dpcs", GTE.class, 0, 0); + i_intpl = new CPUInstruction("intpl", GTE.class, 0, 0); + i_sqr = new CPUInstruction("sqr", GTE.class, 0, 0); + i_ncs = new CPUInstruction("ncs", GTE.class, 0, 0); + i_nct = new CPUInstruction("nct", GTE.class, 0, 0); + i_ncds = new CPUInstruction("ncds", GTE.class, 0, 0); + i_ncdt = new CPUInstruction("ncdt", GTE.class, 0, 0); + i_dpct = new CPUInstruction("dpct", GTE.class, 0, 0); + i_nccs = new CPUInstruction("nccs", GTE.class, 0, 0); + i_cdp = new CPUInstruction("cdp", GTE.class, 0, 0); + i_cc = new CPUInstruction("cc", GTE.class, 0, 0); + i_gpl = new CPUInstruction("gpl", GTE.class, 0, 0); + CPUInstruction i_cop2 = new CPUInstruction("cop2", GTE.class, 0, 0) { + public CPUInstruction subDecode(int ci) { + switch (R3000.Util.bits_rs(ci)) { + case 0: + return i_mfc2; + case 2: + return i_cfc2; + case 4: + return i_mtc2; + case 6: + return i_ctc2; + case 1: + case 3: + case 5: + case 7: + return r3000.getInvalidInstruction(); + } + switch (ci & 0x3f) { + case 0x01: + return i_rtps; + case 0x06: + return i_nclip; + case 0x0c: + return i_op; + case 0x10: + return i_dpcs; + case 0x11: + return i_intpl; + case 0x12: + return i_mvmva; + case 0x13: + return i_ncds; + case 0x14: + return i_cdp; + case 0x16: + return i_ncdt; + case 0x1b: + return i_nccs; + case 0x1c: + return i_cc; + case 0x1e: + return i_ncs; + case 0x20: + return i_nct; + case 0x28: + return i_sqr; + case 0x29: + return i_dcpl; + case 0x2a: + return i_dpct; + case 0x2d: + return i_avsz3; + case 0x2e: + return i_avsz4; + case 0x30: + return i_rtpt; + case 0x3d: + return i_gpf; + case 0x3e: + return i_gpl; + case 0x3f: + return i_ncct; + } + return r3000.getInvalidInstruction(); + } + }; + + registrar.setInstruction(18, i_cop2); + registrar.setInstruction(50, i_lwc2); + registrar.setInstruction(58, i_swc2); + } + + private static CPUInstruction i_mfc2; + private static CPUInstruction i_cfc2; + private static CPUInstruction i_mtc2; + private static CPUInstruction i_ctc2; + private static CPUInstruction i_lwc2; + private static CPUInstruction i_swc2; + private static CPUInstruction i_rtpt; + private static CPUInstruction i_rtps; + private static CPUInstruction i_mvmva; + private static CPUInstruction i_op; + private static CPUInstruction i_avsz3; + private static CPUInstruction i_avsz4; + private static CPUInstruction i_nclip; + private static CPUInstruction i_ncct; + private static CPUInstruction i_gpf; + private static CPUInstruction i_dcpl; + private static CPUInstruction i_dpcs; + private static CPUInstruction i_intpl; + private static CPUInstruction i_sqr; + private static CPUInstruction i_ncs; + private static CPUInstruction i_nct; + private static CPUInstruction i_ncds; + private static CPUInstruction i_ncdt; + private static CPUInstruction i_dpct; + private static CPUInstruction i_nccs; + private static CPUInstruction i_cdp; + private static CPUInstruction i_cc; + private static CPUInstruction i_gpl; + + public static void interpret_mfc2(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int value = readRegister(rd); + if (rt != 0) + r3000regs[rt] = value; + } + + public static int readRegister(final int reg) { + int value; + switch (reg) { + case R_VXY0: + value = (reg_v0.x & 0xffff) | ((reg_v0.y << 16) & 0xffff0000); + break; + case R_VZ0: + value = reg_v0.z; + break; + case R_VXY1: + value = (reg_v1.x & 0xffff) | ((reg_v1.y << 16) & 0xffff0000); + break; + case R_VZ1: + value = reg_v1.z; + break; + case R_VXY2: + value = (reg_v2.x & 0xffff) | ((reg_v2.y << 16) & 0xffff0000); + break; + case R_VZ2: + value = reg_v2.z; + break; + case R_RGB: + value = reg_rgb; + break; + case R_OTZ: + value = reg_otz; + break; + case R_IR0: + value = reg_ir0; + break; + case R_IR1: + value = reg_ir1; + break; + case R_IR2: + value = reg_ir2; + break; + case R_IR3: + value = reg_ir3; + break; + case R_SXY0: + value = (reg_sx0 & 0xffff) | ((reg_sy0 << 16) & 0xffff0000); + break; + case R_SXY1: + value = (reg_sx1 & 0xffff) | ((reg_sy1 << 16) & 0xffff0000); + break; + case R_SXY2: + value = (reg_sx2 & 0xffff) | ((reg_sy2 << 16) & 0xffff0000); + break; + case R_SXYP: + value = (reg_sxp & 0xffff) | ((reg_syp << 16) & 0xffff0000); + break; + case R_SZX: + value = reg_szx; + break; + case R_SZ0: + value = reg_sz0; + break; + case R_SZ1: + value = reg_sz1; + break; + case R_SZ2: + value = reg_sz2; + break; + case R_RGB0: + value = reg_rgb0; + break; + case R_RGB1: + value = reg_rgb1; + break; + case R_RGB2: + value = reg_rgb2; + break; + case R_RES1: + value = reg_res1; + break; + case R_MAC0: + value = reg_mac0; + break; + case R_MAC1: + value = reg_mac1; + break; + case R_MAC2: + value = reg_mac2; + break; + case R_MAC3: + value = reg_mac3; + break; + case R_IRGB: + value = readIORGB(); + break; + case R_ORGB: + value = readIORGB(); + break; + case R_LZCS: + value = reg_lzcs; + break; + case R_LZCR: + value = reg_lzcr; + break; + case R_R11R12: + value = (reg_rot.m11 & 0xffff) | ((reg_rot.m12 << 16) & 0xffff0000); + break; + case R_R13R21: + value = (reg_rot.m13 & 0xffff) | ((reg_rot.m21 << 16) & 0xffff0000); + break; + case R_R22R23: + value = (reg_rot.m22 & 0xffff) | ((reg_rot.m23 << 16) & 0xffff0000); + break; + case R_R31R32: + value = (reg_rot.m31 & 0xffff) | ((reg_rot.m32 << 16) & 0xffff0000); + break; + case R_R33: + value = (reg_rot.m33 & 0xffff); + break; + case R_TRX: + value = reg_trx; + break; + case R_TRY: + value = reg_try; + break; + case R_TRZ: + value = reg_trz; + break; + case R_L11L12: + value = (reg_ls.m11 & 0xffff) | ((reg_ls.m12 << 16) & 0xffff0000); + break; + case R_L13L21: + value = (reg_ls.m13 & 0xffff) | ((reg_ls.m21 << 16) & 0xffff0000); + break; + case R_L22L23: + value = (reg_ls.m21 & 0xffff) | ((reg_ls.m23 << 16) & 0xffff0000); + break; + case R_L31L32: + value = (reg_ls.m31 & 0xffff) | ((reg_ls.m32 << 16) & 0xffff0000); + break; + case R_L33: + value = (reg_ls.m33 & 0xffff); + break; + case R_RBK: + value = reg_rbk; + break; + case R_GBK: + value = reg_gbk; + break; + case R_BBK: + value = reg_bbk; + break; + case R_LR1LR2: + value = (reg_lc.m11 & 0xffff) | ((reg_lc.m12 << 16) & 0xffff0000); + break; + case R_LR3LG1: + value = (reg_lc.m13 & 0xffff) | ((reg_lc.m21 << 16) & 0xffff0000); + break; + case R_LG2LG3: + value = (reg_lc.m22 & 0xffff) | ((reg_lc.m23 << 16) & 0xffff0000); + break; + case R_LB1LB2: + value = (reg_lc.m31 & 0xffff) | ((reg_lc.m32 << 16) & 0xffff0000); + break; + case R_LB3: + value = (reg_lc.m33 & 0xffff); + break; + case R_RFC: + value = reg_rfc; + break; + case R_GFC: + value = reg_gfc; + break; + case R_BFC: + value = reg_bfc; + break; + case R_OFX: + value = reg_ofx; + break; + case R_OFY: + value = reg_ofy; + break; + case R_H: + // this is according to docs that it is accidentally sign extended + value = (reg_h << 16) >> 16; + break; + case R_DQA: + value = reg_dqa; + break; + case R_DQB: + value = reg_dqb; + break; + case R_ZSF3: + value = reg_zsf3; + break; + case R_ZSF4: + value = reg_zsf4; + break; + case R_FLAG: + value = reg_flag; + break; + default: + value = 0; + } + return value; + } + + public static void interpret_cfc2(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int value = readRegister(rd + 32); + if (rt != 0) + r3000regs[rt] = value; + } + + public static void writeIRGB(int value) { + reg_ir1 = (value&0x1f)<<7; + reg_ir2 = ((value>>5)&0x1f)<<7; + reg_ir3 = ((value>>10)&0x1f)<<7; + } + + public static int clampIR(int value) { + if (value < 0) { + value = 0; + } else { + value = value >> 7; + if (value > 0x1f) { + value = 0x1f; + } + } + return value; + } + + public static int readIORGB() { + return clampIR(reg_ir1)|(clampIR(reg_ir2)<<5)|(clampIR(reg_ir3)<<10); + } + + public static void writeRegister(int reg, int value) { + switch (reg) { + case R_VXY0: + reg_v0.x = (value << 16) >> 16; + reg_v0.y = value >> 16; + break; + case R_VZ0: + reg_v0.z = (value << 16) >> 16; + break; + case R_VXY1: + reg_v1.x = (value << 16) >> 16; + reg_v1.y = value >> 16; + break; + case R_VZ1: + reg_v1.z = (value << 16) >> 16; + break; + case R_VXY2: + reg_v2.x = (value << 16) >> 16; + reg_v2.y = value >> 16; + break; + case R_VZ2: + reg_v2.z = (value << 16) >> 16; + break; + case R_RGB: + reg_rgb = value; + break; + case R_OTZ: + reg_otz = value & 0xffff; // checked + break; + case R_IR0: + reg_ir0 = (value << 16) >> 16; // checked + break; + case R_IR1: + reg_ir1 = (value << 16) >> 16; // checked + break; + case R_IR2: + reg_ir2 = (value << 16) >> 16; // checked + break; + case R_IR3: + reg_ir3 = (value << 16) >> 16; // checked + break; + case R_SXY0: + reg_sx0 = (value << 16) >> 16; + reg_sy0 = value >> 16; + break; + case R_SXY1: + reg_sx1 = (value << 16) >> 16; + reg_sy1 = value >> 16; + break; + case R_SXY2: + reg_sx2 = (value << 16) >> 16; + reg_sy2 = value >> 16; + break; + case R_SXYP: + reg_sx0 = reg_sx1; + reg_sx1 = reg_sx2; + reg_sx2 = (value << 16) >> 16; + reg_sy0 = reg_sy1; + reg_sy1 = reg_sy2; + reg_sy2 = value >> 16; + break; + case R_SZX: + reg_szx = value & 0xffff; + break; + case R_SZ0: + reg_sz0 = value & 0xffff; + break; + case R_SZ1: + reg_sz1 = value & 0xffff; + break; + case R_SZ2: + reg_sz2 = value & 0xffff; + break; + case R_RGB0: + reg_rgb0 = value; + break; + case R_RGB1: + reg_rgb1 = value; + break; + case R_RGB2: + reg_rgb2 = value; + break; + case R_RES1: + reg_res1 = value; + break; + case R_MAC0: + reg_mac0 = value; + break; + case R_MAC1: + reg_mac1 = value; + break; + case R_MAC2: + reg_mac2 = value; + break; + case R_MAC3: + reg_mac3 = value; + break; + case R_IRGB: + writeIRGB(value); + break; + case R_ORGB: + // no op + break; + case R_LZCS: { + reg_lzcs = value; + /* + // old code for pre JDK5 + int mask = 0x80000000; + int comp = value & 0x80000000; + int bits; + + for (bits = 0; bits < 32; bits++) { + if ((value & mask) != comp) + break; + mask >>= 1; + comp >>= 1; + } + reg_lzcr = bits; + */ + reg_lzcr = Integer.numberOfLeadingZeros(value >= 0 ? value : ~value); + break; + } + case R_LZCR: + // lzcr is read only + // no op + break; + case R_R11R12: + reg_rot.m11 = (value << 16) >> 16; + reg_rot.m12 = value >> 16; + break; + case R_R13R21: + reg_rot.m13 = (value << 16) >> 16; + reg_rot.m21 = value >> 16; + break; + case R_R22R23: + reg_rot.m22 = (value << 16) >> 16; + reg_rot.m23 = value >> 16; + break; + case R_R31R32: + reg_rot.m31 = (value << 16) >> 16; + reg_rot.m32 = value >> 16; + break; + case R_R33: + reg_rot.m33 = (value << 16) >> 16; + break; + case R_TRX: + reg_trx = value; + break; + case R_TRY: + reg_try = value; + break; + case R_TRZ: + reg_trz = value; + break; + case R_L11L12: + reg_ls.m11 = (value << 16) >> 16; + reg_ls.m12 = value >> 16; + break; + case R_L13L21: + reg_ls.m13 = (value << 16) >> 16; + reg_ls.m21 = value >> 16; + break; + case R_L22L23: + reg_ls.m22 = (value << 16) >> 16; + reg_ls.m23 = value >> 16; + break; + case R_L31L32: + reg_ls.m31 = (value << 16) >> 16; + reg_ls.m32 = value >> 16; + break; + case R_L33: + reg_ls.m33 = (value << 16) >> 16; + break; + case R_RBK: + reg_rbk = value; + break; + case R_GBK: + reg_gbk = value; + break; + case R_BBK: + reg_bbk = value; + break; + case R_LR1LR2: + reg_lc.m11 = (value << 16) >> 16; + reg_lc.m12 = value >> 16; + break; + case R_LR3LG1: + reg_lc.m13 = (value << 16) >> 16; + reg_lc.m21 = value >> 16; + break; + case R_LG2LG3: + reg_lc.m22 = (value << 16) >> 16; + reg_lc.m23 = value >> 16; + break; + case R_LB1LB2: + reg_lc.m31 = (value << 16) >> 16; + reg_lc.m32 = value >> 16; + break; + case R_LB3: + reg_lc.m33 = (value << 16) >> 16; + break; + case R_RFC: + reg_rfc = value; + break; + case R_GFC: + reg_gfc = value; + break; + case R_BFC: + reg_bfc = value; + break; + case R_OFX: + reg_ofx = value; + break; + case R_OFY: + reg_ofy = value; + break; + case R_H: + reg_h = value & 0xffff; + break; + case R_DQA: + reg_dqa = (value << 16) >> 16; + break; + case R_DQB: + reg_dqb = value; + break; + case R_ZSF3: + reg_zsf3 = (value << 16) >> 16; + break; + case R_ZSF4: + reg_zsf4 = (value << 16) >> 16; + break; + case R_FLAG: + reg_flag = value; + break; + } + } + + public static void interpret_mtc2(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int value = r3000regs[rt]; + + writeRegister(rd, value); + } + + public static void interpret_ctc2(final int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int value = r3000regs[rt]; + + writeRegister(rd + 32, value); + } + + public static void interpret_cop2(final int ci) { + switch (R3000.Util.bits_rs(ci)) { + case 0: + GTE.interpret_mfc2(ci); + return; + case 2: + GTE.interpret_cfc2(ci); + return; + case 4: + GTE.interpret_mtc2(ci); + return; + case 6: + GTE.interpret_ctc2(ci); + return; + case 1: + case 3: + case 5: + case 7: + break; + default: + switch (ci & 0x3f) { + case 0x01: + GTE.interpret_rtps(ci); + return; + case 0x06: + GTE.interpret_nclip(ci); + return; + case 0x0c: + GTE.interpret_op(ci); + return; + case 0x10: + GTE.interpret_dpcs(ci); + return; + case 0x11: + GTE.interpret_intpl(ci); + return; + case 0x12: + GTE.interpret_mvmva(ci); + return; + case 0x13: + GTE.interpret_ncds(ci); + return; + case 0x14: + GTE.interpret_cdp(ci); + return; + case 0x16: + GTE.interpret_ncdt(ci); + return; + case 0x1b: + GTE.interpret_nccs(ci); + return; + case 0x1c: + GTE.interpret_cc(ci); + return; + case 0x1e: + GTE.interpret_ncs(ci); + return; + case 0x20: + GTE.interpret_nct(ci); + return; + case 0x28: + GTE.interpret_sqr(ci); + return; + case 0x29: + GTE.interpret_dcpl(ci); + return; + case 0x2a: + GTE.interpret_dpct(ci); + return; + case 0x2d: + GTE.interpret_avsz3(ci); + return; + case 0x2e: + GTE.interpret_avsz4(ci); + return; + case 0x30: + GTE.interpret_rtpt(ci); + return; + case 0x3d: + GTE.interpret_gpf(ci); + return; + case 0x3e: + GTE.interpret_gpl(ci); + return; + case 0x3f: + GTE.interpret_ncct(ci); + return; + } + } + CoreComponentConnections.SCP.resolve().signalReservedInstructionException(); + } + + public static void interpret_lwc2(final int ci) { + int base = R3000.Util.bits_rs(ci); + int rt = R3000.Util.bits_rt(ci); + int offset = (ci << 16) >> 16; + int addr = r3000regs[base] + offset; + addressSpace.tagAddressAccessRead32(r3000.getPC(), addr); + writeRegister(rt, addressSpace.read32(addr)); + } + + public static void interpret_swc2(final int ci) { + int base = R3000.Util.bits_rs(ci); + int rt = R3000.Util.bits_rt(ci); + int offset = (ci << 16) >> 16; + int addr = r3000regs[base] + offset; + addressSpace.tagAddressAccessWrite(r3000.getPC(), addr); + addressSpace.write32(addr, readRegister(rt)); + } + + public static void interpret_rtpt(final int ci) { + reg_flag = 0; + + // todo is no SF bit allowed? + if (0 == (ci & GTE_SF_MASK)) { + log.warn("RTPS with SF field!"); + } + + long vx = reg_v0.x; + long vy = reg_v0.y; + long vz = reg_v0.z; + + reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); + reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); + reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + reg_sz0 = LiD(reg_mac3); + if (debugLimit && reg_sz0 == 0) { + MiscUtil.assertionMessage("rtpt overflow 0"); + } + + + long hsz = LiE(divide(reg_h, reg_sz0)); + reg_sx0 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); + reg_sy0 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); + reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); + reg_ir0 = LiH(reg_mac0); + + // --------------------------------------------------- + + vx = reg_v1.x; + vy = reg_v1.y; + vz = reg_v1.z; + + reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); + reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); + reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + reg_sz1 = LiD(reg_mac3); + + if (debugLimit && reg_sz1 == 0) { + MiscUtil.assertionMessage("rtpt overflow 1"); + } + + hsz = LiE(divide(reg_h, reg_sz1)); + reg_sx1 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); + reg_sy1 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); + reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); + reg_ir0 = LiH(reg_mac0); + + // --------------------------------------------------- + + vx = reg_v2.x; + vy = reg_v2.y; + vz = reg_v2.z; + + reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); + reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); + reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + reg_sz2 = LiD(reg_mac3); + + if (debugLimit && reg_sz2 == 0) { + MiscUtil.assertionMessage("rtpt overflow 2"); + } + + hsz = LiE(divide(reg_h, reg_sz2)); + reg_sx2 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); + reg_sy2 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); + reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); + reg_ir0 = LiH(reg_mac0); + } + + public static void interpret_rtps(final int ci) { +// In: V0 Vector to transform. [1,15,0] +// R Rotation matrix [1,3,12] +// TR Translation vector [1,31,0] +// H View plane distance [0,16,0] +// DQA Depth que interpolation values. [1,7,8] +// DQB [1,7,8]OFX Screen offset values. [1,15,16] +// OFY [1,15,16] +// Out: SXY fifo Screen XY coordinates.(short) [1,15,0] +// SZ fifo Screen Z coordinate.(short) [0,16,0] +// IR0 Interpolation value for depth queing. [1,3,12] +// IR1 Screen X (short) [1,15,0] +// IR2 Screen Y (short) [1,15,0] +// IR3 Screen Z (short) [1,15,0] +// MAC1 Screen X (long) [1,31,0] +// MAC2 Screen Y (long) [1,31,0] +// MAC3 Screen Z (long) [1,31,0] +// Calculation: +// [1,31,0] MAC1=A1[TRX + R11*VX0 + R12*VY0 + R13*VZ0] [1,31,12] +// [1,31,0] MAC2=A2[TRY + R21*VX0 + R22*VY0 + R23*VZ0] [1,31,12] +// [1,31,0] MAC3=A3[TRZ + R31*VX0 + R32*VY0 + R33*VZ0] [1,31,12] +// [1,15,0] IR1= Lm_B1[MAC1] [1,31,0] +// [1,15,0] IR2= Lm_B2[MAC2] [1,31,0] +// [1,15,0] IR3= Lm_B3[MAC3] [1,31,0] +// SZ0<-SZ1<-SZ2<-SZ3 +// [0,16,0] SZ3= Lm_D(MAC3) [1,31,0] +// SX0<-SX1<-SX2, SY0<-SY1<-SY2 +// [1,15,0] SX2= Lm_G1[F[OFX + IR1*(H/SZ)]] [1,27,16] +// [1,15,0] SY2= Lm_G2[F[OFY + IR2*(H/SZ)]] [1,27,16] +// [1,31,0] MAC0= F[DQB + DQA * (H/SZ)] [1,19,24] +// [1,15,0] IR0= Lm_H[MAC0] [1,31,0] + + // or + + +// IR1 = MAC1 = (TRX*1000h + RT11*VX0 + RT12*VY0 + RT13*VZ0) SAR (sf*12) +// IR2 = MAC2 = (TRY*1000h + RT21*VX0 + RT22*VY0 + RT23*VZ0) SAR (sf*12) +// IR3 = MAC3 = (TRZ*1000h + RT31*VX0 + RT32*VY0 + RT33*VZ0) SAR (sf*12) +// SZ3 = MAC3 SAR ((1-sf)*12) ;ScreenZ FIFO 0..+FFFFh +// MAC0=(((H*20000h/SZ3)+1)/2)*IR1+OFX, SX2=MAC0/10000h ;ScrX FIFO -400h..+3FFh +// MAC0=(((H*20000h/SZ3)+1)/2)*IR2+OFY, SY2=MAC0/10000h ;ScrY FIFO -400h..+3FFh +// MAC0=(((H*20000h/SZ3)+1)/2)*DQA+DQB, IR0=MAC0/1000h ;Depth cueing 0..+1000h + + reg_flag = 0; + + long vx = reg_v0.x; + long vy = reg_v0.y; + long vz = reg_v0.z; + + // todo is no SF bit allowed? + if (0 == (ci & GTE_SF_MASK)) { + log.warn("RTPS with SF field!"); + } + reg_mac1 = A1(reg_rot.m11 * vx + reg_rot.m12 * vy + reg_rot.m13 * vz + (((long) reg_trx) << 12)); + reg_mac2 = A2(reg_rot.m21 * vx + reg_rot.m22 * vy + reg_rot.m23 * vz + (((long) reg_try) << 12)); + reg_mac3 = A3(reg_rot.m31 * vx + reg_rot.m32 * vy + reg_rot.m33 * vz + (((long) reg_trz) << 12)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + reg_szx = reg_sz0; + reg_sz0 = reg_sz1; + reg_sz1 = reg_sz2; + reg_sz2 = LiD(reg_mac3); + + reg_sx0 = reg_sx1; + reg_sy0 = reg_sy1; + reg_sx1 = reg_sx2; + reg_sy1 = reg_sy2; + + if (debugLimit && reg_sz2 == 0) { + MiscUtil.assertionMessage("rtps overflow"); + } + + long hsz = LiE(divide(reg_h, reg_sz2)); + // [1,15,0] SX2= LG1[F[OFX + IR1*(H/SZ)]] [1,27,16] + reg_sx2 = LiG1(LiF(reg_ofx + reg_ir1 * hsz)); + // [1,15,0] SY2= LG2[F[OFY + IR2*(H/SZ)]] [1,27,16] + reg_sy2 = LiG2(LiF(reg_ofy + reg_ir2 * hsz)); + // [1,31,0] MAC0= F[DQB + DQA * (H/SZ)] [1,19,24] + reg_mac0 = LiF(reg_dqb + reg_dqa * hsz); + + // [1,15,0] IR0= LH[MAC0] [1,31,0] + reg_ir0 = LiH(reg_mac0); + } + + public static long SIGNED_BIG(int src) { + if (src == 0) + return 0; + if (src > 0) + return 0x10000000000000L; + return -0x10000000000000L; + } + + public static void interpret_mvmva(final int ci) { +// Fields: sf, cv, lm +// R/LLM/LCM Rotation, light or color matrix. [1,3,12] +// TR/BK Translation or background color vector. +// out: [IR1,IR2,IR3] Short vector +// [MAC1,MAC2,MAC3] Long vector +// Calculation: +// MAC1=A1[CV1 + MX11*V1 + MX12*V2 + MX13*V3] +// MAC2=A2[CV2 + MX21*V1 + MX22*V2 + MX23*V3] +// MAC3=A3[CV3 + MX31*V1 + MX32*V2 + MX33*V3] +// IR1=Lm_B1[MAC1] +// IR2=Lm_B2[MAC2] +// IR3=Lm_B3[MAC3] +// Notes: +// The cv field allows selection of the far color vector, but this vector +// is not added correctly by the GTE. + + +// NOTE: int64/A1,A2,A3 can only happen with IR I think + + reg_flag = 0; + + Matrix matrix; + switch (ci & GTE_MX_MASK) { + case GTE_MX_LIGHT: + matrix = reg_ls; + break; + case GTE_MX_COLOR: + matrix = reg_lc; + break; + default: + matrix = reg_rot; + break; + } + + long vx; + long vy; + long vz; + switch (ci & GTE_V_MASK) { + case GTE_V_IR: + vx = reg_ir1; + vy = reg_ir2; + vz = reg_ir3; + break; + case GTE_V_V2: + vx = reg_v2.x; + vy = reg_v2.y; + vz = reg_v2.z; + break; + case GTE_V_V1: + vx = reg_v1.x; + vy = reg_v1.y; + vz = reg_v1.z; + break; + default: + vx = reg_v0.x; + vy = reg_v0.y; + vz = reg_v0.z; + break; + } + + // v values s15.0 or s31.0 (s19.12 in SF case?) + + long ssx = matrix.m11 * vx + matrix.m12 * vy + matrix.m13 * vz; + long ssy = matrix.m21 * vx + matrix.m22 * vy + matrix.m23 * vz; + long ssz = matrix.m31 * vx + matrix.m32 * vy + matrix.m33 * vz; + + if (0 != (ci & GTE_SF_MASK)) { + ssx >>= 12; + ssy >>= 12; + ssz >>= 12; + } + + // ss values are up to about s36.12 + switch (ci & GTE_CV_MASK) { + case GTE_CV_TR: + ssx += reg_trx; + ssy += reg_try; + ssz += reg_trz; + break; + case GTE_CV_BK: + ssx += reg_rbk; + ssy += reg_gbk; + ssz += reg_bbk; + break; + case GTE_CV_FC: + ssx += reg_rfc; + ssy += reg_gfc; + ssz += reg_bfc; + break; + default: + break; + } + + reg_mac1 = A1(ssx << 12); + reg_mac2 = A2(ssy << 12); + reg_mac3 = A3(ssz << 12); + + if (0 != (ci & GTE_LM_MASK)) { + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + } else { + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + } + } + + public static int LiB1_0(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B1; + if (debugLimitB) log.info("B1_0 + "+src); + return 0x7fff; + } else if (src < -0x8000) { + reg_flag |= FLAG_B1; + if (debugLimitB) log.info("B1_0 - "+src); + return -0x8000; + } + return src; + } + + + public static int LiB1_1(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B1; + if (debugLimitB) log.info("B1_1 + "+src); + return 0x7fff; + } else if (src < 0) { + reg_flag |= FLAG_B1; + if (debugLimitB) log.info("B1_1 0 "+src); + return 0; + } + return src; + } + + public static int LiB2_0(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B2; + if (debugLimitB) log.info("B2_0 + "+src); + return 0x7fff; + } else if (src < -0x8000) { + reg_flag |= FLAG_B2; + if (debugLimitB) log.info("B2_0 - "+src); + return -0x8000; + } + return src; + } + + public static int LiB2_1(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B2; + if (debugLimitB) log.info("B2_1 + "+src); + return 0x7fff; + } else if (src < 0) { + reg_flag |= FLAG_B2; + if (debugLimitB) log.info("B2_1 0 "+src); + return 0; + } + return src; + } + + public static int LiB3_0(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B3; + if (debugLimitB) log.info("B3_0 + "+src); + return 0x7fff; + } else if (src < -0x8000) { + reg_flag |= FLAG_B3; + if (debugLimitB) log.info("B3_0 - "+src); + return -0x8000; + } + return src; + } + + public static int LiB3_1(int src) { + if (src >= 0x8000) { + reg_flag |= FLAG_B3; + if (debugLimitB) log.info("B3_1 + "+src); + return 0x7fff; + } else if (src < 0) { + reg_flag |= FLAG_B3; + if (debugLimitB) log.info("B3_1 0 "+src); + return 0; + } + return src; + } + + public static int LiC1(int src) { + if (src < 0) { + reg_flag |= FLAG_C1; + return 0; + } else if (src > 0xfff) { + reg_flag |= FLAG_C1; + return 0xff; + } + return src>>4; + } + + public static int LiC2(int src) { + if (src < 0) { + reg_flag |= FLAG_C2; + return 0; + } else if (src > 0xfff) { + reg_flag |= FLAG_C2; + return 0xff; + } + return src>>4; + } + + public static int LiC3(int src) { + if (src < 0) { + reg_flag |= FLAG_C3; + return 0; + } else if (src > 0xfff) { + reg_flag |= FLAG_C3; + return 0xff; + } + return src>>4; + } + + public static int LiD(int src) { + if (src < 0) { + reg_flag |= FLAG_D; + if (debugLimitD) log.info("D 0 "+src); + return 0; + } else if (src >= 0x10000) { + reg_flag |= FLAG_D; + if (debugLimitD) log.info("D + "+src); + return 0xffff; + } + return src; + } + + private static int LiE(int src) { + if (src >= 0x20000) { + reg_flag |= FLAG_E; + src = 0x1ffff; + } + return src; + } + + private static int LiF(long src) { + if (src >= BIT47) { + reg_flag |= FLAG_FP; + if (debugLimit) log.info("F + "+src); +// return 0x7fffffff; + } else if (src <= -BIT47) { + reg_flag |= FLAG_FN; + if (debugLimit) log.info("F - "+src); +// return 0x80000000; + } + return (int) (src >> 16); + } + + public static int LiG1(int src) { + if (src >= 0x400) { + reg_flag |= FLAG_G1; + if (debugLimitG) log.info("G1 + "+src); + return 0x3ff; + } else if (src < -0x400) { + reg_flag |= FLAG_G1; + if (debugLimitG) log.info("G1 - "+src); + return -0x400; + } + return src; + } + + public static int LiG2(int src) { + if (src >= 0x400) { + reg_flag |= FLAG_G2; + if (debugLimitG) log.info("G2 + "+src); + return 0x3ff; + } else if (src < -0x400) { + reg_flag |= FLAG_G2; + if (debugLimitG) log.info("G2 - "+src); + return -0x400; + } + return src; + } + + public static int LiH(int src) { + if (src >= 0x1000) { + reg_flag |= FLAG_H; +// if (debugLimit) log.info("H "+src); + return 0xfff; + } else if (src < 0) { + reg_flag |= FLAG_H; +// if (debugLimit) log.info("H "+src); + return 0; + } + return src; + } + + private static int A1(long val) { + if (val >= BIT43) { + reg_flag |= FLAG_A1P; + } else if (val <= -BIT43) { + reg_flag |= FLAG_A1N; + } + return (int) (val >> 12); + } + + private static int A2(long val) { + if (val >= BIT43) { + reg_flag |= FLAG_A2P; + } else if (val <= -BIT43) { + reg_flag |= FLAG_A2N; + } + return (int) (val >> 12); + } + + private static long mac3_64; + + private static int A3(long val) { + if (val >= BIT43) { + reg_flag |= FLAG_A3P; + } else if (val <= -BIT43) { + reg_flag |= FLAG_A3N; + } + return (int) (val >> 12); + } + + public static void interpret_op(final int ci) { + // checked except todo unclear whether lm is supported - added here +// Fields: sf +// in: [R11R12,R22R23,R33] vector 1 +// [IR1,IR2,IR3] vector 2 +// out: [IR1,IR2,IR3] outer product +// [MAC1,MAC2,MAC3] outer product +// Calculation: (D1=R11R12,D2=R22R23,D3=R33) +// MAC1=A1[D2*IR3 - D3*IR2] +// MAC2=A2[D3*IR1 - D1*IR3] +// MAC3=A3[D1*IR2 - D2*IR1] +// IR1=Lm_B1[MAC0] +// IR2=Lm_B2[MAC1] +// IR3=Lm_B3[MAC2] + reg_flag = 0; + + long a1 = reg_rot.m11; + long a2 = reg_rot.m22; + long a3 = reg_rot.m33; + + long ss1 = a2 * reg_ir3 - a3 * reg_ir2; + long ss2 = a3 * reg_ir1 - a1 * reg_ir3; + long ss3 = a1 * reg_ir2 - a2 * reg_ir1; + + if (0 == (ci & GTE_SF_MASK)) { + ss1 <<= 12; + ss2 <<= 12; + ss3 <<= 12; + } + + reg_mac1 = A1(ss1); + reg_mac2 = A2(ss2); + reg_mac3 = A3(ss3); + if (0 != (ci & GTE_LM_MASK)) { + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + } else { + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + } + } + + public static void interpret_avsz3(final int ci) { + // checked +// in: SZ1, SZ2, SZ3 Z-Values [0,16,0] +// ZSF3 Divider [1,3,12] +// out: OTZ Average. [0,16,0] +// MAC0 Average. [1,31,0] +// Calculation: +// [1,31,0] MAC0=F[ZSF3*SZ1 + ZSF3*SZ2 + ZSF3*SZ3] [1,31,12] +// [0,16,0] OTZ=Lm_D[MAC0] [1,31,0] + + reg_flag = 0; + reg_mac0 = LiF(reg_zsf3 * (long)((reg_sz0 + reg_sz1 + reg_sz2)<<4)); + reg_otz = LiD(reg_mac0); + } + + public static void interpret_avsz4(final int ci) { + // checked +// Fields: +// in: SZ1,SZ2,SZ3,SZ4 Z-Values [0,16,0] +// ZSF4 Divider [1,3,12] +// out: OTZ Average. [0,16,0] +// MAC0 Average. [1,31,0] +// Calculation: +// [1,31,0] MAC0=F[ZSF4*SZ0 + ZSF4*SZ1 + ZSF4*SZ2 + ZSF4*SZ3] [1,31,12] +// [0,16,0] OTZ=Lm_D[MAC0] [1,31,0] + + reg_flag = 0; + reg_mac0 = LiF(reg_zsf4 * (long)((reg_sz0 + reg_sz1 + reg_sz2 + reg_szx)<<4)); + reg_otz = LiD(reg_mac0); + } + + public static void interpret_nclip(final int ci) { + /* + NOTE: I don't think nclip should clear the FLAG register. + + In Tomb Raider, there is code which looks something like this: + RTPT + NCLIP + f = gte->R_FLAG + if (f & 0x7fc7e000) goto skip_polygon; + + Since the RTPT can only set SX0,SX1,SX2,SY0,SY1,SY2 to values in the + range -0x800 to 0x800, there is no way NCLIP's calculation can overflow. + Hence, if NCLIP clears the FLAG register there is no way the branch + in the above code can ever be taken. + Whereas, if NCLIP _doesn't_ clear the FLAG, the above code actually + makes sense. + */ + reg_flag = 0; + + // [1,31,0] MAC0 = F[SX0*SY1+SX1*SY2+SX2*SY0-SX0*SY2-SX1*SY0-SX2*SY1] [1,43,0] + // @@ not too worried about liF() here... + reg_mac0 = reg_sx0 * reg_sy1 + reg_sx1 * reg_sy2 + reg_sx2 * reg_sy0 - + reg_sx0 * reg_sy2 - reg_sx1 * reg_sy0 - reg_sx2 * reg_sy1; + } + + public static void interpret_ncct(final int ci) { + // untested + reg_flag = 0; + + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + long ss1 = m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z; + long ss2 = m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z; + long ss3 = m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z; + + int mac1 = A1(ss1); + int mac2 = A2(ss2); + int mac3 = A3(ss3); + + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); + ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); + ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + mac1 = A1(r * ir1); + mac2 = A2(g * ir2); + mac3 = A3(b * ir3); + + int rr = LiC1(mac1); + int gg = LiC2(mac2); + int bb = LiC3(mac3); + reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; + + // 2 + ss1 = m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z; + ss2 = m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z; + ss3 = m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z; + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); + ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); + ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + mac1 = A1(r * ir1); + mac2 = A2(g * ir2); + mac3 = A3(b * ir3); + + // gcs 011802 added >>4 + rr = LiC1(mac1); + gg = LiC2(mac2); + bb = LiC3(mac3); + reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; + + // 3 + ss1 = m11 * reg_v2.x + m12 * reg_v2.y + m13 * reg_v2.z; + ss2 = m21 * reg_v2.x + m22 * reg_v2.y + m23 * reg_v2.z; + ss3 = m31 * reg_v2.x + m32 * reg_v2.y + m33 * reg_v2.z; + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); + ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); + ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + reg_mac1 = A1(r * ir1); + reg_mac2 = A2(g * ir2); + reg_mac3 = A3(b * ir3); + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + + // gcs 011802 added >>4 + rr = LiC1(reg_mac1); + gg = LiC2(reg_mac2); + bb = LiC3(reg_mac3); + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_gpf(final int ci) { + reg_flag = 0; + // MAC1=A1[IR0 * IR1] + // MAC2=A2[IR0 * IR2] + // MAC3=A3[IR0 * IR3] + // IR1=LB1[MAC1] + // IR2=LB2[MAC2] + // IR3=LB3[MAC3] + //[0,8,0] Cd0<-Cd1<-Cd2<- CODE + //[0,8,0] R0<-R1<-R2<- LC1[MAC1] + //[0,8,0] G0<-G1<-G2<- LC2[MAC2] + //[0,8,0] B0<-B1<-B2<- LC3[MAC3] + + long m = reg_ir0; + if (0 != (ci & GTE_SF_MASK)) { + reg_mac1 = A1(m * reg_ir1); + reg_mac2 = A2(m * reg_ir2); + reg_mac3 = A3(m * reg_ir3); + } else { + reg_mac1 = A1((m * reg_ir1) << 12); + reg_mac2 = A2((m * reg_ir2) << 12); + reg_mac3 = A3((m * reg_ir3) << 12); + } + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); + } + + public static void interpret_dcpl(final int ci) { + +// In: RGB Primary color. R,G,B,CODE [0,8,0] +// IR0 interpolation value. [1,3,12] +// [IR1,IR2,IR3] Local color vector. [1,3,12] +// CODE Code value from RGB. CODE [0,8,0] +// FC Far color. [1,27,4] +// Out: RGBn RGB fifo Rn,Gn,Bn,CDn [0,8,0] +// [IR1,IR2,IR3] Color vector [1,11,4] +// [MAC1,MAC2,MAC3] Color vector [1,27,4] +// Calculation: +// [1,27,4] MAC1=A1[R*IR1 + IR0*(Lm_B1[RFC-R* IR1])] [1,27,16] +// [1,27,4] MAC2=A2[G*IR2 + IR0*(Lm_B1[GFC-G* IR2])] [1,27,16] +// [1,27,4] MAC3=A3[B*IR3 + IR0*(Lm_B1[BFC-B* IR3])] [1,27,16] +// [1,11,4] IR1=Lm_B1[MAC1] [1,27,4] +// [1,11,4] IR2=Lm_B2[MAC2] [1,27,4] +// [1,11,4] IR3=Lm_B3[MAC3] [1,27,4] +// [0,8,0] Cd0<-Cd1<-Cd2<- CODE +// [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] +// [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] +// [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] + + reg_flag = 0; + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + // TODO - is this B1 all the way correct? + reg_mac1 = A1(r * reg_ir1 + reg_ir0 * LiB1_0(reg_rfc - ((r * reg_ir1) >> 12))); + reg_mac2 = A2(g * reg_ir2 + reg_ir0 * LiB1_0(reg_gfc - ((g * reg_ir2) >> 12))); + reg_mac3 = A3(b * reg_ir3 + reg_ir0 * LiB1_0(reg_bfc - ((b * reg_ir3) >> 12))); + + // TODO - is this B1 all the way correct? + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_dpcs(final int ci) { + // checked + /** + In: IR0 Interpolation value [1,3,12] + RGB Color R,G,B,CODE [0,8,0] + FC Far color RFC,GFC,BFC [1,27,4] + + Out: RGBn RGB fifo Rn,Gn,Bn,CDn [0,8,0] + [IR1,IR2,IR3] Color vector [1,11,4] + [MAC1,MAC2,MAC3] Color vector [1,27,4] + + [1,27,4] MAC1=A1[(R + IR0*(Lm_B1[RFC - R])] [1,27,16][lm=0] + [1,27,4] MAC2=A2[(G + IR0*(Lm_B1[GFC - G])] [1,27,16][lm=0] + [1,27,4] MAC3=A3[(B + IR0*(Lm_B1[BFC - B])] [1,27,16][lm=0] + [1,11,4] IR1=Lm_B1[MAC1] [1,27,4][lm=0] + [1,11,4] IR2=Lm_B2[MAC2] [1,27,4][lm=0] + [1,11,4] IR3=Lm_B3[MAC3] [1,27,4][lm=0] + [0,8,0] Cd0<-Cd1<-Cd2<- CODE + [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] + [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] + [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] + */ + reg_flag = 0; + + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + reg_mac1 = A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r)); + reg_mac2 = A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g)); + reg_mac3 = A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_intpl(final int ci) { + reg_flag = 0; + int chi = reg_rgb & 0xff000000; + + long ir0 = reg_ir0; + reg_mac1 = A1((reg_ir1 << 12) + ir0 * LiB1_0(reg_rfc - reg_ir1)); + reg_mac2 = A2((reg_ir2 << 12) + ir0 * LiB2_0(reg_gfc - reg_ir2)); + reg_mac3 = A3((reg_ir3 << 12) + ir0 * LiB3_0(reg_bfc - reg_ir3)); + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_sqr(final int ci) { + // checked +// Fields: sf +// in: [IR1,IR2,IR3] vector [1,15,0][1,3,12] +// out: [IR1,IR2,IR3] vector^2 [1,15,0][1,3,12] +// [MAC1,MAC2,MAC3] vector^2 [1,31,0][1,19,12] +// Calculation: (left format sf=0, right format sf=1) +// [1,31,0][1,19,12] MAC1=A1[IR1*IR1] [1,43,0][1,31,12] +// [1,31,0][1,19,12] MAC2=A2[IR2*IR2] [1,43,0][1,31,12] +// [1,31,0][1,19,12] MAC3=A3[IR3*IR3] [1,43,0][1,31,12] +// [1,15,0][1,3,12] IR1=Lm_B1[MAC1] [1,31,0][1,19,12][lm=1] +// [1,15,0][1,3,12] IR2=Lm_B2[MAC2] [1,31,0][1,19,12][lm=1] +// [1,15,0][1,3,12] IR3=Lm_B3[MAC3] [1,31,0][1,19,12][lm=1] + + reg_flag = 0; + + // [1,31,0] MAC1=A1[IR1*IR1] [1,43,0] + // [1,31,0] MAC2=A2[IR2*IR2] [1,43,0] + // [1,31,0] MAC3=A3[IR3*IR3] [1,43,0] + // [1,15,0] IR1=LB1[MAC1] [1,31,0][lm=1] + // [1,15,0] IR2=LB2[MAC2] [1,31,0][lm=1] + // [1,15,0] IR3=LB3[MAC3] [1,31,0][lm=1] + + int i1 = reg_ir1 * reg_ir1; + int i2 = reg_ir2 * reg_ir2; + int i3 = reg_ir3 * reg_ir3; + + if (0 != (ci & GTE_SF_MASK)) { + i1 >>= 12; + i2 >>= 12; + i3 >>= 12; + } + + // A1,A2,A3 not possible since the inputs are signed 16 bit + reg_mac1 = i1; + reg_mac2 = i2; + reg_mac3 = i3; + + // lm=0 also not pertinent + reg_ir1 = LiB1_1(i1); + reg_ir2 = LiB2_1(i2); + reg_ir3 = LiB3_1(i3); + } + + public static void interpret_ncs(final int ci) { + // test with ridge racer + reg_flag = 0; + int chi = reg_rgb & 0xff000000; + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); + int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); + int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); + + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + reg_mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + reg_mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + reg_mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_nct(final int ci) { + // test with ridge racer + reg_flag = 0; + int chi = reg_rgb & 0xff000000; + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); + int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); + int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); + + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + int rr = LiC1(mac1); + int gg = LiC2(mac2); + int bb = LiC3(mac3); + reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; + + // 2 + + mac1 = A1(m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z); + mac2 = A2(m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z); + mac3 = A3(m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + rr = LiC1(mac1); + gg = LiC2(mac2); + bb = LiC3(mac3); + reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; + + // 3 + + mac1 = A1(m11 * reg_v2.x + m12 * reg_v2.y + m13 * reg_v2.z); + mac2 = A2(m21 * reg_v2.x + m22 * reg_v2.y + m23 * reg_v2.z); + mac3 = A3(m31 * reg_v2.x + m32 * reg_v2.y + m33 * reg_v2.z); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + reg_mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + reg_mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + reg_mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + + rr = LiC1(reg_mac1); + gg = LiC2(reg_mac2); + bb = LiC3(reg_mac3); + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_ncds(final int ci) { + reg_flag = 0; + + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + // [1,19,12] MAC1=A1[L11*VX0 + L12*VY0 + L13*VZ0] [1,19,24] + // [1,19,12] MAC2=A1[L21*VX0 + L22*VY0 + L23*VZ0] [1,19,24] + // [1,19,12] MAC3=A1[L31*VX0 + L32*VY0 + L33*VZ0] [1,19,24] + // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); + int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); + int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] + // [1,19,12] MAC2=A1[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] + // [1,19,12] MAC3=A1[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] + // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + // [1,27,4] MAC1=A1[R*IR1 + IR0*(LB1[RFC-R*IR1])] [1,27,16][lm=0] + // [1,27,4] MAC2=A1[G*IR2 + IR0*(LB2[GFC-G*IR2])] [1,27,16][lm=0] + // [1,27,4] MAC3=A1[B*IR3 + IR0*(LB3[BFC-B*IR3])] [1,27,16][lm=0] + // [1,3,4] IR1= LB1[MAC1] [1,27,4][lm=1] + // [1,3,4] IR2= LB2[MAC2] [1,27,4][lm=1] + // [1,3,4] IR3= LB3[MAC3] [1,27,4][lm=1] + long ir0 = reg_ir0; + reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); + reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); + reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); + + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + + // [0,8,0] Cd0<-Cd1<-Cd2<- CODE + // [0,8,0] R0<-R1<-R2<- LC1[MAC1] [1,27,4] + // [0,8,0] G0<-G1<-G2<- LC2[MAC2] [1,27,4] + // [0,8,0] B0<-B1<-B2<- LC3[MAC3] [1,27,4] + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_ncdt(final int ci) { + reg_flag = 0; + + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + // [1,19,12] MAC1=A1[L11*VX0 + L12*VY0 + L13*VZ0] [1,19,24] + // [1,19,12] MAC2=A1[L21*VX0 + L22*VY0 + L23*VZ0] [1,19,24] + // [1,19,12] MAC3=A1[L31*VX0 + L32*VY0 + L33*VZ0] [1,19,24] + // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + int mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); + int mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); + int mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] + // [1,19,12] MAC2=A1[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] + // [1,19,12] MAC3=A1[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] + // [1,3,12] IR1= LB1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= LB2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= LB3[MAC3] [1,19,12][lm=1] + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + // [1,27,4] MAC1=A1[R*IR1 + IR0*(LB1[RFC-R*IR1])] [1,27,16][lm=0] + // [1,27,4] MAC2=A1[G*IR2 + IR0*(LB2[GFC-G*IR2])] [1,27,16][lm=0] + // [1,27,4] MAC3=A1[B*IR3 + IR0*(LB3[BFC-B*IR3])] [1,27,16][lm=0] + // [1,3,4] IR1= LB1[MAC1] [1,27,4][lm=1] + // [1,3,4] IR2= LB2[MAC2] [1,27,4][lm=1] + // [1,3,4] IR3= LB3[MAC3] [1,27,4][lm=1] + long ir0 = reg_ir0; + reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); + reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); + reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); + + // [0,8,0] Cd0<-Cd1<-Cd2<- CODE + // [0,8,0] R0<-R1<-R2<- LC1[MAC1] [1,27,4] + // [0,8,0] G0<-G1<-G2<- LC2[MAC2] [1,27,4] + // [0,8,0] B0<-B1<-B2<- LC3[MAC3] [1,27,4] + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = rr | (gg << 8) | (bb << 16) | chi; + + // 2 ---- + + mac1 = A1(m11 * reg_v1.x + m12 * reg_v1.y + m13 * reg_v1.z); + mac2 = A2(m21 * reg_v1.x + m22 * reg_v1.y + m23 * reg_v1.z); + mac3 = A3(m31 * reg_v1.x + m32 * reg_v1.y + m33 * reg_v1.z); + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); + reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); + reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); + + rr = LiC1(reg_mac1); + gg = LiC2(reg_mac2); + bb = LiC3(reg_mac3); + reg_rgb1 = rr | (gg << 8) | (bb << 16) | chi; + + // 3 ---- + + mac1 = A1(m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z); + mac2 = A2(m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z); + mac3 = A3(m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z); + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); + reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); + reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); + + rr = LiC1(reg_mac1); + gg = LiC2(reg_mac2); + bb = LiC3(reg_mac3); + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_dpct(final int ci) { + // checked +// [1,27,4] MAC1=A1[R0+ IR0*(Lm_B1[RFC - R0])] [1,27,16][lm=0] +// [1,27,4] MAC2=A2[G0+ IR0*(Lm_B1[GFC - G0])] [1,27,16][lm=0] +// [1,27,4] MAC3=A3[B0+ IR0*(Lm_B1[BFC - B0])] [1,27,16][lm=0] +// [1,11,4] IR1=Lm_B1[MAC1] [1,27,4][lm=0] +// [1,11,4] IR2=Lm_B2[MAC2] [1,27,4][lm=0] +// [1,11,4] IR3=Lm_B3[MAC3] [1,27,4][lm=0] +// [0,8,0] Cd0<-Cd1<-Cd2<- CODE +// [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] +// [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] +// [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] +// *3 + + reg_flag = 0; + + // 1 ---- + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb0 & 0xff) << 4; + int g = (reg_rgb0 & 0xff00) >> 4; + int b = (reg_rgb0 & 0xff0000) >> 12; + + int rr = LiC1(A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r))); + int gg = LiC2(A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g))); + int bb = LiC3(A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b))); + reg_rgb0 = chi | rr | (gg << 8) | (bb << 16); + + // 2 ---- + + r = (reg_rgb1 & 0xff) << 4; + g = (reg_rgb1 & 0xff00) >> 4; + b = (reg_rgb1 & 0xff0000) >> 12; + + rr = LiC1(A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r))); + gg = LiC2(A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g))); + bb = LiC3(A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b))); + reg_rgb1 = chi | rr | (gg << 8) | (bb << 16); + + // 3 ---- + + r = (reg_rgb2 & 0xff) << 4; + g = (reg_rgb2 & 0xff00) >> 4; + b = (reg_rgb2 & 0xff0000) >> 12; + + reg_mac1 = A1((r << 12) + reg_ir0 * LiB1_0(reg_rfc - r)); + reg_mac2 = A2((g << 12) + reg_ir0 * LiB1_0(reg_gfc - g)); + reg_mac3 = A3((b << 12) + reg_ir0 * LiB1_0(reg_bfc - b)); + + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + + rr = LiC1(reg_mac1); + gg = LiC2(reg_mac2); + bb = LiC3(reg_mac3); + reg_rgb2 = chi | rr | (gg << 8) | (bb << 16); + } + + public static void interpret_nccs(final int ci) { + // untested + reg_flag = 0; + + int chi = reg_rgb & 0xff000000; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + + long m11 = reg_ls.m11; + long m12 = reg_ls.m12; + long m13 = reg_ls.m13; + long m21 = reg_ls.m21; + long m22 = reg_ls.m22; + long m23 = reg_ls.m23; + long m31 = reg_ls.m31; + long m32 = reg_ls.m32; + long m33 = reg_ls.m33; + + long ss1 = m11 * reg_v0.x + m12 * reg_v0.y + m13 * reg_v0.z; + long ss2 = m21 * reg_v0.x + m22 * reg_v0.y + m23 * reg_v0.z; + long ss3 = m31 * reg_v0.x + m32 * reg_v0.y + m33 * reg_v0.z; + + int mac1 = A1(ss1); + int mac2 = A2(ss2); + int mac3 = A3(ss3); + + int ir1 = LiB1_1(mac1); + int ir2 = LiB2_1(mac2); + int ir3 = LiB3_1(mac3); + + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + ss1 = c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12); + ss2 = c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12); + ss3 = c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12); + + mac1 = A1(ss1); + mac2 = A2(ss2); + mac3 = A3(ss3); + + ir1 = LiB1_1(mac1); + ir2 = LiB2_1(mac2); + ir3 = LiB3_1(mac3); + + reg_mac1 = A1(r * ir1); + reg_mac2 = A2(g * ir2); + reg_mac3 = A3(b * ir3); + reg_ir1 = LiB1_1(reg_mac1); + reg_ir2 = LiB2_1(reg_mac2); + reg_ir3 = LiB3_1(reg_mac3); + + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = rr | (gg << 8) | (bb << 16) | chi; + } + + public static void interpret_cdp(final int ci) { + // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] + // [1,19,12] MAC2=A2[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] + // [1,19,12] MAC3=A3[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] + int ir1 = reg_ir1; + int ir2 = reg_ir2; + int ir3 = reg_ir3; + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + int mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + int mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + int mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + // [1,3,12] IR1= Lm_B1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= Lm_B2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= Lm_B3[MAC3] [1,19,12][lm=1] + ir1 = LiB1_1(mac1); + ir2 = LiB1_1(mac2); + ir3 = LiB1_1(mac3); + + // [1,27,4] MAC1=A1[R*IR1 + IR0*(Lm_B1[RFC-R*IR1])] [1,27,16][lm=0] + // [1,27,4] MAC2=A2[G*IR2 + IR0*(Lm_B2[GFC-G*IR2])] [1,27,16][lm=0] + // [1,27,4] MAC3=A3[B*IR3 + IR0*(Lm_B3[BFC-B*IR3])] [1,27,16][lm=0] + // [1,3,12] IR1= Lm_B1[MAC1] [1,27,4][lm=1] + // [1,3,12] IR2= Lm_B2[MAC2] [1,27,4][lm=1] + // [1,3,12] IR3= Lm_B3[MAC3] [1,27,4][lm=1] + long ir0 = reg_ir0; + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + reg_mac1 = A1(r * ir1 + ((ir0 * LiB1_0((reg_rfc << 12) - r * ir1)) >> 12)); + reg_mac2 = A2(g * ir2 + ((ir0 * LiB2_0((reg_gfc << 12) - g * ir2)) >> 12)); + reg_mac3 = A3(b * ir3 + ((ir0 * LiB3_0((reg_bfc << 12) - b * ir3)) >> 12)); + reg_ir1 = LiB1_1(mac1); + reg_ir2 = LiB1_1(mac2); + reg_ir3 = LiB1_1(mac3); + + // [0,8,0] Cd0<-Cd1<-Cd2<- CODE + // [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] + // [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] + // [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); + } + + public static void interpret_cc(final int ci) { + // [1,19,12] MAC1=A1[RBK + LR1*IR1 + LR2*IR2 + LR3*IR3] [1,19,24] + // [1,19,12] MAC2=A2[GBK + LG1*IR1 + LG2*IR2 + LG3*IR3] [1,19,24] + // [1,19,12] MAC3=A3[BBK + LB1*IR1 + LB2*IR2 + LB3*IR3] [1,19,24] + int ir1 = reg_ir1; + int ir2 = reg_ir2; + int ir3 = reg_ir3; + long c11 = reg_lc.m11; + long c12 = reg_lc.m12; + long c13 = reg_lc.m13; + long c21 = reg_lc.m21; + long c22 = reg_lc.m22; + long c23 = reg_lc.m23; + long c31 = reg_lc.m31; + long c32 = reg_lc.m32; + long c33 = reg_lc.m33; + + long bkr = reg_rbk; + long bkg = reg_gbk; + long bkb = reg_bbk; + + int mac1 = A1(c11 * ir1 + c12 * ir2 + c13 * ir3 + (bkr << 12)); + int mac2 = A2(c21 * ir1 + c22 * ir2 + c23 * ir3 + (bkg << 12)); + int mac3 = A3(c31 * ir1 + c32 * ir2 + c33 * ir3 + (bkb << 12)); + + // [1,3,12] IR1= Lm_B1[MAC1] [1,19,12][lm=1] + // [1,3,12] IR2= Lm_B2[MAC2] [1,19,12][lm=1] + // [1,3,12] IR3= Lm_B3[MAC3] [1,19,12][lm=1] + ir1 = LiB1_1(mac1); + ir2 = LiB1_1(mac2); + ir3 = LiB1_1(mac3); + + // [1,27,4] MAC1=A1[R*IR1] [1,27,16] + // [1,27,4] MAC2=A2[G*IR2] [1,27,16] + // [1,27,4] MAC3=A3[B*IR3] [1,27,16] + // [1,3,12] IR1= Lm_B1[MAC1] [1,27,4][lm=1] + // [1,3,12] IR2= Lm_B2[MAC2] [1,27,4][lm=1] + // [1,3,12] IR3= Lm_B3[MAC3] [1,27,4][lm=1] + int r = (reg_rgb & 0xff) << 4; + int g = (reg_rgb & 0xff00) >> 4; + int b = (reg_rgb & 0xff0000) >> 12; + reg_mac1 = A1(r * ir1); + reg_mac2 = A2(g * ir2); + reg_mac3 = A3(b * ir3); + reg_ir1 = LiB1_1(mac1); + reg_ir2 = LiB1_1(mac2); + reg_ir3 = LiB1_1(mac3); + + // [0,8,0] Cd0<-Cd1<-Cd2<- CODE + // [0,8,0] R0<-R1<-R2<- Lm_C1[MAC1] [1,27,4] + // [0,8,0] G0<-G1<-G2<- Lm_C2[MAC2] [1,27,4] + // [0,8,0] B0<-B1<-B2<- Lm_C3[MAC3] [1,27,4] + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); + } + + public static void interpret_gpl(final int ci) { + reg_flag = 0; + + long i = reg_ir0; + if (0 != (ci & GTE_SF_MASK)) { + reg_mac1 = A1((((long) reg_mac1) << 12) + i * reg_ir1); + reg_mac2 = A2((((long) reg_mac2) << 12) + i * reg_ir2); + reg_mac3 = A3((((long) reg_mac3) << 12) + i * reg_ir3); + } else { + reg_mac1 = A1((reg_mac1 + i * reg_ir1) << 12); + reg_mac2 = A2((reg_mac2 + i * reg_ir2) << 12); + reg_mac3 = A3((reg_mac3 + i * reg_ir3) << 12); + } + reg_ir1 = LiB1_0(reg_mac1); + reg_ir2 = LiB2_0(reg_mac2); + reg_ir3 = LiB3_0(reg_mac3); + int rr = LiC1(reg_mac1); + int gg = LiC2(reg_mac2); + int bb = LiC3(reg_mac3); + reg_rgb0 = reg_rgb1; + reg_rgb1 = reg_rgb2; + reg_rgb2 = (reg_rgb & 0xff000000) | rr | (gg << 8) | (bb << 16); + } + + static int table[] = + { + 0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3, + 0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8, + 0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb, 0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0, + 0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a, + 0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74, + 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, + 0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, + 0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f, + 0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24, + 0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, + 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11, + 0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, + 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, + 0x00 + }; + + static int dividex(int numerator, int denominator) { + if (denominator == 0) { + return Integer.MAX_VALUE; + } + return (int)((((long)numerator)<<16)/denominator); + } + + static int divide(int numerator, int denominator) { + if (denominator == 0) { + return Integer.MAX_VALUE; + } + if (numerator <= 0x7fff) { + return (numerator<<16)/denominator; + } else { + return (int)((((long)numerator)<<16)/denominator); + } + } + + static int gte_divide(int numerator, int denominator) { + if (numerator < (denominator * 2)) { + int shift = Integer.numberOfLeadingZeros(denominator) - 16; + + int r1 = (denominator << shift) & 0x7fff; + int r2 = table[((r1 + 0x40) >> 7)] + 0x101; + int r3 = ((0x80 - (r2 * (r1 + 0x8000))) >> 8) & 0x1ffff; + int reciprocal = ((r2 * r3) + 0x80) >> 8; + + return (int) ((((long) reciprocal * (numerator << shift)) + 0x8000) >> 16); + } + + return Integer.MAX_VALUE; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java new file mode 100644 index 0000000..6a1e8d5 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.mdec; + +public class IDCT { + private static final int W1 = 2841; // 2048*sqrt(2)*cos(1*pi/16) + private static final int W2 = 2676; // 2048*sqrt(2)*cos(2*pi/16) + private static final int W3 = 2408; // 2048*sqrt(2)*cos(3*pi/16) + private static final int W5 = 1609; // 2048*sqrt(2)*cos(5*pi/16) + private static final int W6 = 1108; // 2048*sqrt(2)*cos(6*pi/16) + private static final int W7 = 565; // 2048*sqrt(2)*cos(7*pi/16) + + private static final int clamp[] = new int[2048]; + + private static void idctrow(int[] blk, int base) { + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + if (0 == ((x1 = blk[base + 4] << 11) | (x2 = blk[base + 6]) | (x3 = blk[base + 2]) | + (x4 = blk[base + 1]) | (x5 = blk[base + 7]) | (x6 = blk[base + 5]) | (x7 = blk[base + 3]))) { + blk[base + 0] = blk[base + 1] = blk[base + 2] = blk[base + 3] = blk[base + 4] = blk[base + 5] = blk[base + 6] = blk[base + 7] = blk[base + 0] << 3; + return; + } + + x0 = (blk[base + 0] << 11) + 128; + + x8 = W7 * (x4 + x5); + x4 = x8 + (W1 - W7) * x4; + x5 = x8 - (W1 + W7) * x5; + x8 = W3 * (x6 + x7); + x6 = x8 - (W3 - W5) * x6; + x7 = x8 - (W3 + W5) * x7; + + x8 = x0 + x1; + x0 -= x1; + x1 = W6 * (x3 + x2); + x2 = x1 - (W2 + W6) * x2; + x3 = x1 + (W2 - W6) * x3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + blk[base + 0] = (x7 + x1) >> 8; + blk[base + 1] = (x3 + x2) >> 8; + blk[base + 2] = (x0 + x4) >> 8; + blk[base + 3] = (x8 + x6) >> 8; + blk[base + 4] = (x8 - x6) >> 8; + blk[base + 5] = (x0 - x4) >> 8; + blk[base + 6] = (x3 - x2) >> 8; + blk[base + 7] = (x7 - x1) >> 8; + } + + private static void idctcol(int[] blk, int base) { + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + if (0 == ((x1 = (blk[base + 8 * 4] << 8)) | (x2 = blk[base + 8 * 6]) | (x3 = blk[base + 8 * 2]) | + (x4 = blk[base + 8 * 1]) | (x5 = blk[base + 8 * 7]) | (x6 = blk[base + 8 * 5]) | (x7 = blk[base + 8 * 3]))) { + blk[base + 8 * 0] = blk[base + 8 * 1] = blk[base + 8 * 2] = blk[base + 8 * 3] = blk[base + 8 * 4] = blk[base + 8 * 5] = blk[base + 8 * 6] = blk[base + 8 * 7] = + clamp[1024 + ((blk[base + 8 * 0] + 32) >> 6)]; + return; + } + + x0 = (blk[base + 8 * 0] << 8) + 8192; + + x8 = W7 * (x4 + x5) + 4; + x4 = (x8 + (W1 - W7) * x4) >> 3; + x5 = (x8 - (W1 + W7) * x5) >> 3; + x8 = W3 * (x6 + x7) + 4; + x6 = (x8 - (W3 - W5) * x6) >> 3; + x7 = (x8 - (W3 + W5) * x7) >> 3; + + x8 = x0 + x1; + x0 -= x1; + x1 = W6 * (x3 + x2) + 4; + x2 = (x1 - (W2 + W6) * x2) >> 3; + x3 = (x1 + (W2 - W6) * x3) >> 3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + blk[base + 8 * 0] = clamp[1024 + ((x7 + x1) >> 14)]; + blk[base + 8 * 1] = clamp[1024 + ((x3 + x2) >> 14)]; + blk[base + 8 * 2] = clamp[1024 + ((x0 + x4) >> 14)]; + blk[base + 8 * 3] = clamp[1024 + ((x8 + x6) >> 14)]; + blk[base + 8 * 4] = clamp[1024 + ((x8 - x6) >> 14)]; + blk[base + 8 * 5] = clamp[1024 + ((x0 - x4) >> 14)]; + blk[base + 8 * 6] = clamp[1024 + ((x3 - x2) >> 14)]; + blk[base + 8 * 7] = clamp[1024 + ((x7 - x1) >> 14)]; + } + + public static void transform(int[] block) { + for (int i = 0; i < 64; i += 8) + idctrow(block, i); + + for (int i = 0; i < 8; i++) + idctcol(block, i); + } + + static { + for (int i = 0; i < 2048; i++) { + if (i < 1024) { + clamp[i] = 0; + } else if (i < (1024 + 256)) { + clamp[i] = i - 1024; + } else { + clamp[i] = 255; + } + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java new file mode 100644 index 0000000..e65aa02 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.mdec; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.DMAChannelOwnerBase; +import org.jpsx.runtime.util.MiscUtil; + +public class MDEC extends JPSXComponent implements MemoryMapped { + private static final Logger log = Logger.getLogger("MDEC"); + + private static final boolean debugMDEC = log.isDebugEnabled(); + + private static final int ADDR_MDEC_CTRL = 0x1f801820; + private static final int ADDR_MDEC_STATUS = 0x1f801824; + + // abe mdec_in_sync waits for bit 0x20000000 to clear + // abe mdec_out_sync waits for bit 0x01000000 to clear + private static final int NFIFO0 = 0x80000000; + private static final int FIFO1 = 0x40000000; + private static final int BUSY0 = 0x20000000; + private static final int DREQ0 = 0x10000000; + private static final int DREQ1 = 0x08000000; + private static final int RGB24 = 0x02000000; + private static final int BUSY1 = 0x01000000; + private static final int STP = 0x00800000; + +// private static final int BUSY0 = 0x80000000; +// private static final int DREQ0 = 0x40000000; +// private static final int DREQ1 = 0x20000000; + // private static final int RGB24 = 0x08000000; + // private static final int BUSY1 = 0x04000000; + // private static final int STP = 0x02000000; + private static final int CTRL_RGB24 = 0x08000000; + private static final int CTRL_STP = 0x02000000; + + private static final int[] yqm = new int[64]; + private static final int[] uvqm = new int[64]; + + private static final int unzig[] = new int[]{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, + 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, + 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 + }; + + private static AddressSpace addressSpace; + private static int ctrl; + private static int status; + private static int stp; + private static AddressSpace.ResolveResult source = new AddressSpace.ResolveResult(); + private static int sourceRemaining; + + public MDEC() { + super("JPSX Movie Decoder"); + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new InChannel()); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new OutChannel()); + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + } + + public void registerAddresses(AddressSpaceRegistrar registrar) { + registrar.registerWrite32Callback(ADDR_MDEC_CTRL, MDEC.class, "writeCtrl32"); + registrar.registerWrite32Callback(ADDR_MDEC_STATUS, MDEC.class, "writeStatus32"); + registrar.registerRead32Callback(ADDR_MDEC_CTRL, MDEC.class, "readCtrl32"); + registrar.registerRead32Callback(ADDR_MDEC_STATUS, MDEC.class, "readStatus32"); + } + + public static void writeStatus32(int address, int value) { + if (debugMDEC) log.debug("MDEC status write32 " + MiscUtil.toHex(value, 8)); + if (value == 0x80000000) { + if (debugMDEC) log.debug("MDEC turn off FIFO"); + status = value; + } else if (value == 0x60000000) { + if (debugMDEC) log.debug("MDEC turn on FIFO"); + status = value & ~BUSY0; + } else { + throw new IllegalStateException("MDEC unknown status write " + MiscUtil.toHex(value, 8)); + } + } + + public static void writeCtrl32(int address, int value) { + if (debugMDEC) log.debug("MDEC ctrl write32 " + MiscUtil.toHex(value, 8)); + + ctrl = value; + if (0 != (ctrl & CTRL_RGB24)) { + status &= ~RGB24; + } else { + status |= RGB24; + } + if (0 != (ctrl & CTRL_STP)) { + status |= STP; + stp = 0x8000; + } else { + status &= ~STP; + stp = 0; + } + } + + public static int readStatus32(int address) { + int rc = status; + if (debugMDEC) log.debug("MDEC status read32 " + MiscUtil.toHex(rc, 8)); + return rc; + } + + public static int readCtrl32(int address) { + //int rc = m_ctrl; + //if (debugMDEC) log.debug("MDEC ctrl read32 "+MiscUtil.toHex( rc, 8)); + //return rc; + throw new IllegalStateException("wahhh?"); + } + + private static class InChannel extends DMAChannelOwnerBase { + public final int getDMAChannel() { + return DMAController.DMA_MDEC_IN; + } + + public final String getName() { + return "MDEC-In"; + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + if (debugMDEC) + log.debug("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + int size = blocks * blockSize; + + if (MDEC.ctrl == 0x60000000) { + if (debugMDEC) log.debug("INIT COSINE TABLE size=" + MiscUtil.toHex(size, 4)); + } else if (MDEC.ctrl == 0x40000001) { + if (debugMDEC) log.debug("INIT QTABLE size=" + MiscUtil.toHex(size, 4)); + for (int i = 0; i < 64; i++) { + yqm[i] = addressSpace.read8(base + i); + } + for (int i = 0; i < 64; i++) { + uvqm[i] = addressSpace.read8(base + 64 + i); + } + // todo figure these commands out +// } else if (0!=(m_ctrl & BUSY0) && (0!=(m_ctrl&DREQ0)) && 0==(m_ctrl & NFIFO0)) { + } else { + //log.debug("MDEC cmd "+MiscUtil.toHex( m_ctrl, 8)); + if (debugMDEC) + log.debug("INCOMING DATA FROM " + MiscUtil.toHex(base, 8) + " SIZE = " + MiscUtil.toHex(size, 8) + " low16 = " + MiscUtil.toHex(MDEC.ctrl & 0xffff, 4)); + + //m_status |= BUSY0; +// m_status &= ~DREG0; +// m_status &= ~NFIFO0; + + addressSpace.resolve(base, size * 4, true, source); + sourceRemaining = size * 4; +// } else { +// throw new IllegalStateException("unknown MDEC ctrl = "+MiscUtil.toHex( m_ctrl, 8)); + } + signalTransferComplete(); + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + throw new IllegalStateException("unknown mdec dma from channel 0"); + //if (debugMDEC) log.debug( "begin DMA transfer from "+getName()+" "+MiscUtil.toHex( base, 8)+" 0x"+Integer.toHexString(blocks)+"*0x"+Integer.toHexString( blockSize)+" ctrl "+MiscUtil.toHex( ctrl, 8)); + //signalTransferComplete(); + } + + public void cancelDMATransfer(int ctrl) { + if (debugMDEC) log.debug("cancel " + getName() + " DMA transfer"); + } + } + + //private static final int SIGNED10BITS(x) + //{ + // return (x<<22)>>22; + //} + + private static class OutChannel extends DMAChannelOwnerBase { + private final int[] ycoeffs = new int[64]; + private final int[] ucoeffs = new int[64]; + private final int[] vcoeffs = new int[64]; + + public final int getDMAChannel() { + return DMAController.DMA_MDEC_OUT; + } + + public final String getName() { + return "MDEC-Out"; + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + throw new IllegalStateException("unknown mdec dma to channel 1"); +// if (debugMDEC) log.debug( "begin DMA transfer to "+getName()+" "+MiscUtil.toHex( base, 8)+" 0x"+Integer.toHexString(blocks)+"*0x"+Integer.toHexString( blockSize)+" ctrl "+MiscUtil.toHex( ctrl, 8)); +// signalTransferComplete(); + } + + + private static int rgb15(int y, int v, int u) { + int r = y + ((0x0000059B * u) >> 10); + int g = y + ((-0x15F * v) >> 10) + ((-0x2DB * u) >> 10); + int b = y + ((0x00000716 * v) >> 10); + if (r < 0) r = 0; + if (r > 255) r = 255; + if (g < 0) g = 0; + if (g > 255) g = 255; + if (b < 0) b = 0; + if (b > 255) b = 255; + return stp | ((b >> 3) << 10) + ((g >> 3) << 5) + (r >> 3); + } + + private static int rgb24(int y, int v, int u) { + int r = y + ((0x0000059B * u) >> 10); + int g = y + ((-0x15F * v) >> 10) + ((-0x2DB * u) >> 10); + int b = y + ((0x00000716 * v) >> 10); + if (r < 0) r = 0; + if (r > 255) r = 255; + if (g < 0) g = 0; + if (g > 255) g = 255; + if (b < 0) b = 0; + if (b > 255) b = 255; + return (r << 16) | (g << 8) | b; + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if (debugMDEC) + log.debug("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + + //assert 0!=(m_status&FIFO1); + // if (0==(m_status&FIFO1)) { + // m_status|=NFIFO0; + // signalTransferComplete(); + // } + //int baseTime = MTScheduler.getTime(); + //log.debug("configure mdec out time = "+baseTime); + int size = blocks * blockSize * 4; + + boolean rgb24 = 0 != (status & RGB24); + int mbsize = 256 * (rgb24 ? 3 : 2); + int mbcount = size / mbsize; + + AddressSpace.ResolveResult target = new AddressSpace.ResolveResult(); + addressSpace.resolve(base, size, false, target); + + int dword = source.mem[source.offset]; + + outer: + for (; mbcount > 0; mbcount--) { +// // make IRQ keep happening for sake of CD streaming +// r3000.checkAndHandleBreakout(); + if (debugMDEC) log.debug("mbcount " + mbcount + " remaining " + sourceRemaining); + for (int mb = 0; mb < 6; mb++) { + int word; + if (sourceRemaining <= 0) break outer; + if (0 == (sourceRemaining & 2)) { + dword = source.mem[source.offset]; + word = dword & 0xffff; + } else { + source.offset++; + word = (dword >> 16) & 0xffff; + } + sourceRemaining -= 2; + + int dc = (word & 0x3ff) ^ 0x200; + int qf = word >> 10; + + //if (mbcount==(size/mbsize)) dc = 0; + + int[] coeffs; + int[] qm; + if (mb == 0) { + coeffs = vcoeffs; + qm = uvqm; + } else if (mb == 1) { + coeffs = ucoeffs; + qm = uvqm; + } else { + coeffs = ycoeffs; + qm = yqm; + } + + for (int i = 1; i < 64; i++) coeffs[i] = 0; + coeffs[0] = dc * qm[0]; + + int index = 0; + do { + if (sourceRemaining <= 0) break outer; + if (0 == (sourceRemaining & 2)) { + dword = source.mem[source.offset]; + word = dword & 0xffff; + } else { + source.offset++; + word = (dword >> 16) & 0xffff; + } + sourceRemaining -= 2; + if (word == 0xfe00) + break; + index += (word >> 10) + 1; + coeffs[unzig[index]] = (qf * ((word << 22) >> 22) * qm[index]) >> 3; + } while (true); + + IDCT.transform(coeffs); + + final int[] mem = target.mem; + if (rgb24) { + if (mb >= 2) { + int uvoffset = 0; + int which = mb - 2; + int offset = target.offset; + if (0 != (which & 1)) { + offset += 6; + uvoffset += 4; + } + if (0 != (which & 2)) { + offset += 96; + uvoffset += 32; + } + for (int i = 0; i < 64; i += 4) { + int u0 = ucoeffs[uvoffset] - 128; + int u1 = ucoeffs[uvoffset + 1] - 128; + int v0 = vcoeffs[uvoffset] - 128; + int v1 = vcoeffs[uvoffset + 1] - 128; + + int p0 = coeffs[i]; + int p1 = coeffs[i + 1]; + int p2 = coeffs[i + 2]; + int p3 = coeffs[i + 3]; + int q0 = coeffs[i + 8]; + int q1 = coeffs[i + 9]; + int q2 = coeffs[i + 10]; + int q3 = coeffs[i + 11]; + + p0 = rgb24(p0, u0, v0); + p1 = rgb24(p1, u0, v0); + p2 = rgb24(p2, u1, v1); + p3 = rgb24(p3, u1, v1); + + mem[offset] = p0 | (p1 << 24); // b1r0g0b0 + mem[offset + 1] = ((p1 >> 8) & 0xffff) | (p2 << 16); // g2b2r1g1 + mem[offset + 2] = ((p2 >> 16) & 0xff) | (p3 << 8); // r3g3b3r2 + + q0 = rgb24(q0, u0, v0); + q1 = rgb24(q1, u0, v0); + q2 = rgb24(q2, u1, v1); + q3 = rgb24(q3, u1, v1); + + mem[offset + 12] = q0 | (q1 << 24); + mem[offset + 13] = ((q1 >> 8) & 0xffff) | (q2 << 16); + mem[offset + 14] = ((q2 >> 16) & 0xff) | (q3 << 8); + + offset += 3; + uvoffset += 2; + if (4 == (i & 7)) { + i += 8; + offset += 18; + uvoffset += 4; + } + } + } + } else { + if (mb >= 2) { + int uvoffset = 0; + int which = mb - 2; + int offset = target.offset; + if (0 != (which & 1)) { + offset += 4; + uvoffset += 4; + } + if (0 != (which & 2)) { + offset += 64; + uvoffset += 32; + } + for (int i = 0; i < 64; i += 4) { + int u0 = ucoeffs[uvoffset] - 128; + int u1 = ucoeffs[uvoffset + 1] - 128; + int v0 = vcoeffs[uvoffset] - 128; + int v1 = vcoeffs[uvoffset + 1] - 128; + + int p0 = coeffs[i]; + int p1 = coeffs[i + 1]; + int p2 = coeffs[i + 2]; + int p3 = coeffs[i + 3]; + int q0 = coeffs[i + 8]; + int q1 = coeffs[i + 9]; + int q2 = coeffs[i + 10]; + int q3 = coeffs[i + 11]; + + p0 = rgb15(p0, u0, v0); + p1 = rgb15(p1, u0, v0); + p2 = rgb15(p2, u1, v1); + p3 = rgb15(p3, u1, v1); + + mem[offset] = p0 | (p1 << 16); + mem[offset + 1] = p2 | (p3 << 16); + + q0 = rgb15(q0, u0, v0); + q1 = rgb15(q1, u0, v0); + q2 = rgb15(q2, u1, v1); + q3 = rgb15(q3, u1, v1); + + mem[offset + 8] = q0 | (q1 << 16); + mem[offset + 9] = q2 | (q3 << 16); + + offset += 2; + uvoffset += 2; + if (4 == (i & 7)) { + i += 8; + offset += 12; + uvoffset += 4; + } + } + } + } + } + target.offset += mbsize >> 2; + } + + + if (sourceRemaining == 0) { + if (debugMDEC) log.debug("COMPLETE!!"); + + status &= ~BUSY0; + status &= ~BUSY1; + } + + signalTransferComplete(); + //log.debug("end mdec out dtime = "+(MTScheduler.getTime()-baseTime)); + } + + public void cancelDMATransfer(int ctrl) { + if (debugMDEC) log.debug("cancel " + getName() + " DMA transfer"); + } + } +} \ No newline at end of file diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java new file mode 100644 index 0000000..f1b14be --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.media; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.hardware.cd.CDDrive; +import org.jpsx.api.components.hardware.cd.CDMedia; +import org.jpsx.api.components.hardware.cd.MediaException; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.CDUtil; +import org.jpsx.runtime.util.MiscUtil; + +import java.io.*; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.RandomAccessFile; + +public class CueBinImageDrive extends SingletonJPSXComponent implements CDDrive { + public static final String PROPERTY_IMAGE_FILE = "image"; + + private static final String CATEGORY = "CDImage"; + private static final Logger log = Logger.getLogger(CATEGORY); + private static final String DEFAULT_CUE_FILE = "rips/wipeoutxl.cue"; + private CDMedia currentMedia; + + private boolean refreshed = false; + + public CueBinImageDrive() { + super("JPSX CUE/BIN Image CD Drive"); + } + + public void init() { + super.init(); + HardwareComponentConnections.CD_DRIVE.set(this); + } + + public CDMedia getCurrentMedia() { + if (!refreshed) { + refreshMedia(); + refreshed = true; + } + return currentMedia; + } + + public boolean isDriveOpen() { + return false; + } + + public void refreshMedia() { + String cueFilename = getProperty(PROPERTY_IMAGE_FILE, DEFAULT_CUE_FILE); + currentMedia = CueBinImageMedia.create(cueFilename); + } + + private static class CueBinImageMedia implements CDMedia { + int first; + int last; + int[] msf = new int[100]; + TrackType[] trackType = new TrackType[100]; + byte[] byteBuf = new byte[2352]; + RandomAccessFile binFile; + + private CueBinImageMedia() { + } + + public TrackType getTrackType(int track) { + return trackType[track]; + } + + public static CueBinImageMedia create(String cueFilename) { + CueBinImageMedia rc = new CueBinImageMedia(); + if (!rc.parse(cueFilename)) { + return null; + } + return rc; + } + + private boolean parse(String cueFilename) { + LineNumberReader reader; + try { + reader = new LineNumberReader(new FileReader(cueFilename)); + } catch (IOException e) { + log.warn("Unable to open CUE file " + cueFilename+": "+e.getMessage()); + return false; + } + String binFilename = cueFilename; + + int offset = 150; + try { + first = 99; + last = 0; + int dot = binFilename.lastIndexOf("."); + if (dot >= 0) binFilename = binFilename.substring(0, dot) + ".bin"; + + String line = reader.readLine(); + int trackNum = -1; + while (line != null) { + line = line.trim(); + String uline = line.toUpperCase(); + if (uline.startsWith("TRACK")) { + trackNum = readNumber(line.substring(5)); + if (trackNum < first) first = trackNum; + if (trackNum > last) last = trackNum; + String typeString = uline.substring(8).trim(); + trackType[trackNum] = CDMedia.TrackType.UNKNOWN; + if (typeString.equals("MODE2/2352")) { + trackType[trackNum] = CDMedia.TrackType.MODE2_2352; + } else if (typeString.equals("AUDIO")) { + trackType[trackNum] = CDMedia.TrackType.AUDIO; + } + } else if (uline.startsWith("INDEX 01")) { + msf[trackNum] = toMSF(parseMSFStringAsLBA(line.substring(8)) + offset); + } else if (uline.startsWith("FILE")) { + int q1 = line.indexOf("\""); + if (q1 >= 0) { + int q2 = line.indexOf("\"", q1 + 1); + if (q2 >= q1) { + binFilename = line.substring(q1 + 1, q2); + } + } + } + line = reader.readLine(); + } + } catch (IOException e) { + log.warn("Error reading CUE file " + cueFilename); + return false; + } finally { + try { + reader.close(); + } catch (IOException e) { + } + } + // hack + binFilename = binFilename.replace('\\','/'); + binFilename = binFilename.toLowerCase(); + File file = new File(binFilename); + if (!file.exists()) { + file = new File(new File(cueFilename).getParent(), file.getName()); + log.info("try "+file); + if (file.exists()) { + binFilename = file.getAbsolutePath(); + } + } + binFile = null; + long length; + try { + binFile = new RandomAccessFile(binFilename, "r"); + length = binFile.length(); + } catch (IOException e) { + log.warn("Unable to open BIN file " + binFilename+": "+e.getMessage()); + return false; + } + msf[0] = toMSF(offset + (int) (length / 2352L)); + if (log.isDebugEnabled()) { + for (int i = first; i <= last; i++) { + log.debug("track " + i + " " + printMSF(msf[i])); + } + log.debug("end " + printMSF(msf[0])); + } + return true; + } + + public void readSector(int num, byte[] buffer) throws MediaException { + try { + // note findbugs complains about this, but we know that the value can't overflow + binFile.seek(num * 2352); + binFile.readFully(buffer, 0, 2352); + } catch (IOException e) { + throw new MediaException("readSector failed", e); + } + } + + public void readSector(int num, int[] buffer) throws MediaException { + try { + // note findbugs complains about this, but we know that the value can't overflow + binFile.seek(num * 2352); + binFile.readFully(byteBuf); + for (int i = 0; i < 2352 / 4; i++) { + buffer[i] = ((((int) byteBuf[i * 4 + 3]) & 0xff) << 24) | + ((((int) byteBuf[i * 4 + 2]) & 0xff) << 16) | + ((((int) byteBuf[i * 4 + 1]) & 0xff) << 8) | + ((((int) byteBuf[i * 4]) & 0xff)); + } + } catch (IOException e) { + throw new MediaException("readSector failed", e); + } + } + + public int getFirstTrack() { + return first; + } + + public int getLastTrack() { + return last; + } + + public int getTrackMSF(int trackIndex) { + return msf[trackIndex]; + } + + static int toMSF(int sector) { + int f = sector % 75; + sector /= 75; + int s = sector % 60; + sector /= 60; + int m = sector; + return (CDUtil.toBCD(m) << 16) | (CDUtil.toBCD(s) << 8) | CDUtil.toBCD(f); + } + + static String printMSF(int msf) { + int m = (msf & 0xff0000) >> 16; + int s = (msf & 0xff00) >> 8; + int f = msf & 0xff; + return MiscUtil.toHex(m, 2) + ":" + MiscUtil.toHex(s, 2) + ":" + MiscUtil.toHex(f, 2); + } + + static int readNumber(String s) { + // read a two digit number + int rc = 0; + s = s.trim(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (!Character.isDigit(c)) break; + rc = rc * 10 + (c - '0'); + } + return rc; + } + + static int parseMSFStringAsLBA(String msf) { + msf = msf.trim(); + int c1 = msf.indexOf(':'); + int c2 = msf.indexOf(':', c1 + 1); + int m = readNumber(msf.substring(0, c1)); + int s = readNumber(msf.substring(c1 + 1, c2)); + int f = readNumber(msf.substring(c2 + 1)); + return ((m * 60) + s) * 75 + f; + } + + } + +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java new file mode 100644 index 0000000..245256a --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java @@ -0,0 +1,2947 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.r3000; + +import org.apache.bcel.generic.*; +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.*; +import org.jpsx.runtime.FinalResolvedConnectionCache; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.R3000Impl; + +// todo move reg_hi/reg_lo into compilation context +public final class R3000InstructionSet extends JPSXComponent implements InstructionProvider { + public static final Logger log = Logger.getLogger("R3000 Instruction Set"); + + private static final String R3000_CLASS = R3000Impl.class.getName(); + private static final String CLASS = R3000InstructionSet.class.getName(); + + private static final boolean ignoreArithmeticOverflow = true; + + private static class Refs extends FinalResolvedConnectionCache { + public static final AddressSpace addressSpace = resolve(CoreComponentConnections.ADDRESS_SPACE); + public static final R3000 r3000 = resolve(CoreComponentConnections.R3000); + public static final int[] r3000Regs = resolve(CoreComponentConnections.R3000).getInterpreterRegs(); + public static final SCP scp = resolve(CoreComponentConnections.SCP); + } + + public R3000InstructionSet() { + super("JPSX R3000 Instruction Set"); + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); + } + + // instructions and interpreters + + public void addInstructions(InstructionRegistrar registrar) { + log.info("Adding R3000 instructions..."); + CPUInstruction i_add; + if (ignoreArithmeticOverflow) { + i_add = new CPUInstruction("add", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) + context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + int val = context.getRegValue(rs); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IADD()); + } + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IADD()); + } + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new IADD()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rs] + regs[rt]; + } + return true; + } + }; + } else { + i_add = new CPUInstruction("add", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + } + CPUInstruction i_addi; + if (ignoreArithmeticOverflow) { + i_addi = new CPUInstruction("addi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + assert false; + int val = context.getRegValue(rs) + imm; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rt); + } else { + context.emitGetReg(il, rs); + if (imm != 0) { + il.append(new PUSH(cp, imm)); + il.append(new IADD()); + } + context.emitSetReg(il, rt); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + if (rt != 0) { + regs[rt] = regs[rs] + imm; + } + return true; + } + }; + } else { + i_addi = new CPUInstruction("addi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + } + CPUInstruction i_addiu = new CPUInstruction("addiu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + int val = context.getRegValue(rs) + imm; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rt); + } else { + context.emitGetReg(il, rs); + if (imm != 0) { + il.append(new PUSH(cp, imm)); + il.append(new IADD()); + } + context.emitSetReg(il, rt); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + if (rt != 0) { + regs[rt] = regs[rs] + imm; + } + return true; + } + }; + CPUInstruction i_addu = new CPUInstruction("addu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) + context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + int val = context.getRegValue(rs); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IADD()); + } + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IADD()); + } + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new IADD()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rs] + regs[rt]; + } + return true; + } + }; + CPUInstruction i_and = new CPUInstruction("and", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) & context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + int val = context.getRegValue(rs); + context.emitGetReg(il, rt); + il.append(new PUSH(cp, val)); + il.append(new IAND()); + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + il.append(new PUSH(cp, val)); + il.append(new IAND()); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new IAND()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rs] & regs[rt]; + } + return true; + } + }; + CPUInstruction i_andi = new CPUInstruction("andi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + assert false; + int val = context.getRegValue(rs) & imm; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rt); + } else { + context.emitGetReg(il, rs); + if (imm != 0) { + il.append(new PUSH(cp, imm)); + il.append(new IAND()); + } + context.emitSetReg(il, rt); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + if (rt != 0) { + regs[rt] = regs[rs] & imm; + } + return true; + } + }; + CPUInstruction i_beq = new CPUInstruction("beq", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rs == rt) { + context.emitDelaySlot(il); + il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } else { + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + if (0 != (cr & (1 << rt))) { + // rs const, rt const + il.append(new PUSH(cp, context.getRegValue(rs))); + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitDelaySlot(il); + il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } else { + // rs const, rt varied + il.append(new PUSH(cp, context.getRegValue(rs))); + context.emitGetReg(il, rt); + context.emitDelaySlot(il); + il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + if (0 != (cr & (1 << rt))) { + // rs varied, rt const + context.emitGetReg(il, rs); + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitDelaySlot(il); + il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } else { + // rs varied, rt varied + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + context.emitDelaySlot(il); + il.append(new IF_ICMPEQ(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != R3000.Util.bits_rt(ci)) + return BRANCH_SOMETIMES; + return BRANCH_ALWAYS; + } + }; + CPUInstruction i_bgez = new CPUInstruction("bgez", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + context.emitDelaySlot(il); + if (context.getRegValue(rs) >= 0) { + il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + il.append(new IFGE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_ALWAYS; + } + }; + CPUInstruction i_bgezal = new CPUInstruction("bgezal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_LINK) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + int target = address + 4 + R3000.Util.signed_branch_delta(ci); + if (0 != (cr & (1 << rs))) { + log.warn("Untested constant bgezal"); + context.emitDelaySlot(il); + if (context.getRegValue(rs) >= 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, R3000.R_RETADDR); + context.emitCall(il, target, address + 8); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + // skip over the call if not GE + IFLT lt = new IFLT(null); + il.append(lt); + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, R3000.R_RETADDR); + context.emitCall(il, target, address + 8); + // Link up the to whatever comes next - since we don't now what that is, we'll insert a NOP + lt.setTarget(il.append(new NOP())); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_ALWAYS; + } + }; + CPUInstruction i_bgtz = new CPUInstruction("bgtz", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + context.emitDelaySlot(il); + if (context.getRegValue(rs) > 0) { + il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + il.append(new IFGT(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_NEVER; + } + }; + CPUInstruction i_blez = new CPUInstruction("blez", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + context.emitDelaySlot(il); + if (context.getRegValue(rs) <= 0) { + il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + il.append(new IFLE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_ALWAYS; + } + }; + CPUInstruction i_bltz = new CPUInstruction("bltz", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + context.emitDelaySlot(il); + if (context.getRegValue(rs) < 0) { + il.append(new GOTO(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + il.append(new IFLT(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_NEVER; + } + }; + CPUInstruction i_bltzal = new CPUInstruction("bltzal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET | CPUInstruction.FLAG_LINK) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + + int cr = context.getConstantRegs(); + int target = address + 4 + R3000.Util.signed_branch_delta(ci); + if (0 != (cr & (1 << rs))) { + log.warn("Untested constant bltzal"); + context.emitDelaySlot(il); + if (context.getRegValue(rs) < 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, R3000.R_RETADDR); + context.emitCall(il, target, address + 8); + } + } else { + context.emitGetReg(il, rs); + context.emitDelaySlot(il); + // skip over the call if not LT + IFGE ge = new IFGE(null); + il.append(ge); + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, R3000.R_RETADDR); + context.emitCall(il, target, address + 8); + // Link up the to whatever comes next - since we don't now what that is, we'll insert a NOP + ge.setTarget(il.append(new NOP())); + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != 0) + return BRANCH_SOMETIMES; + return BRANCH_NEVER; + } + }; + CPUInstruction i_bne = new CPUInstruction("bne", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_NEAR_TARGET) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rs != rt) { + // todo constant values! + int cr = context.getConstantRegs(); + if (0 != (cr & (1 << rs))) { + if (0 != (cr & (1 << rt))) { + // rs const, rt const + il.append(new PUSH(cp, context.getRegValue(rs))); + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitDelaySlot(il); + il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } else { + // rs const, rt varied + il.append(new PUSH(cp, context.getRegValue(rs))); + context.emitGetReg(il, rt); + context.emitDelaySlot(il); + il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } else { + if (0 != (cr & (1 << rt))) { + // rs varied, rt const + context.emitGetReg(il, rs); + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitDelaySlot(il); + il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } else { + // rs varied, rt varied + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + context.emitDelaySlot(il); + il.append(new IF_ICMPNE(context.getBranchTarget(address + 4 + R3000.Util.signed_branch_delta(ci)))); + } + } + } + } + + public int getBranchType(int ci) { + if (R3000.Util.bits_rs(ci) != R3000.Util.bits_rt(ci)) + return BRANCH_SOMETIMES; + return BRANCH_NEVER; + } + }; + CPUInstruction i_break = new CPUInstruction("break", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + CPUInstruction i_div = new CPUInstruction("div", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + // reg_lo = regs[rs]/regs[rt]; + // reg_hi = regs[rs]%regs[rt]; + + IFEQ gotoDivideByZero = null; + GOTO gotoWriteRegHi = null; + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + gotoDivideByZero = new IFEQ(null); + il.append(gotoDivideByZero); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, context.getRegValue(rs))); + } else { + context.emitGetReg(il, rs); + } + + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + il.append(new IDIV()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, context.getRegValue(rs))); + } else { + context.emitGetReg(il, rs); + } + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + il.append(new IREM()); + gotoWriteRegHi = new GOTO(null); + il.append(gotoWriteRegHi); + } + // Code for divide by zero + InstructionHandle end = il.getEnd(); + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, context.getRegValue(rs))); + } else { + context.emitGetReg(il, rs); + } + if (gotoDivideByZero != null) { + gotoDivideByZero.setTarget(end.getNext()); + } + il.append(new DUP()); + il.append(new PUSH(cp, 31)); + il.append(new ISHR()); + il.append(new PUSH(cp, 1)); + il.append(new ISHL()); + il.append(new PUSH(cp, 1)); + il.append(new ISUB()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + + InstructionHandle writeRegHi = il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); + if (gotoWriteRegHi != null) { + gotoWriteRegHi.setTarget(writeRegHi); + } + } + }; + + CPUInstruction i_divu = new CPUInstruction("divu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + //long a = longFromUnsigned( regs[rs]); + //long b = longFromUnsigned( regs[rt]); + //reg_lo = (int)(a/b); + //reg_hi = (int)(a%b); + + IFEQ gotoDivideByZero = null; + GOTO gotoWriteRegHi = null; + + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + gotoDivideByZero = new IFEQ(null); + il.append(gotoDivideByZero); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); + } else { + context.emitGetReg(il, rs); + emitLongFromUnsigned(cp, il); + } + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); + } else { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + } + il.append(new LDIV()); + il.append(new L2I()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); + } else { + context.emitGetReg(il, rs); + emitLongFromUnsigned(cp, il); + } + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); + } else { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + } + il.append(new LREM()); + il.append(new L2I()); + gotoWriteRegHi = new GOTO(null); + il.append(gotoWriteRegHi); + } + // Code for divide by zero + InstructionHandle divdieByZero = il.append(new PUSH(cp, -1)); + if (gotoDivideByZero != null) { + gotoDivideByZero.setTarget(divdieByZero); + } + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, context.getRegValue(rs))); + } else { + context.emitGetReg(il, rs); + } + InstructionHandle writeRegHi = il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); + if (gotoWriteRegHi != null) { + gotoWriteRegHi.setTarget(writeRegHi); + } + } + }; + CPUInstruction i_j = new CPUInstruction("j", R3000InstructionSet.class, 0, CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_FAR_TARGET | CPUInstruction.FLAG_UNCONDITIONAL) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + context.emitDelaySlot(il); + int delay = address + 4; + int target = delay & 0xf0000000; + target += ((ci & 0x3ffffff) << 2); + il.append(new GOTO(context.getBranchTarget(target))); + } + }; + CPUInstruction i_jal = new CPUInstruction("jal", R3000InstructionSet.class, 0, CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_IMM_FAR_TARGET | CPUInstruction.FLAG_UNCONDITIONAL | CPUInstruction.FLAG_LINK) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + context.emitDelaySlot(il); + int delay = address + 4; + int target = delay & 0xf0000000; + target += ((ci & 0x3ffffff) << 2); + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, R3000.R_RETADDR); + context.emitCall(il, target, address + 8); + } + }; + CPUInstruction i_jalr = new CPUInstruction("jalr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_UNCONDITIONAL | CPUInstruction.FLAG_LINK) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + + int rs = bits_rs(ci); + int rd = bits_rd(ci); + context.emitDelaySlot(il); + // todo constant! + context.emitGetReg(il, rs); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, address + 8)); + context.emitSetReg(il, rd); + } + context.emitCall(il, address + 8); + } + }; + CPUInstruction i_jr = new CPUInstruction("jr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_BRANCH | CPUInstruction.FLAG_UNCONDITIONAL) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + context.emitDelaySlot(il); + int r = bits_rs(ci); + if (0 != (context.getConstantRegs() & (1 << r))) { + context.emitJump(il, context.getRegValue(r)); + } else { + context.emitGetReg(il, bits_rs(ci)); + context.emitJump(il); + } + } + }; + + CPUInstruction i_lb = new CPUInstruction("lb", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM8) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem8(il, context.getRegValue(base) + offset, true); + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } else { + context.emitReadMem8(il, base, offset); + if (rt != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, 24)); + il.append(new ISHL()); + il.append(new PUSH(cp, 24)); + il.append(new ISHR()); + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + } + }; + CPUInstruction i_lbu = new CPUInstruction("lbu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM8) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem8(il, context.getRegValue(base) + offset, false); + } else { + context.emitReadMem8(il, base, offset); + } + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + }; + CPUInstruction i_lh = new CPUInstruction("lh", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM16) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem16(il, context.getRegValue(base) + offset, true); + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } else { + context.emitReadMem16(il, base, offset); + if (rt != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il.append(new PUSH(cp, 16)); + il.append(new ISHL()); + il.append(new PUSH(cp, 16)); + il.append(new ISHR()); + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + } + }; + CPUInstruction i_lhu = new CPUInstruction("lhu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM16) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem16(il, context.getRegValue(base) + offset, false); + } else { + context.emitReadMem16(il, base, offset); + } + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + }; + + CPUInstruction i_lui = new CPUInstruction("lui", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rt = bits_rt(ci); + if (rt != 0) { + il.append(new PUSH(context.getConstantPoolGen(), ci << 16)); + context.emitSetReg(il, rt); + } + } + + public boolean simulate(int ci, int[] regs) { + int rt = bits_rt(ci); + if (rt != 0) { + regs[rt] = ci << 16; + } + return true; + } + }; + CPUInstruction i_lw = new CPUInstruction("lw", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitReadMem32(il, context.getRegValue(base) + offset, false); + } else { + context.emitReadMem32(il, base, offset, false); + } + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + }; + CPUInstruction i_lwc1 = new CPUInstruction("lwc1", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + CPUInstruction i_lwc3 = new CPUInstruction("lwc3", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + CPUInstruction i_lwl = new CPUInstruction("lwl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + // regs[rt]=(regs[rt]&lwl_mask[addr&3])|(value<> low2x8 + // shift = 24 - low2x8; + + // regs[rt] + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + // mask + il.append(new PUSH(cp, 0x00ffffff)); + il.append(new ILOAD(low2x8)); + il.append(new ISHR()); + + // & + il.append(new IAND()); + + // value + context.emitReadMem32(il, base, offset, true); + + // shift + il.append(new PUSH(cp, 24)); + il.append(new ILOAD(low2x8)); + il.append(new ISUB()); + + // << + il.append(new ISHL()); + + // | + il.append(new IOR()); + } + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + }; + CPUInstruction i_lwr = new CPUInstruction("lwr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + // regs[rt]=(regs[rt]&lwr_mask[addr&3])|((value>>lwr_shift[addr&3])&~lwr_mask[addr&3]); + + if (0 != (context.getConstantRegs() & (1 << base))) { + // constant address + int addr = context.getRegValue(base) + offset; + int mask = lwr_mask[addr & 3]; + int shift = lwr_shift[addr & 3]; + + // regs[rt]&mask; + if (0 != (context.getConstantRegs() & (1 << rt))) { + int val = context.getRegValue(rt); + if (mask != 0) { + il.append(new PUSH(cp, val & mask)); + } + } else { + if (mask != 0) { + context.emitGetReg(il, rt); + il.append(new PUSH(cp, mask)); + il.append(new IAND()); + } + } + + // value>>shift + context.emitReadMem32(il, addr, true); + if (0 != shift) { + il.append(new PUSH(cp, shift)); + il.append(new ISHR()); + } + + if (0 != mask) { + int nmask = ~mask; + il.append(new PUSH(cp, nmask)); + il.append(new IAND()); + il.append(new IOR()); + } + } else { + // low2x8 = ((regs[base]+offset)&3) << 8 + int low2x8 = context.getTempLocal(0); + int mask = context.getTempLocal(1); + + context.emitGetReg(il, base); + if (offset != 0) { + il.append(new PUSH(cp, offset)); + il.append(new IADD()); + } + il.append(new PUSH(cp, 3)); + il.append(new IAND()); + il.append(new PUSH(cp, 3)); + il.append(new ISHL()); + il.append(new ISTORE(low2x8)); + + // private final static int[] lwr_mask = new int[] { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00}; + // private final static int[] lwr_shift = new int[] { 0, 8, 16, 24}; + + // mask = 0xffffff00 << (24 - low2x8); + // shift = low2x8 + + // regs[rt]&mask + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + } + + if (false) { + // for some reason this causes a MASSIVE slowdown, but I can't figure + // out why; the hotspot compiler produces identical code!!!... would be good + // to know so we don't hit similar things elsewhere. + il.append(new PUSH(cp, 0xffffff00)); + il.append(new PUSH(cp, 24)); + il.append(new ILOAD(low2x8)); + il.append(new ISUB()); + il.append(new ISHL()); + il.append(new IAND()); + } else { + il.append(new PUSH(cp, 24)); + il.append(new ILOAD(low2x8)); + il.append(new ISUB()); + il.append(new PUSH(cp, 0xffffff00)); + il.append(new SWAP()); + il.append(new ISHL()); + il.append(new ISTORE(mask)); + il.append(new ILOAD(mask)); + il.append(new IAND()); + } + + // value>>shift; + context.emitReadMem32(il, base, offset, true); + il.append(new ILOAD(low2x8)); + il.append(new ISHR()); + + // &~mask + il.append(new ILOAD(mask)); + il.append(new PUSH(cp, -1)); + il.append(new IXOR()); + il.append(new IAND()); + + il.append(new IOR()); + } + if (rt != 0) { + context.emitSetReg(il, rt); + } else { + il.append(new POP()); + } + } + }; + CPUInstruction i_mfhi = new CPUInstruction("mfhi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + //int rs = bits_rs( ci ); + //int rt = bits_rt( ci ); + int rd = bits_rd(ci); + if (rd != 0) { + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); + context.emitSetReg(il, rd); + } + + } + }; + CPUInstruction i_mflo = new CPUInstruction("mflo", R3000InstructionSet.class, 0, CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + //int rs = bits_rs( ci ); + //int rt = bits_rt( ci ); + int rd = bits_rd(ci); + if (rd != 0) { + il.append(new GETSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + context.emitSetReg(il, rd); + } + + } + }; + CPUInstruction i_mthi = new CPUInstruction("mthi", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS); + CPUInstruction i_mtlo = new CPUInstruction("mtlo", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS); + CPUInstruction i_mult = new CPUInstruction("mult", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + // long result = ((long)regs[rs])*((long)regs[rt]); + + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, (long) context.getRegValue(rs))); + } else { + context.emitGetReg(il, rs); + il.append(new I2L()); + } + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, (long) context.getRegValue(rt))); + } else { + context.emitGetReg(il, rt); + il.append(new I2L()); + } + il.append(new LMUL()); + il.append(new DUP2()); + il.append(new PUSH(cp, 32)); + il.append(new LSHR()); + il.append(new L2I()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); + il.append(new L2I()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + } + }; + CPUInstruction i_multu = new CPUInstruction("multu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + // long result = (longFromUnsigned(regs[rs]))*(longFromUnsigned(regs[rt])); + if (0 != (context.getConstantRegs() & (1 << rs))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rs)))); + } else { + context.emitGetReg(il, rs); + emitLongFromUnsigned(cp, il); + } + if (0 != (context.getConstantRegs() & (1 << rt))) { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); + } else { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + } + il.append(new LMUL()); + il.append(new DUP2()); + il.append(new PUSH(cp, 32)); + il.append(new LSHR()); + il.append(new L2I()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_hi", "I"))); + il.append(new L2I()); + il.append(new PUTSTATIC(context.getConstantPoolGen().addFieldref(R3000_CLASS, "reg_lo", "I"))); + } + }; + CPUInstruction i_nor = new CPUInstruction("nor", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = (context.getRegValue(rs) | context.getRegValue(rt)) ^ 0xffffffff; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + int val = context.getRegValue(rs); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IOR()); + } + il.append(new PUSH(cp, 0xffffffff)); + il.append(new IXOR()); + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IOR()); + } + il.append(new PUSH(cp, 0xffffffff)); + il.append(new IXOR()); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new IOR()); + il.append(new PUSH(cp, 0xffffffff)); + il.append(new IXOR()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = (regs[rs] | regs[rt]) ^ 0xffffffff; + } + return true; + } + }; + CPUInstruction i_or = new CPUInstruction("or", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) | context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + int val = context.getRegValue(rs); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IOR()); + } + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new IOR()); + } + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new IOR()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rs] | regs[rt]; + } + return true; + } + }; + CPUInstruction i_ori = new CPUInstruction("ori", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_WRITES_RT) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rt != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + int val = context.getRegValue(rs) | imm; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rt); + } else { + context.emitGetReg(il, rs); + if (imm != 0) { + il.append(new PUSH(cp, imm)); + il.append(new IOR()); + } + context.emitSetReg(il, rt); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + if (rt != 0) { + regs[rt] = regs[rs] | imm; + } + return true; + } + }; + CPUInstruction i_sb = new CPUInstruction("sb", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM16) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + InstructionList il2 = new InstructionList(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il2.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il2, rt); + } + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitWriteMem8(il, context.getRegValue(base) + offset, il2); + } else { + il.append(il2); + context.emitWriteMem8(il, base, offset); + } + il2.dispose(); + } + }; + + CPUInstruction i_sh = new CPUInstruction("sh", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM8) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + InstructionList il2 = new InstructionList(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il2.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il2, rt); + } + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitWriteMem16(il, context.getRegValue(base) + offset, il2); + } else { + il.append(il2); + context.emitWriteMem16(il, base, offset); + } + il2.dispose(); + } + }; + CPUInstruction i_sll = new CPUInstruction("sll", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int sa = bits_sa(ci); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rt) << sa; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + il.append(new PUSH(cp, sa)); + il.append(new ISHL()); + context.emitSetReg(il, rd); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int sa = bits_sa(ci); + if (rd != 0) { + regs[rd] = regs[rt] << sa; + } + return true; + } + }; + CPUInstruction i_sllv = new CPUInstruction("sllv", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int rs = bits_rs(ci); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + assert false; + int val = context.getRegValue(rt) << (context.getRegValue(rs) & 31); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + return; + } else { + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rs))) { + context.emitGetReg(il, rt); + il.append(new PUSH(cp, context.getRegValue(rs) & 31)); + } else { + context.emitGetReg(il, rt); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } + il.append(new ISHL()); + context.emitSetReg(il, rd); + } + } + + public boolean simulate(int ci, int[] regs) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int rs = bits_rs(ci); + if (rd != 0) { + regs[rd] = regs[rt] << (regs[rs] & 31); + } + return true; + } + }; + CPUInstruction i_slt = new CPUInstruction("slt", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + // regs[rd]=(regs[rs]imm + IFLT lt = new IFLT(null); + il.append(lt); + il.append(new ICONST(0)); + GOTO gt = new GOTO(null); + il.append(gt); + lt.setTarget(il.append(new ICONST(1))); + context.emitSetReg(il, rt); + // the goto is whatever got emitted after the ICONST(1); + gt.setTarget(lt.getTarget().getNext()); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + if (rt != 0) { + regs[rt] = (longFromUnsigned(regs[rs]) < (long) imm) ? 1 : 0; + } + return true; + } + }; + CPUInstruction i_sltu = new CPUInstruction("sltu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + //regs[rt] = (longFromUnsigned(regs[rs])rt + IFLT lt = new IFLT(null); + il.append(lt); + il.append(new ICONST(0)); + GOTO gt = new GOTO(null); + il.append(gt); + lt.setTarget(il.append(new ICONST(1))); + context.emitSetReg(il, rd); + // the goto is whatever got emitted after the ICONST(1); + gt.setTarget(lt.getTarget().getNext()); + + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = (longFromUnsigned(regs[rs]) < longFromUnsigned(regs[rt])) ? 1 : 0; + } + return true; + } + }; + CPUInstruction i_sra = new CPUInstruction("sra", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int sa = bits_sa(ci); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rt) >> sa; + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + il.append(new PUSH(cp, sa)); + il.append(new ISHR()); + context.emitSetReg(il, rd); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int sa = bits_sa(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rt] >> sa; + } + return true; + } + }; + CPUInstruction i_srav = new CPUInstruction("srav", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int rs = bits_rs(ci); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + assert false; + int val = context.getRegValue(rt) >> (context.getRegValue(rs) & 31); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + return; + } else { + il.append(new PUSH(cp, context.getRegValue(rt))); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rs))) { + context.emitGetReg(il, rt); + il.append(new PUSH(cp, context.getRegValue(rs) & 31)); + } else { + context.emitGetReg(il, rt); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } + il.append(new ISHR()); + context.emitSetReg(il, rd); + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = regs[rt] >> regs[rs]; + } + return true; + } + }; + CPUInstruction i_srl = new CPUInstruction("srl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int sa = bits_sa(ci); + // regs[rd] = (int)((longFromUnsigned(regs[rt]))>>sa); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = (int) (longFromUnsigned(context.getRegValue(rt)) >> sa); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + il.append(new PUSH(cp, sa)); + il.append(new LSHR()); + il.append(new L2I()); + context.emitSetReg(il, rd); + } + } + } + + public boolean simulate(int ci, int[] regs) { + int sa = bits_sa(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = (int) ((longFromUnsigned(regs[rt])) >> sa); + } + return true; + } + }; + CPUInstruction i_srlv = new CPUInstruction("srlv", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int rs = bits_rs(ci); + if (rd != 0) { + ConstantPoolGen cp = context.getConstantPoolGen(); + if (0 != (context.getConstantRegs() & (1 << rt))) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + assert false; + int val = (int) longFromUnsigned(context.getRegValue(rt)) >> (context.getRegValue(rs) & 31); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + return; + } else { + il.append(new PUSH(cp, longFromUnsigned(context.getRegValue(rt)))); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rs))) { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + il.append(new PUSH(cp, context.getRegValue(rs) & 31)); + } else { + context.emitGetReg(il, rt); + emitLongFromUnsigned(cp, il); + context.emitGetReg(il, rs); + il.append(new PUSH(cp, 31)); + il.append(new IAND()); + } + } + il.append(new LSHR()); + il.append(new L2I()); + context.emitSetReg(il, rd); + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + regs[rd] = (int) ((longFromUnsigned(regs[rt])) >> regs[rs]); + } + return true; + } + }; + CPUInstruction i_sub; + if (ignoreArithmeticOverflow) { + i_sub = new CPUInstruction("sub", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) - context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + il.append(new PUSH(cp, context.getRegValue(rs))); + context.emitGetReg(il, rt); + il.append(new ISUB()); + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new ISUB()); + } + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new ISUB()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + if (rd != 0) { + regs[rd] = regs[rs] - regs[rt]; + } + return true; + } + }; + } else { + i_sub = new CPUInstruction("sub", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD | CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + } + CPUInstruction i_subu = new CPUInstruction("subu", R3000InstructionSet.class, 0, CPUInstruction.FLAG_SIMULATABLE | CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_WRITES_RD) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + ConstantPoolGen cp = context.getConstantPoolGen(); + + if (rd != 0) { + if (0 != (context.getConstantRegs() & (1 << rs))) { + if (0 != (context.getConstantRegs() & (1 << rt))) { + assert false; + int val = context.getRegValue(rs) - context.getRegValue(rt); + il.append(new PUSH(cp, val)); + context.emitSetReg(il, rd); + } else { + il.append(new PUSH(cp, context.getRegValue(rs))); + context.emitGetReg(il, rt); + il.append(new ISUB()); + context.emitSetReg(il, rd); + } + } else { + if (0 != (context.getConstantRegs() & (1 << rt))) { + context.emitGetReg(il, rs); + int val = context.getRegValue(rt); + if (val != 0) { + il.append(new PUSH(cp, val)); + il.append(new ISUB()); + } + context.emitSetReg(il, rd); + } else { + context.emitGetReg(il, rs); + context.emitGetReg(il, rt); + il.append(new ISUB()); + context.emitSetReg(il, rd); + } + } + } + } + + public boolean simulate(int ci, int[] regs) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + if (rd != 0) { + regs[rd] = regs[rs] - regs[rt]; + } + return true; + } + }; + CPUInstruction i_sw = new CPUInstruction("sw", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + InstructionList il2 = new InstructionList(); + + if (0 != (context.getConstantRegs() & (1 << rt))) { + ConstantPoolGen cp = context.getConstantPoolGen(); + il2.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il2, rt); + } + if (0 != (context.getConstantRegs() & (1 << base))) { + context.emitWriteMem32(il, context.getRegValue(base) + offset, il2, false); + } else { + context.emitWriteMem32(il, base, offset, il2, false); + } + il2.dispose(); + } + }; + + CPUInstruction i_swc1 = new CPUInstruction("swc1", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + CPUInstruction i_swc3 = new CPUInstruction("swc3", R3000InstructionSet.class, 0, CPUInstruction.FLAG_MAY_SIGNAL_EXCEPTION); + CPUInstruction i_swl = new CPUInstruction("swl", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + InstructionList il2 = new InstructionList(); + // private static final int[] swl_mask = new int[] { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000}; + // private static final int[] swl_shift = new int[] { 24, 16, 8, 0}; + // value = (value&swl_mask[addr&3])|((regs[rt]>>swl_shift[addr&3])&~swl_mask[addr&3]); + + if (0 != (context.getConstantRegs() & (1 << base))) { + // constant address + int addr = context.getRegValue(base) + offset; + int mask = swl_mask[addr & 3]; + int shift = swl_shift[addr & 3]; + + // regs[rt]>>shift & ~mask; + if (0 != (context.getConstantRegs() & (1 << rt))) { + il2.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il2, rt); + } + if (0 != shift) { + il2.append(new PUSH(cp, shift)); + il2.append(new ISHR()); + } + if (mask != 0) { + il2.append(new PUSH(cp, ~mask)); + il2.append(new IAND()); + } + + // value&mask + context.emitReadMem32(il2, addr, true); + il2.append(new PUSH(cp, mask)); + il2.append(new IAND()); + + il2.append(new IOR()); + context.emitWriteMem32(il, addr, il2, true); + } else { + // low2x8 = ((regs[base]+offset)&3) << 8 + int low2x8 = context.getTempLocal(0); + int maskVar = context.getTempLocal(1); + context.emitGetReg(il2, base); + if (offset != 0) { + il2.append(new PUSH(cp, offset)); + il2.append(new IADD()); + } + il2.append(new PUSH(cp, 3)); + il2.append(new IAND()); + il2.append(new PUSH(cp, 3)); + il2.append(new ISHL()); + il2.append(new ISTORE(low2x8)); + + // mask = 0xffffff00 << low2x8 + // shift = 24 - low2x8; + + il2.append(new PUSH(cp, 0xffffff00)); + il2.append(new ILOAD(low2x8)); + il2.append(new ISHL()); + il2.append(new ISTORE(maskVar)); + + // regs[rt]>>shift & ~mask; + if (0 != (context.getConstantRegs() & (1 << rt))) { + il2.append(new PUSH(cp, context.getRegValue(rt))); + } else { + context.emitGetReg(il2, rt); + } + il2.append(new PUSH(cp, 24)); + il2.append(new ILOAD(low2x8)); + il2.append(new ISUB()); + il2.append(new ISHR()); + + il2.append(new ILOAD(maskVar)); + il2.append(new PUSH(cp, 0xffffffff)); + il2.append(new IXOR()); + il2.append(new IAND()); + + // value&mask; + context.emitReadMem32(il2, base, offset, true); + il2.append(new ILOAD(maskVar)); + il2.append(new IAND()); + + il2.append(new IOR()); + context.emitWriteMem32(il, base, offset, il2, true); + } + il2.dispose(); + } + }; + CPUInstruction i_swr = new CPUInstruction("swr", R3000InstructionSet.class, 0, CPUInstruction.FLAG_READS_RS | CPUInstruction.FLAG_READS_RT | CPUInstruction.FLAG_MEM32) { + public void compile(CompilationContext context, int address, int ci, InstructionList il) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + + ConstantPoolGen cp = context.getConstantPoolGen(); + + InstructionList il2 = new InstructionList(); + // private static final int[] swr_mask = new int[] { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff}; + // private static final int[] swr_shift = new int[] { 0, 8, 16, 24}; + // value = (value&swr_mask[addr&3])|(regs[rt]<> (24-low2x8) + // shift = low2x8; + + // regs[rt]<> 21) & 0x1f; + } + + private static final int bits_rt(final int ci) { + return (ci >> 16) & 0x1f; + } + + private static final int bits_rd(final int ci) { + return (ci >> 11) & 0x1f; + } + + private static final int bits_sa(final int ci) { + return (ci >> 6) & 0x1f; + } + + private static final boolean mask_bit31(int x) { + return (x < 0); + } + + private static final int bits25_6(int x) { + return (x >> 6) & 0xfffff; + } + + private static final int sign_extend(int x) { + return ((x) << 16) >> 16; + } + + private static final int signed_branch_delta(int x) { + return sign_extend(x) << 2; + } + + private static final int lo(int x) { + return x & 0xffff; + } + + private static final long longFromUnsigned(int x) { + return ((long) x) & 0xffffffffL; + } + + public static void interpret_add(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + int res = Refs.r3000Regs[rs] + Refs.r3000Regs[rt]; + + // arithmetic overflow if rs and rs have same top bit (i.e. sign) + // and the result has a different sign + if (!ignoreArithmeticOverflow) { + if (!mask_bit31(Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]) && mask_bit31(res ^ Refs.r3000Regs[rs])) { + Refs.scp.signalIntegerOverflowException(); + return; + } + } + if (rd != 0) { + Refs.r3000Regs[rd] = res; + } + } + + public static void interpret_addi(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + + int res = Refs.r3000Regs[rs] + imm; + + // arithmetic overflow if rs and rs have same top bit (i.e. sign) + // and the result has a different sign + if (!ignoreArithmeticOverflow) { + if (!mask_bit31(Refs.r3000Regs[rs] ^ imm) && mask_bit31(res ^ Refs.r3000Regs[rs])) { + Refs.scp.signalIntegerOverflowException(); + return; + } + } + if (rt != 0) { + Refs.r3000Regs[rt] = res; + } + } + + // getstatic #reg1 + // iconst imm + // iadd + // putstatic #reg2 + + public static void interpret_addiu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + + if (rt != 0) { + Refs.r3000Regs[rt] = Refs.r3000Regs[rs] + imm; + } + } + + public static void interpret_addu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rs] + Refs.r3000Regs[rt]; + } + } + + public static void interpret_and(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rs] & Refs.r3000Regs[rt]; + } + } + + public static void interpret_andi(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + + if (rt != 0) { + Refs.r3000Regs[rt] = Refs.r3000Regs[rs] & imm; + } + } + + public static void interpret_beq(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + if (Refs.r3000Regs[rs] == Refs.r3000Regs[rt]) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + public static void interpret_bgez(final int ci) { + int rs = bits_rs(ci); + + if (Refs.r3000Regs[rs] >= 0) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + public static void interpret_bgezal(final int ci) { + int rs = bits_rs(ci); + // note operation is undefined if rs==31 so we don't care + if (Refs.r3000Regs[rs] >= 0) { + Refs.r3000Regs[R3000.R_RETADDR] = Refs.r3000.getPC() + 8; // return address + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + } + + public static void interpret_bgtz(final int ci) { + int rs = bits_rs(ci); + + if (Refs.r3000Regs[rs] > 0) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + public static void interpret_blez(final int ci) { + int rs = bits_rs(ci); + + if (Refs.r3000Regs[rs] <= 0) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + public static void interpret_bltz(final int ci) { + int rs = bits_rs(ci); + + if (Refs.r3000Regs[rs] < 0) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + public static void interpret_bltzal(final int ci) { + int rs = bits_rs(ci); + // note operation is undefined if rs==31 so we don't care + if (Refs.r3000Regs[rs] < 0) { + Refs.r3000Regs[R3000.R_RETADDR] = Refs.r3000.getPC() + 8; // return address + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + } + + public static void interpret_bne(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + if (Refs.r3000Regs[rs] != Refs.r3000Regs[rt]) + Refs.r3000.interpreterBranch(signed_branch_delta(ci)); + } + + // todo recheck this; this is a hack to avoid problems with certain versions of HotSpot (perhaps 1.4?) + protected static boolean breakHotspot; + + public static void interpret_break(final int ci) { + // TODO - note this is used for division by zero in wipeout! + breakHotspot = false; + Refs.scp.signalBreakException(); + } + + public static void interpret_div(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + if (Refs.r3000Regs[rt] != 0) { + Refs.r3000.setLO(Refs.r3000Regs[rs] / Refs.r3000Regs[rt]); + Refs.r3000.setHI(Refs.r3000Regs[rs] % Refs.r3000Regs[rt]); + } else { + // According to docs, this is what it does + Refs.r3000.setLO(((Refs.r3000Regs[rs] >>> 31) << 1) - 1); + Refs.r3000.setHI(Refs.r3000Regs[rs]); + } + } + + public static void interpret_divu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + if (Refs.r3000Regs[rt] != 0) { + long a = longFromUnsigned(Refs.r3000Regs[rs]); + long b = longFromUnsigned(Refs.r3000Regs[rt]); + Refs.r3000.setLO((int) (a / b)); + Refs.r3000.setHI((int) (a % b)); + } else { + // According to docs, this is what it does + Refs.r3000.setLO(-1); + Refs.r3000.setHI(Refs.r3000Regs[rs]); + } + } + + public static void interpret_j(final int ci) { + int delay = Refs.r3000.getPC() + 4; + int target = delay & 0xf0000000; + target += ((ci & 0x3ffffff) << 2); + Refs.r3000.interpreterBranch(target - delay); + } + + + public static void interpret_jal(final int ci) { + int pc = Refs.r3000.getPC(); + int delay = pc + 4; + int target = (delay & 0xf0000000); + target += ((ci & 0x3ffffff) << 2); + + Refs.addressSpace.tagClearPollCounters(); + Refs.r3000Regs[R3000.R_RETADDR] = pc + 8; + Refs.r3000.interpreterJumpAndLink(target - delay, target, pc + 8); + } + + public static void interpret_jalr(final int ci) { + int rs = bits_rs(ci); + int rd = bits_rd(ci); + int pc = Refs.r3000.getPC(); + if (rd != 0) { + Refs.r3000Regs[rd] = pc + 8; + } + Refs.addressSpace.tagClearPollCounters(); + int delay = pc + 4; + int target = Refs.r3000Regs[rs]; + Refs.r3000.interpreterJumpAndLink(target - delay, target, pc + 8); + } + + public static void interpret_jr(final int ci) { + int rs = bits_rs(ci); + // for now, mask to low PC + int target = Refs.r3000Regs[rs]; + int delay = Refs.r3000.getPC() + 4; + Refs.r3000.interpreterJump(target - delay, target); + } + + public static void interpret_lb(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead8(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read8(addr); + //System.out.println("lb "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( (value<<24)>>24, 8)); + if (rt != 0) { + value = (value << 24) >> 24; + Refs.r3000Regs[rt] = value; + } + } + + public static void interpret_lbu(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead8(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read8(addr); + //System.out.println("lbu "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( value, 8)); + if (rt != 0) { + Refs.r3000Regs[rt] = value; + } + } + + public static void interpret_lh(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead16(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read16(addr); + //System.out.println("lh "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( (value<<16)>>16, 8)); + if (rt != 0) { + value = (value << 16) >> 16; + Refs.r3000Regs[rt] = value; + } + } + + public static void interpret_lhu(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead16(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read16(addr); + //System.out.println("lhu "+MiscUtil.toHex( addr, 8)+" "+MiscUtil.toHex( value, 8)); + if (rt != 0) { + Refs.r3000Regs[rt] = value; + } + } + + public static void interpret_lui(final int ci) { + int rt = bits_rt(ci); + if (rt != 0) { + Refs.r3000Regs[rt] = ci << 16; + } + } + + public static void interpret_lw(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read32(addr); + if (rt != 0) { + Refs.r3000Regs[rt] = value; + } + } + + public static void interpret_lwc1(final int ci) { + breakHotspot = false; + Refs.scp.signalReservedInstructionException(); + } + + public static void interpret_lwc3(final int ci) { + breakHotspot = false; + Refs.scp.signalReservedInstructionException(); + } + + private final static int[] lwl_mask = new int[]{0x00ffffff, 0x0000ffff, 0x000000ff, 0x00000000}; + private final static int[] lwl_shift = new int[]{24, 16, 8, 0}; + + public static void interpret_lwl(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read32(addr & ~3); + if (rt != 0) { + Refs.r3000Regs[rt] = (Refs.r3000Regs[rt] & lwl_mask[addr & 3]) | (value << lwl_shift[addr & 3]); + } + } + + private final static int[] lwr_mask = new int[]{0x00000000, 0xff000000, 0xffff0000, 0xffffff00}; + private final static int[] lwr_shift = new int[]{0, 8, 16, 24}; + + public static void interpret_lwr(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessRead32(Refs.r3000.getPC(), addr); + } + int value = Refs.addressSpace.read32(addr & ~3); + if (rt != 0) { + Refs.r3000Regs[rt] = (Refs.r3000Regs[rt] & lwr_mask[addr & 3]) | ((value >> lwr_shift[addr & 3]) & ~lwr_mask[addr & 3]); + } + } + + public static void interpret_mfhi(final int ci) { + int rd = bits_rd(ci); + Refs.r3000Regs[rd] = Refs.r3000.getHI(); + } + + public static void interpret_mflo(final int ci) { + int rd = bits_rd(ci); + Refs.r3000Regs[rd] = Refs.r3000.getLO(); + } + + public static void interpret_mthi(final int ci) { + int rs = bits_rs(ci); + Refs.r3000.setHI(Refs.r3000Regs[rs]); + } + + public static void interpret_mtlo(final int ci) { + int rs = bits_rs(ci); + Refs.r3000.setLO(Refs.r3000Regs[rs]); + } + + public static void interpret_mult(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + long result = ((long) Refs.r3000Regs[rs]) * ((long) Refs.r3000Regs[rt]); + Refs.r3000.setLO((int) result); + Refs.r3000.setHI((int) (result >> 32)); + } + + public static void interpret_multu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + + long result = (longFromUnsigned(Refs.r3000Regs[rs])) * (longFromUnsigned(Refs.r3000Regs[rt])); + Refs.r3000.setLO((int) result); + Refs.r3000.setHI((int) (result >> 32)); + } + + public static void interpret_nor(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = (Refs.r3000Regs[rs] | Refs.r3000Regs[rt]) ^ 0xffffffff; + } + } + + public static void interpret_or(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rs] | Refs.r3000Regs[rt]; + } + } + + public static void interpret_ori(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + if (rt != 0) { + Refs.r3000Regs[rt] = Refs.r3000Regs[rs] | lo(ci); + } + } + + public static void interpret_sb(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); + } + Refs.addressSpace.write8(addr, Refs.r3000Regs[rt]); + } + + public static void interpret_sh(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); + } + Refs.addressSpace.write16(addr, Refs.r3000Regs[rt]); + } + + public static void interpret_sll(final int ci) { + if (ci == 0) + return; // nop + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int sa = bits_sa(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rt] << sa; + } + } + + public static void interpret_sllv(final int ci) { + int rd = bits_rd(ci); + int rt = bits_rt(ci); + int rs = bits_rs(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rt] << (Refs.r3000Regs[rs] & 31); + } + } + + public static void interpret_slt(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = (Refs.r3000Regs[rs] < Refs.r3000Regs[rt]) ? 1 : 0; + } + } + + public static void interpret_slti(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = sign_extend(ci); + if (rt != 0) { + Refs.r3000Regs[rt] = (Refs.r3000Regs[rs] < imm) ? 1 : 0; + } + } + + public static void interpret_sltiu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int imm = lo(ci); + if (rt != 0) { + Refs.r3000Regs[rt] = (longFromUnsigned(Refs.r3000Regs[rs]) < (long) imm) ? 1 : 0; + } + } + + public static void interpret_sltu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = (longFromUnsigned(Refs.r3000Regs[rs]) < longFromUnsigned(Refs.r3000Regs[rt])) ? 1 : 0; + } + } + + public static void interpret_srl(final int ci) { + int sa = bits_sa(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = (int) ((longFromUnsigned(Refs.r3000Regs[rt])) >> sa); + } + } + + public static void interpret_srlv(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = (int) ((longFromUnsigned(Refs.r3000Regs[rt])) >> Refs.r3000Regs[rs]); + } + } + + public static void interpret_sra(final int ci) { + int sa = bits_sa(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rt] >> sa; + } + } + + public static void interpret_srav(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rt] >> Refs.r3000Regs[rs]; + } + } + + public static void interpret_sub(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + int res = Refs.r3000Regs[rs] - Refs.r3000Regs[rt]; + + // arithmetic overflow if rs and rs have different top bit (i.e. sign) + // and the result has a different sign to rs + if (!ignoreArithmeticOverflow) { + if (mask_bit31(Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]) && mask_bit31(res ^ Refs.r3000Regs[rs])) { + Refs.scp.signalIntegerOverflowException(); + return; + } + } + if (rd != 0) { + Refs.r3000Regs[rd] = res; + } + } + + public static void interpret_subu(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rs] - Refs.r3000Regs[rt]; + } + } + + public static void interpret_sw(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + if (base != R3000.R_SP) { + Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); + } + Refs.addressSpace.write32(addr, Refs.r3000Regs[rt]); + + // tmp hack + //if (addr==0x800dee54) { + // System.out.println("Write cdCurrentCmd "+MiscUtil.toHex( Refs.r3000Regs[rt], 8)+" at "+MiscUtil.toHex( Refs.r3000.getPC(), 8)); + // m_cpuCmdPending = true; + //} + } + + public static void interpret_swc1(final int ci) { + breakHotspot = false; + Refs.scp.signalReservedInstructionException(); + } + + public static void interpret_swc3(final int ci) { + breakHotspot = false; + Refs.scp.signalReservedInstructionException(); + } + + private static final int[] swl_mask = new int[]{0xffffff00, 0xffff0000, 0xff000000, 0x00000000}; + private static final int[] swl_shift = new int[]{24, 16, 8, 0}; + + public static void interpret_swl(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); + int value = Refs.addressSpace.read32(addr & ~3); + value = (value & swl_mask[addr & 3]) | ((Refs.r3000Regs[rt] >> swl_shift[addr & 3]) & ~swl_mask[addr & 3]); + Refs.addressSpace.write32(addr & ~3, value); + } + + private static final int[] swr_mask = new int[]{0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff}; + private static final int[] swr_shift = new int[]{0, 8, 16, 24}; + + public static void interpret_swr(final int ci) { + int base = bits_rs(ci); + int rt = bits_rt(ci); + int offset = sign_extend(ci); + int addr = Refs.r3000Regs[base] + offset; + Refs.addressSpace.tagAddressAccessWrite(Refs.r3000.getPC(), addr); + int value = Refs.addressSpace.read32(addr & ~3); + value = (value & swr_mask[addr & 3]) | (Refs.r3000Regs[rt] << swr_shift[addr & 3]); + Refs.addressSpace.write32(addr & ~3, value); + } + + public static void interpret_syscall(final int ci) { + breakHotspot = false; + Refs.scp.signalSyscallException(); + } + + public static void interpret_xor(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + int rd = bits_rd(ci); + if (rd != 0) { + Refs.r3000Regs[rd] = Refs.r3000Regs[rs] ^ Refs.r3000Regs[rt]; + } + } + + public static void interpret_xori(final int ci) { + int rs = bits_rs(ci); + int rt = bits_rt(ci); + if (rt != 0) { + Refs.r3000Regs[rt] = Refs.r3000Regs[rs] ^ lo(ci); + } + } + + public static void emitLongFromUnsigned(ConstantPoolGen cp, InstructionList il) { + il.append(new I2L()); + il.append(new PUSH(cp, 0xffffffffL)); + il.append(new LAND()); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java new file mode 100644 index 0000000..e59d201 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.sio; + +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Map; + +// todo allow different mappings +public class AWTKeyboardController extends StandardController implements KeyListener { + protected KeyMapping mapping; + + protected static final KeyMapping DEF_CONTROLLER_0_MAPPING; + + static { + DEF_CONTROLLER_0_MAPPING = new KeyMapping(); + + DEF_CONTROLLER_0_MAPPING.put(PADstart, KeyEvent.VK_SPACE); + DEF_CONTROLLER_0_MAPPING.put(PADselect, KeyEvent.VK_S); + DEF_CONTROLLER_0_MAPPING.put(PADLup, KeyEvent.VK_UP); + DEF_CONTROLLER_0_MAPPING.put(PADLleft, KeyEvent.VK_LEFT); + DEF_CONTROLLER_0_MAPPING.put(PADLright, KeyEvent.VK_RIGHT); + DEF_CONTROLLER_0_MAPPING.put(PADLdown, KeyEvent.VK_DOWN); + DEF_CONTROLLER_0_MAPPING.put(PADRup, KeyEvent.VK_8); + DEF_CONTROLLER_0_MAPPING.put(PADRup, KeyEvent.VK_KP_UP); + DEF_CONTROLLER_0_MAPPING.put(PADRdown, KeyEvent.VK_K); + DEF_CONTROLLER_0_MAPPING.put(PADRleft, KeyEvent.VK_KP_LEFT); + DEF_CONTROLLER_0_MAPPING.put(PADRright, KeyEvent.VK_I); + DEF_CONTROLLER_0_MAPPING.put(PADRright, KeyEvent.VK_KP_RIGHT); + DEF_CONTROLLER_0_MAPPING.put(PADRdown, KeyEvent.VK_KP_DOWN); + DEF_CONTROLLER_0_MAPPING.put(PADRleft, KeyEvent.VK_U); + DEF_CONTROLLER_0_MAPPING.put(PADL1, KeyEvent.VK_1); + DEF_CONTROLLER_0_MAPPING.put(PADL2, KeyEvent.VK_Q); + DEF_CONTROLLER_0_MAPPING.put(PADR1, KeyEvent.VK_2); + DEF_CONTROLLER_0_MAPPING.put(PADR2, KeyEvent.VK_W); + } + + public static class KeyMapping { + private Map map = CollectionsFactory.newHashMap(); + + public int get(int vkey) { + Integer mask = map.get(vkey); + if (mask != null) + return mask; + return 0; + } + + public void put(int mask, int vkey) { + map.put(vkey, mask); + } + } + + public AWTKeyboardController() { + this(DEF_CONTROLLER_0_MAPPING); + } + + public AWTKeyboardController(KeyMapping mapping) { + super("JPSX AWT Keyboard Controller"); + this.mapping = mapping; + } + + @Override + public void init() { + super.init(); + RuntimeConnections.KEY_LISTENERS.add(this); + } + + public void resolveConnections() { + // for now just connect to the left serial port + HardwareComponentConnections.LEFT_PORT_INSTANCE.resolve().connect(this); + } + + public void keyTyped(KeyEvent e) { + } + + public void keyPressed(KeyEvent e) { + int vkey = e.getKeyCode(); + pressed(mapping.get(vkey)); + } + + public void keyReleased(KeyEvent e) { + int vkey = e.getKeyCode(); + released(mapping.get(vkey)); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java new file mode 100644 index 0000000..35da454 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.sio; + +import org.jpsx.api.components.hardware.sio.SerialDevice; +import org.jpsx.runtime.JPSXComponent; + +/** + * just old BIOS style pad - no two way comms + */ +public abstract class BasicPad extends JPSXComponent implements SerialDevice { + public abstract int getType(); // e.g. 0x41 for standard controller (type and size really!) + + public abstract void getState(byte[] buffer); + + protected BasicPad(String description) { + super(description); + } + + protected byte[] rxBuffer = new byte[32]; + protected byte[] txBuffer = new byte[32]; + protected int state; + protected int txIndex; + + public void prepareForTransfer() { + getState(rxBuffer); + state = 0; + txIndex = 0; + } + + public int receive() { + int rc; + if (state == 0) { + rc = 0x00; + } else if (state == 1) { + rc = getType(); + if (rc == 0x41) { + if (txBuffer[0] == 0x43) { + rc = 0x43; + } + if (txBuffer[0] == 0x45) { + rc = 0xf3; + } + } + } else if (state == 2) { + rc = 0x5a; + } else { + rc = rxBuffer[state - 3]; + } + state++; + return rc; + } + + public void send(int data) { + txBuffer[txIndex++] = (byte) data; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/SIO0.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/SIO0.java new file mode 100644 index 0000000..a96e2cc --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/SIO0.java @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.sio; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.irq.IRQController; +import org.jpsx.api.components.hardware.sio.SerialDevice; +import org.jpsx.api.components.hardware.sio.SerialPort; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.IRQOwnerBase; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +public class SIO0 extends SingletonJPSXComponent implements MemoryMapped { + private static final Logger log = Logger.getLogger("SIO0"); + private static final boolean debugSIO = false; + + private static final int ADDR_SIO0_DATA = 0x1f801040; + private static final int ADDR_SIO0_STATUS = 0x1f801044; + private static final int ADDR_SIO0_MODE = 0x1f801048; + private static final int ADDR_SIO0_CTRL = 0x1f80104a; + private static final int ADDR_SIO0_BAUD = 0x1f80104e; + + private static final int CTL_TX_ENABLE = 0x0001; + private static final int CTL_DTR = 0x0002; + private static final int CTL_RX_ENABLE = 0x0004; + private static final int CTL_ERR_RESET = 0x0010; + private static final int CTL_RESET = 0x0040; + private static final int CTL_DSR_IRQ = 0x1000; + private static final int CTL_SELECT = 0x2000; + + private static final int STAT_TX_READY = 0x0001; // can become set without anything connected + private static final int STAT_RX_READY = 0x0002; // can become set without anything connected + private static final int STAT_TX_EMPTY = 0x0004; + private static final int STAT_PARITY_ERR = 0x0008; + private static final int STAT_RX_OVERRUN = 0x0010; + private static final int STAT_FRAMING_ERR = 0x0020; + private static final int STAT_SYNC_DETEXT = 0x0040; + private static final int STAT_DSR = 0x0080; + private static final int STAT_CTS = 0x0100; + private static final int STAT_IRQ = 0x0200; + + private static SerialDevice[] devices = new SerialDevice[2]; + + public SIO0() { + super("JPSX Serial Controller 0"); + } + + public void init() { + super.init(); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + HardwareComponentConnections.LEFT_PORT_INSTANCE.set(new Port(0)); + HardwareComponentConnections.RIGHT_PORT_INSTANCE.set(new Port(1)); + irq = new IRQ(); + CoreComponentConnections.IRQ_OWNERS.add(irq); + } + + private static class Port implements SerialPort { + private int index; + + public Port(int index) { + this.index = index; + } + + public void connect(SerialDevice device) { + connectDevice(index, device); + } + + public void disconnect() { + disconnectDevice(index); + } + } + + private static void connectDevice(int which, SerialDevice device) { + devices[which] = device; + log.info("Connected " + device.getDescription() + " to port " + which); + } + + private static void disconnectDevice(int which) { + devices[which] = null; + } + + private static class IRQ extends IRQOwnerBase { + public IRQ() { + super(IRQController.IRQ_SIO0, "SIO0"); + } + } + + private static IRQ irq; + + public void registerAddresses(AddressSpaceRegistrar registrar) { + registrar.registerWrite8Callback(ADDR_SIO0_DATA, SIO0.class, "writeData8"); + registrar.registerWrite16Callback(ADDR_SIO0_DATA, SIO0.class, "writeData16"); + registrar.registerWrite32Callback(ADDR_SIO0_DATA, SIO0.class, "writeData32"); + registrar.registerRead8Callback(ADDR_SIO0_DATA, SIO0.class, "readData8"); + registrar.registerRead16Callback(ADDR_SIO0_DATA, SIO0.class, "readData16"); + registrar.registerRead32Callback(ADDR_SIO0_DATA, SIO0.class, "readData32"); + + registrar.registerWrite16Callback(ADDR_SIO0_MODE, SIO0.class, "writeMode16"); + registrar.registerRead16Callback(ADDR_SIO0_MODE, SIO0.class, "readMode16"); + registrar.registerWrite16Callback(ADDR_SIO0_CTRL, SIO0.class, "writeCtrl16"); + registrar.registerRead16Callback(ADDR_SIO0_CTRL, SIO0.class, "readCtrl16"); + registrar.registerWrite16Callback(ADDR_SIO0_BAUD, SIO0.class, "writeBaud16"); + registrar.registerRead16Callback(ADDR_SIO0_BAUD, SIO0.class, "readBaud16"); + registrar.registerRead16Callback(ADDR_SIO0_STATUS, SIO0.class, "readStatus16"); + } + + private static int m_baud; + private static int m_mode; + private static int m_ctrl; + private static int m_status; + + private static boolean communicating = false; + + private static SerialDevice currentDevice; + + public static void writeData8(int address, int value) { + value &= 0xff; + if (debugSIO) System.out.println("SIO DATA WRITE 8 " + MiscUtil.toHex(value, 2)); + if (!communicating) { + if (value == 1) { + currentDevice = 0 == (m_ctrl & CTL_SELECT) ? devices[0] : devices[1]; + if (currentDevice != null) + currentDevice.prepareForTransfer(); + if (debugSIO) { + System.out.println("Select SIO device: " + ((currentDevice == null) ? "not connected" : currentDevice.getDescription())); + } + communicating = true; + } else if (value == 0x81) { + if (log.isDebugEnabled()) { + log.debug("CARD SELECT " + (((m_ctrl & CTL_SELECT) != 0) ? "1" : "0")); + } + } + } else { + if (currentDevice != null) { + if (value == 0x43) { + m_status |= STAT_DSR; + } + currentDevice.send(value); + } + } + m_status |= STAT_RX_READY; + } + + public static void writeData16(int address, int value) { + if (debugSIO) System.out.println("SIO DATA WRITE 16 " + MiscUtil.toHex(value, 16)); + } + + public static void writeData32(int address, int value) { + if (debugSIO) System.out.println("SIO DATA WRITE 32 " + MiscUtil.toHex(value, 32)); + } + + public static int readData8(int address) { + int rc = 0; + + // this isn't probably right, however the bios does... + + // (enable DSR IRQ) + // write data + // sleep + // clear IRQ + // wait for receive ready + // read data + // wait for IRQ + // + // ideally the irq should just be delayed... still this is OK for now + if (currentDevice != null) + rc = currentDevice.receive(); + + if (debugSIO) System.out.println("SIO DATA READ 8 " + MiscUtil.toHex(rc, 2)); + if (0 != (m_ctrl & CTL_DSR_IRQ)) { + if (currentDevice != null) { + if (debugSIO) { + System.out.println("SIO setting DSR IRQ at end of read from connected device!"); + } + m_status |= STAT_IRQ; + irq.raiseIRQ(); + } + } + m_status &= ~STAT_RX_READY; + return rc; + } + + public static int readData16(int address) { + int rc = 0; + if (debugSIO) System.out.println("SIO DATA READ 16 " + MiscUtil.toHex(rc, 4)); + return rc; + } + + public static int readData32(int address) { + int rc = 0; + if (debugSIO) System.out.println("SIO DATA READ 32 " + MiscUtil.toHex(rc, 8)); + return rc; + } + + public static void writeMode16(int address, int value) { + m_mode = value & 0xffff; + if (debugSIO) System.out.println("SIO MODE WRITE 16 " + MiscUtil.toHex(m_mode, 4)); + } + + public static int readMode16(int address) { + if (debugSIO) System.out.println("SIO MODE READ 16 " + MiscUtil.toHex(m_mode, 4)); + return m_mode; + } + + public static void writeCtrl16(int address, int value) { + if (debugSIO) System.out.println("SIO CTRL WRITE 16 " + MiscUtil.toHex(value, 4)); + m_ctrl = value & ~CTL_ERR_RESET; + // todo some things + if (0 != (m_ctrl & CTL_RESET)) { + if (debugSIO) System.out.println("SIO0 RESET"); + m_status |= STAT_TX_READY; + m_status &= ~STAT_DSR; + communicating = false; + } + if (0 != (value & CTL_ERR_RESET)) { + m_status &= ~STAT_IRQ; + } + if (value == 0) { + currentDevice = null; + communicating = false; + } + } + + public static int readCtrl16(int address) { + int rc = m_ctrl; + if (debugSIO) System.out.println("SIO CTRL READ 16 " + MiscUtil.toHex(rc, 4)); + return rc; + } + + public static void writeBaud16(int address, int value) { + m_baud = value; + if (debugSIO) System.out.println("SIO BAUD WRITE 16 " + MiscUtil.toHex(m_baud, 4)); + } + + public static int readBaud16(int address) { + if (debugSIO) System.out.println("SIO BAUD READ 16 " + MiscUtil.toHex(m_baud, 4)); + return m_baud; + } + + public static int readStatus16(int address) { + int rc = m_status; + if (debugSIO) System.out.println("SIO STATUS READ 16 " + MiscUtil.toHex(rc, 4)); + return rc; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/StandardController.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/StandardController.java new file mode 100644 index 0000000..d5a4d99 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/sio/StandardController.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.sio; + +public abstract class StandardController extends BasicPad { + protected int padState = 0xffff; + + protected StandardController(String description) { + super(description); + } + + public static final int PADLup = (1 << 12); + public static final int PADLdown = (1 << 14); + public static final int PADLleft = (1 << 15); + public static final int PADLright = (1 << 13); + public static final int PADRup = (1 << 4); + public static final int PADRdown = (1 << 6); + public static final int PADRleft = (1 << 7); + public static final int PADRright = (1 << 5); + + public static final int PADi = (1 << 9); + public static final int PADj = (1 << 10); + public static final int PADk = (1 << 8); + public static final int PADl = (1 << 3); + public static final int PADm = (1 << 1); + public static final int PADn = (1 << 2); + public static final int PADo = (1 << 0); + public static final int PADh = (1 << 11); + + public static final int PADL1 = PADn; + public static final int PADL2 = PADo; + public static final int PADR1 = PADl; + public static final int PADR2 = PADm; + public static final int PADstart = PADh; + public static final int PADselect = PADk; + + public int getType() { + return 0x41; + } + + public void getState(byte[] state) { + state[0] = (byte) ((padState >> 8) & 0xff); + state[1] = (byte) (padState & 0xff); + } + + public void pressed(int mask) { + padState &= ~mask; +// System.out.println("Controller state now: "+MiscUtil.toHex( padState, 4)); + } + + public void released(int mask) { + padState |= mask; +// System.out.println("Controller state now: "+MiscUtil.toHex( padState, 4)); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java new file mode 100644 index 0000000..1a653f0 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.spu; + +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.DMAChannelOwnerBase; +import org.jpsx.runtime.util.MiscUtil; + +/** + * Empty SPU that does enough to not prevent games from working at all + */ +public class NullSPU extends SingletonJPSXComponent implements MemoryMapped { + protected static final int ADDR_VOICES = 0x1f801c00; + + protected static final int ADDR_MAIN_VOL_L = 0x1f801d80; + protected static final int ADDR_MAIN_VOL_R = 0x1f801d82; + protected static final int ADDR_REVERB_L = 0x1f801d84; + protected static final int ADDR_REVERB_R = 0x1f801d86; + protected static final int ADDR_CHANNEL_ON0 = 0x1f801d88; + protected static final int ADDR_CHANNEL_ON1 = 0x1f801d8a; + protected static final int ADDR_CHANNEL_OFF0 = 0x1f801d8c; + protected static final int ADDR_CHANNEL_OFF1 = 0x1f801d8e; + protected static final int ADDR_CHANNEL_FM0 = 0x1f801d90; + protected static final int ADDR_CHANNEL_FM1 = 0x1f801d92; + protected static final int ADDR_CHANNEL_NOISE0 = 0x1f801d94; + protected static final int ADDR_CHANNEL_NOISE1 = 0x1f801d96; + protected static final int ADDR_CHANNEL_REVERB0 = 0x1f801d98; + protected static final int ADDR_CHANNEL_REVERB1 = 0x1f801d9a; + protected static final int ADDR_CHANNEL_MUTE0 = 0x1f801d9c; + protected static final int ADDR_CHANNEL_MUTE1 = 0x1f801d9e; + + protected static final int ADDR_TRANSFER_ADDR = 0x1f801da6; + protected static final int ADDR_TRANSFER_DATA = 0x1f801da8; + + protected static final int ADDR_SPU_CTRL = 0x1f801daa; + protected static final int ADDR_SPU_STATUS = 0x1f801dae; + + protected static final int ADDR_CD_VOL_L = 0x1f801db0; + protected static final int ADDR_CD_VOL_R = 0x1f801db2; + + protected static final int VOICES = 24; + + protected static final int VOICE_VOL_L = 0x0; + protected static final int VOICE_VOL_R = 0x2; + protected static final int VOICE_PITCH = 0x4; + protected static final int VOICE_START_OFFSET = 0x6; + protected static final int VOICE_ADS_LEVEL = 0x8; + protected static final int VOICE_SR_RATE = 0xa; + protected static final int VOICE_ADSR_VOL = 0xc; + protected static final int VOICE_REPEAT_OFFSET = 0xe; + + protected static int m_ctrl; + protected static int m_transferAddress; + + public NullSPU() { + super("JPSX Null (no sound) SPU"); + } + + + @Override + public void init() { + super.init(); + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new SPUDMAChannel()); + } + + // figure out RAM + public void registerAddresses(AddressSpaceRegistrar registrar) { + + for (int i = 0; i < VOICES; i++) { + int base = ADDR_VOICES + i * 0x10; + registrar.registerWrite16Callback(base + VOICE_VOL_L, NullSPU.class, "writeVolLeft"); + registrar.registerWrite16Callback(base + VOICE_VOL_R, NullSPU.class, "writeVolRight"); + registrar.registerWrite16Callback(base + VOICE_PITCH, NullSPU.class, "writePitch"); + registrar.registerWrite16Callback(base + VOICE_START_OFFSET, NullSPU.class, "writeStartOffset"); + registrar.registerWrite16Callback(base + VOICE_ADS_LEVEL, NullSPU.class, "writeADSLevel"); + registrar.registerWrite16Callback(base + VOICE_SR_RATE, NullSPU.class, "writeSRRate"); + registrar.registerWrite16Callback(base + VOICE_ADSR_VOL, NullSPU.class, "writeADSRVol"); + registrar.registerWrite16Callback(base + VOICE_REPEAT_OFFSET, NullSPU.class, "writeRepeatOffset"); + } + registrar.registerWrite16Callback(ADDR_MAIN_VOL_L, NullSPU.class, "writeMainVolLeft"); + registrar.registerWrite16Callback(ADDR_MAIN_VOL_R, NullSPU.class, "writeMainVolRight"); + registrar.registerWrite16Callback(ADDR_REVERB_L, NullSPU.class, "writeReverbLeft"); + registrar.registerWrite16Callback(ADDR_REVERB_R, NullSPU.class, "writeReverbRight"); + registrar.registerWrite16Callback(ADDR_CHANNEL_ON0, NullSPU.class, "writeChannelOn0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_ON1, NullSPU.class, "writeChannelOn1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_OFF0, NullSPU.class, "writeChannelOff0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_OFF1, NullSPU.class, "writeChannelOff1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_FM0, NullSPU.class, "writeChannelFM0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_FM1, NullSPU.class, "writeChannelFM1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE0, NullSPU.class, "writeChannelNoise0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE1, NullSPU.class, "writeChannelNoise1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB0, NullSPU.class, "writeChannelReverb0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB1, NullSPU.class, "writeChannelReverb1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE0, NullSPU.class, "writeChannelMute0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE1, NullSPU.class, "writeChannelMute1"); + + registrar.registerWrite16Callback(ADDR_SPU_CTRL, NullSPU.class, "writeSPUCtrl"); + registrar.registerRead16Callback(ADDR_SPU_CTRL, NullSPU.class, "readSPUCtrl"); + + registrar.registerWrite16Callback(ADDR_CD_VOL_L, NullSPU.class, "writeCDVolL"); + registrar.registerWrite16Callback(ADDR_CD_VOL_R, NullSPU.class, "writeCDVolR"); + + registrar.registerRead16Callback(ADDR_SPU_STATUS, NullSPU.class, "readSPUStatus"); + + registrar.registerWrite16Callback(ADDR_TRANSFER_ADDR, NullSPU.class, "writeTransferAddr"); + registrar.registerWrite16Callback(ADDR_TRANSFER_DATA, NullSPU.class, "writeTransferData"); + registrar.registerRead16Callback(ADDR_TRANSFER_ADDR, NullSPU.class, "readTransferAddr"); + } + + public static void writeVolLeft(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeVolRight(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writePitch(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeStartOffset(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeADSLevel(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeSRRate(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeADSRVol(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeRepeatOffset(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + } + + public static void writeMainVolLeft(int address, int val) { + } + + public static void writeMainVolRight(int address, int val) { + } + + public static void writeReverbLeft(int address, int val) { + } + + public static void writeReverbRight(int address, int val) { + } + + public static void writeChannelOn0(int address, int val) { + for (int i = 0; i < 16; i++) { + if (0 != (val & (1 << i))) { + //System.out.println("SPU Voice "+i+" on"); + } + } + } + + public static void writeChannelOn1(int address, int val) { + for (int i = 0; i < 8; i++) { + if (0 != (val & (1 << i))) { + //System.out.println("SPU Voice "+(i+16)+" on"); + } + } + } + + public static void writeChannelOff0(int address, int val) { + for (int i = 0; i < 16; i++) { + if (0 != (val & (1 << i))) { + //System.out.println("SPU Voice "+i+" off"); + } + } + } + + public static void writeChannelOff1(int address, int val) { + for (int i = 0; i < 8; i++) { + if (0 != (val & (1 << i))) { + //System.out.println("SPU Voice "+(i+16)+" off"); + } + } + } + + public static void writeChannelFM0(int address, int val) { + } + + public static void writeChannelFM1(int address, int val) { + } + + public static void writeChannelNoise0(int address, int val) { + } + + public static void writeChannelNoise1(int address, int val) { + } + + public static void writeChannelReverb0(int address, int val) { + } + + public static void writeChannelReverb1(int address, int val) { + } + + public static void writeChannelMute0(int address, int val) { + } + + public static void writeChannelMute1(int address, int val) { + } + + public static void writeSPUCtrl(int address, int val) { + m_ctrl = val; + } + + public static int readSPUCtrl(int address) { + return m_ctrl; + } + + public static void writeCDVolL(int address, int val) { + } + + public static void writeCDVolR(int address, int val) { + } + + public static void writeTransferAddr(int address, int val) { + m_transferAddress = val & 0xffff; + } + + public static int readTransferAddr(int address) { + return m_transferAddress; + } + + public static void writeTransferData(int address, int val) { + } + + static boolean toggle; + + public static int readSPUStatus(int address) { + toggle = !toggle; +// System.out.println("READ SPU STATUS!"); + return toggle ? 0x400 : 0; + } + + protected static class SPUDMAChannel extends DMAChannelOwnerBase { + public final int getDMAChannel() { + return DMAController.DMA_SPU; + } + + public final String getName() { + return "SPU"; + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + signalTransferComplete(); + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + signalTransferComplete(); + } + + public void cancelDMATransfer(int ctrl) { + System.out.println("cancel " + getName() + " DMA transfer"); + } + } + +} + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/SPU.java b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/SPU.java new file mode 100644 index 0000000..6c76830 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/components/hardware/spu/SPU.java @@ -0,0 +1,1287 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.components.hardware.spu; + +import org.apache.log4j.Logger; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.MemoryMapped; +import org.jpsx.api.components.core.dma.DMAController; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.api.components.core.scheduler.ScheduledAction; +import org.jpsx.api.components.core.scheduler.Scheduler; +import org.jpsx.api.components.hardware.cd.CDAudioSink; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.components.core.DMAChannelOwnerBase; +import org.jpsx.runtime.components.hardware.HardwareComponentConnections; +import org.jpsx.runtime.util.MiscUtil; + +import javax.sound.sampled.*; + +// todo volume panning +// bit of a mess! needs some work. +// +// TODO - noise/reverb/fm + +// todo check if getLevel is now supported +public class SPU extends SingletonJPSXComponent implements MemoryMapped, CDAudioSink { + private static final Logger log = Logger.getLogger("SPU"); + + private static final boolean noVoices = false; + private static final boolean debugEnvelope = false; + private static final boolean debugVoiceOnOff = false; + private static final boolean debugDMA = false; + + private static final int ADDR_VOICES = 0x1f801c00; + + private static final int ADDR_MAIN_VOL_L = 0x1f801d80; + private static final int ADDR_MAIN_VOL_R = 0x1f801d82; + private static final int ADDR_REVERB_L = 0x1f801d84; + private static final int ADDR_REVERB_R = 0x1f801d86; + private static final int ADDR_CHANNEL_ON0 = 0x1f801d88; + private static final int ADDR_CHANNEL_ON1 = 0x1f801d8a; + private static final int ADDR_CHANNEL_OFF0 = 0x1f801d8c; + private static final int ADDR_CHANNEL_OFF1 = 0x1f801d8e; + private static final int ADDR_CHANNEL_FM0 = 0x1f801d90; + private static final int ADDR_CHANNEL_FM1 = 0x1f801d92; + private static final int ADDR_CHANNEL_NOISE0 = 0x1f801d94; + private static final int ADDR_CHANNEL_NOISE1 = 0x1f801d96; + private static final int ADDR_CHANNEL_REVERB0 = 0x1f801d98; + private static final int ADDR_CHANNEL_REVERB1 = 0x1f801d9a; + private static final int ADDR_CHANNEL_MUTE0 = 0x1f801d9c; + private static final int ADDR_CHANNEL_MUTE1 = 0x1f801d9e; + + private static final int ADDR_TRANSFER_ADDR = 0x1f801da6; + private static final int ADDR_TRANSFER_DATA = 0x1f801da8; + + private static final int ADDR_SPU_CTRL = 0x1f801daa; + private static final int ADDR_SPU_STATUS = 0x1f801dae; + + private static final int ADDR_CD_VOL_L = 0x1f801db0; + private static final int ADDR_CD_VOL_R = 0x1f801db2; + + private static final int VOICES = 24; + + private static final int VOICE_VOL_L = 0x0; + private static final int VOICE_VOL_R = 0x2; + private static final int VOICE_PITCH = 0x4; + private static final int VOICE_START_OFFSET = 0x6; + private static final int VOICE_ADS_LEVEL = 0x8; + private static final int VOICE_SR_RATE = 0xa; + private static final int VOICE_ADSR_VOL = 0xc; + private static final int VOICE_REPEAT_OFFSET = 0xe; + + + private static final int SAMPLE_RATE = 44100; + private static final int MIN_BUFFER_SAMPLE_RATE = 16000; + private static final int BUFFER_MS = 240; + private static final long BUFFER_REFILL_PERIOD_NS = 30 * Quartz.MSEC; + private static final int BUFFER_MAX_FILL_MS = BUFFER_MS; + private static final int BUFFER_MAX_REFILL_MS = 80; + private static final int BUFFER_SAMPLES = (SAMPLE_RATE * BUFFER_MS) / 1000; + + private static final int CD_BUFFER_SAMPLES = SAMPLE_RATE / 2; + private static final byte[] cdAudioBuffer = new byte[2352 * 4 * 4]; // maximum we're likely to get! + private static SourceDataLine cdline; + private static int cdlineFreq; + private static FloatControl cdPanControl; + private static FloatControl cdGainControl; + private static int cdLeftVol = 0; + private static int cdRightVol = 0; + private static int cdLeftVolExternal = 0x3fff; + private static int cdRightVolExternal = 0x3fff; + + private static int m_ctrl; + private static int m_transferOffset; + private static int m_dataTransferWordOffset; + + private static int[] m_ram = new int[512 * 1024 / 4]; + private static short[] m_decoded = new short[1024 * 1024]; + // 4 short header bytes then 28 short samples... * 32768 + + private static Voice[] voices = new Voice[VOICES]; + + private static boolean cdAudio = true; + private static boolean voiceAudio = true; + public static final String PROPERTY_CD_AUDIO = "cdAudio"; + public static final String PROPERTY_VOICE_AUDIO = "voiceAudio"; + + private static int mainLeftVol; + private static int mainRightVol; + + private static AddressSpace addressSpace; + private static Quartz quartz; + private static Scheduler scheduler; + + public SPU() { + super("JPSX JavaSound SPU"); + } + + public void init() { + super.init(); + cdAudio = getBooleanProperty(PROPERTY_CD_AUDIO, true); + voiceAudio = getBooleanProperty(PROPERTY_VOICE_AUDIO, true); + log.info("Voice Audio " + (voiceAudio ? "ON" : "OFF")); + log.info("CD Audio " + (cdAudio ? "ON" : "OFF")); + if (cdAudio) { + HardwareComponentConnections.CD_AUDIO_SINK.set(this); + } + CoreComponentConnections.ALL_MEMORY_MAPPED.add(this); + CoreComponentConnections.DMA_CHANNEL_OWNERS.add(new SPUDMAChannel()); + } + + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + scheduler = CoreComponentConnections.SCHEDULER.resolve(); + } + + public void registerAddresses(AddressSpaceRegistrar registrar) { + for (int i = 0; i < VOICES; i++) { + voices[i] = new Voice(i); + int base = ADDR_VOICES + i * 0x10; + registrar.registerWrite16Callback(base + VOICE_VOL_L, SPU.class, "writeVolLeft"); + registrar.registerWrite16Callback(base + VOICE_VOL_R, SPU.class, "writeVolRight"); + registrar.registerWrite16Callback(base + VOICE_PITCH, SPU.class, "writePitch"); + registrar.registerWrite16Callback(base + VOICE_START_OFFSET, SPU.class, "writeStartOffset"); + registrar.registerWrite16Callback(base + VOICE_ADS_LEVEL, SPU.class, "writeADSLevel"); + registrar.registerWrite16Callback(base + VOICE_SR_RATE, SPU.class, "writeSRRate"); + registrar.registerRead16Callback(base + VOICE_ADSR_VOL, SPU.class, "readADSRVol"); + registrar.registerWrite16Callback(base + VOICE_REPEAT_OFFSET, SPU.class, "writeRepeatOffset"); + + registrar.registerRead16Callback(base + VOICE_VOL_L, SPU.class, "readVolLeft"); + registrar.registerRead16Callback(base + VOICE_VOL_R, SPU.class, "readVolRight"); + registrar.registerRead16Callback(base + VOICE_PITCH, SPU.class, "readPitch"); + registrar.registerRead16Callback(base + VOICE_START_OFFSET, SPU.class, "readStartOffset"); + registrar.registerRead16Callback(base + VOICE_ADS_LEVEL, SPU.class, "readADSLevel"); + registrar.registerRead16Callback(base + VOICE_SR_RATE, SPU.class, "readSRRate"); + registrar.registerRead16Callback(base + VOICE_REPEAT_OFFSET, SPU.class, "readRepeatOffset"); + } + registrar.registerWrite16Callback(ADDR_MAIN_VOL_L, SPU.class, "writeMainVolLeft"); + registrar.registerWrite16Callback(ADDR_MAIN_VOL_R, SPU.class, "writeMainVolRight"); + registrar.registerWrite16Callback(ADDR_REVERB_L, SPU.class, "writeReverbLeft"); + registrar.registerWrite16Callback(ADDR_REVERB_R, SPU.class, "writeReverbRight"); + registrar.registerWrite16Callback(ADDR_CHANNEL_ON0, SPU.class, "writeChannelOn0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_ON1, SPU.class, "writeChannelOn1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_OFF0, SPU.class, "writeChannelOff0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_OFF1, SPU.class, "writeChannelOff1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_FM0, SPU.class, "writeChannelFM0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_FM1, SPU.class, "writeChannelFM1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE0, SPU.class, "writeChannelNoise0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_NOISE1, SPU.class, "writeChannelNoise1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB0, SPU.class, "writeChannelReverb0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_REVERB1, SPU.class, "writeChannelReverb1"); + registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE0, SPU.class, "writeChannelMute0"); + registrar.registerWrite16Callback(ADDR_CHANNEL_MUTE1, SPU.class, "writeChannelMute1"); + + registrar.registerWrite16Callback(ADDR_SPU_CTRL, SPU.class, "writeSPUCtrl"); + registrar.registerRead16Callback(ADDR_SPU_CTRL, SPU.class, "readSPUCtrl"); + + registrar.registerWrite16Callback(ADDR_CD_VOL_L, SPU.class, "writeCDVolL"); + registrar.registerWrite16Callback(ADDR_CD_VOL_R, SPU.class, "writeCDVolR"); + + registrar.registerRead16Callback(ADDR_SPU_STATUS, SPU.class, "readSPUStatus"); + + registrar.registerWrite16Callback(ADDR_TRANSFER_ADDR, SPU.class, "writeTransferAddr"); + registrar.registerWrite16Callback(ADDR_TRANSFER_DATA, SPU.class, "writeTransferData"); + registrar.registerRead16Callback(ADDR_TRANSFER_ADDR, SPU.class, "readTransferAddr"); + + } + + public void begin() { + new SPUCallback().start(); + } + + public static void writeVolLeft(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setLeftVol(val); + } + + public static void writeVolRight(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setRightVol(val); + } + + public static void writePitch(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setPitch(val); + } + + public static void writeStartOffset(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setStartOffset(val); + } + + public static void writeADSLevel(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setADSLevel(val); + } + + public static void writeSRRate(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setSRRate(val); + } + + public static int readADSRVol(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getADSRVol(); + } + + public static void writeRepeatOffset(int address, int val) { + int voice = (address - ADDR_VOICES) >> 4; + voices[voice].setRepeatOffset(val); + } + + public static int readVolLeft(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getLeftVol(); + } + + public static int readVolRight(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getRightVol(); + } + + public static int readPitch(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getPitch(); + } + + public static int readStartOffset(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getStartOffset(); + } + + public static int readADSLevel(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getADSLevel(); + } + + public static int readSRRate(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getSRRate(); + } + + public static int readRepeatOffset(int address) { + int voice = (address - ADDR_VOICES) >> 4; + return voices[voice].getRepeatOffset(); + } + + public static void writeMainVolLeft(int address, int val) { + mainLeftVol = decodeVolume(val); + for (int i = 0; i < VOICES; i++) { + voices[i].updateVolume(); + } + } + + public static void writeMainVolRight(int address, int val) { + mainRightVol = decodeVolume(val); + for (int i = 0; i < VOICES; i++) { + voices[i].updateVolume(); + } + } + + public static void writeReverbLeft(int address, int val) { + } + + public static void writeReverbRight(int address, int val) { + } + + public static void writeChannelOn0(int address, int val) { + for (int i = 0; i < 16; i++) { + if ((val & (1 << i)) != 0) { + voices[i].on(); + } + } + } + + public static void writeChannelOn1(int address, int val) { + for (int i = 0; i < 8; i++) { + if ((val & (1 << i)) != 0) { + voices[i + 16].on(); + } + } + } + + public static void writeChannelOff0(int address, int val) { + for (int i = 0; i < 16; i++) { + if ((val & (1 << i)) != 0) { + voices[i].off(); + } + } + } + + public static void writeChannelOff1(int address, int val) { + for (int i = 0; i < 8; i++) { + if ((val & (1 << i)) != 0) { + voices[i + 16].off(); + } + } + } + + public static void writeChannelFM0(int address, int val) { + for (int i = 0; i < 16; i++) { + voices[i].setFM((val & (1 << i)) != 0); + } + } + + public static void writeChannelFM1(int address, int val) { + for (int i = 0; i < 8; i++) { + voices[i + 16].setFM((val & (1 << i)) != 0); + } + } + + public static void writeChannelNoise0(int address, int val) { + for (int i = 0; i < 16; i++) { + voices[i].setNoise((val & (1 << i)) != 0); + } + } + + public static void writeChannelNoise1(int address, int val) { + for (int i = 0; i < 8; i++) { + voices[i + 16].setNoise((val & (1 << i)) != 0); + } + } + + public static void writeChannelReverb0(int address, int val) { + for (int i = 0; i < 16; i++) { + voices[i].setReverb((val & (1 << i)) != 0); + } + } + + public static void writeChannelReverb1(int address, int val) { + for (int i = 0; i < 8; i++) { + voices[i + 16].setReverb((val & (1 << i)) != 0); + } + } + + public static void writeChannelMute0(int address, int val) { + for (int i = 0; i < 16; i++) { + voices[i].setMute((val & (1 << i)) != 0); + } + } + + public static void writeChannelMute1(int address, int val) { + for (int i = 0; i < 8; i++) { + voices[i + 16].setMute((val & (1 << i)) != 0); + } + } + + public static void writeSPUCtrl(int address, int val) { + if (val == m_ctrl) return; + m_ctrl = val; + /* + boolean spuOn = (val & 0x8000) != 0; + boolean spuMuted = (val & 0x4000) == 0; + boolean spuReverb = (val & 0x80) != 0; + boolean spuIrq = (val & 0x40) != 0; + boolean spuCD = (val & 0x1) != 0; + System.out.println("SPU "+(spuOn?"on":"off")+ + (spuMuted?" muted":"")+ + (spuReverb?" RV":"")+ + (spuIrq?" irq":" noirq")+ + (spuCD?" media":" nocd"));*/ + } + + public static int readSPUCtrl(int address) { + return m_ctrl; + } + + public static void writeCDVolL(int address, int val) { + cdLeftVol = decodeVolume(val); + updateCDVolume(); + } + + public static void writeCDVolR(int address, int val) { + cdRightVol = decodeVolume(val); + updateCDVolume(); + } + + public static void writeTransferAddr(int address, int val) { + m_transferOffset = val & 0xffff; + m_dataTransferWordOffset = m_transferOffset << 2; + } + + public static int readTransferAddr(int address) { + return m_transferOffset; + } + + public static void writeTransferData(int address, int val) { + int index = m_dataTransferWordOffset >> 1; + m_decoded[(m_dataTransferWordOffset << 2) & 0xfffffff0] = 0; + // todo mark area as dirty. + if (0 == (m_dataTransferWordOffset & 1)) { + m_ram[index] = (m_ram[index] & 0xffff0000) | (val & 0xffff); + } else { + m_ram[index] = (m_ram[index] & 0xffff) | (val << 16); + } + m_dataTransferWordOffset++; + } + + static boolean toggle; + + public static int readSPUStatus(int address) { + toggle = !toggle; +// System.out.println("READ SPU STATUS!"); + return toggle ? 0x400 : 0; + } + + private static class SPUDMAChannel extends DMAChannelOwnerBase { + private static AddressSpace.ResolveResult rr = new AddressSpace.ResolveResult(); + + public final int getDMAChannel() { + return DMAController.DMA_SPU; + } + + public final String getName() { + return "SPU"; + } + + public void beginDMATransferToDevice(int base, int blocks, int blockSize, int ctrl) { + if (debugDMA) + System.out.println("begin DMA transfer to " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + int destIndex = m_transferOffset << 1; + int size = blocks * blockSize; + addressSpace.resolve(base, size * 4, true, rr); + int srcIndex = rr.offset; + if ((destIndex + size) > 0x20000) { + if (debugDMA) + System.out.println("transfer to SPU overrun buffer by " + ((destIndex + size) - 0x20000) + " dwords"); + size = 0x20000 - destIndex; + } + int[] src = rr.mem; + for (size = size - 1; size >= 0; size--) { + // destIndex = 0->0x020000; + // decoded = 0->0x100000; + m_decoded[(destIndex << 3) & 0xfffffff0] = 0; + m_ram[destIndex++] = src[srcIndex++]; + } + signalTransferComplete(); + } + + public void beginDMATransferFromDevice(int base, int blocks, int blockSize, int ctrl) { + if (debugDMA) + System.out.println("begin DMA transfer from " + getName() + " " + MiscUtil.toHex(base, 8) + " 0x" + Integer.toHexString(blocks) + "*0x" + Integer.toHexString(blockSize) + " ctrl " + MiscUtil.toHex(ctrl, 8)); + int srcIndex = m_transferOffset << 1; + int size = blocks * blockSize; + addressSpace.resolve(base, size * 4, false, rr); + int destIndex = rr.offset; + int[] dest = rr.mem; + for (size = size - 1; size >= 0; size--) { + dest[destIndex++] = m_ram[srcIndex++]; + } + signalTransferComplete(); + } + + public void cancelDMATransfer(int ctrl) { + if (debugDMA) System.out.println("cancel " + getName() + " DMA transfer"); + } + } + + public static class SPUCallback implements ScheduledAction { + private long next; + private static byte[] buffer = new byte[BUFFER_SAMPLES * 2]; + + public void start() { + next = quartz.nanoTime() + (BUFFER_REFILL_PERIOD_NS << 4); + scheduler.schedule(next, this); + } + + public long run(long currentTime) { + //System.out.println("invoke "+time); + for (int i = 0; i < VOICES; i++) { + voices[i].fill(buffer, false); + } + next = quartz.nanoTime() + BUFFER_REFILL_PERIOD_NS; + return next; + } + } + + // for debugging + private static byte[] debugbuffer = new byte[BUFFER_SAMPLES * 2]; + + public static void fill() { + for (int i = 0; i < VOICES; i++) { + voices[i].fill(debugbuffer, BUFFER_SAMPLES * 2); + } + } + + private static class Voice { + private int index; + + private static final int OFF = 0; + private static final int ATTACK = 1; + private static final int DECAY = 2; + private static final int SUSTAIN = 3; + private static final int RELEASE = 4; + + private int state; + private boolean mute; + private boolean fm; + private boolean noise; + private boolean reverb; + private int leftVol; + private int rightVol; + private int rateA, rateD, rateS, rateR; + private int levelS; + private boolean expA, expS, expR; + private boolean decS; + private int pitch; + + private int vol; + private int sampleDelta; + private int startOffset; + private int blockOffset; + private int repeatOffset; + private int sample; + private int currentBlockSample; + private boolean locked; + private int envelope; + private int currentMS; + private int currentSubMS; + private int adslevel; + private int srrate; + + private static final int ENVELOPE_HISTORY_SIZE = 256; + private int[] envelopeHistory = new int[ENVELOPE_HISTORY_SIZE]; + private long onTime; + private long offTime; + + private static byte[] buffer = new byte[BUFFER_SAMPLES * 2]; + + private static DataLine.Info desiredLine = new DataLine.Info(SourceDataLine.class, + new AudioFormat[]{new AudioFormat(SAMPLE_RATE, 16, 1, true, false)}, +// Guess this was ignored by the software mixer - doesn't really make much sense +// 0, BUFFER_SAMPLES * 2); + BUFFER_SAMPLES * 2, AudioSystem.NOT_SPECIFIED); + private SourceDataLine line; + private FloatControl panControl; + private FloatControl rateControl; + + private boolean slow; + private int sampleRate; + private int BUFFER_MAX_REFILL_SAMPLES; + private int BUFFER_MAX_FILL_SAMPLES; + + private static int[] adsrRates = initADSR(); + + private static int[] initADSR() { + int[] rates = new int[160]; + int r, rs, rd; + int i; + + r = 3; + rs = 1; + rd = 0; + + for (i = 32; i < 160; i++) { + if (r < 0x3FFFFFFF) { + r += rs; + rd++; + if (rd == 5) { + rd = 1; + rs *= 2; + } + } + if (r > 0x3FFFFFFF) r = 0x3FFFFFFF; + rates[i] = r; + } + return rates; + } + + public String toString() { + return "V" + index + " L" + MiscUtil.toHex(leftVol, 4) + " R" + MiscUtil.toHex(rightVol, 4) + " " + + "pitch " + MiscUtil.toHex(pitch, 4) + " " + + "st " + MiscUtil.toHex(startOffset, 4) + " " + + "rpt " + MiscUtil.toHex(repeatOffset, 4) + + " ar " + rateA + + " dr " + rateD + + " sl " + levelS + + " sr " + rateS + + " rr " + rateR + + (mute ? " muted" : "") + + (fm ? " FM" : "") + + (reverb ? " RV" : ""); + } + + public Voice(int index) { + if (!voiceAudio) return; + this.index = index; + try { + line = (SourceDataLine) AudioSystem.getLine(desiredLine); + line.open(); + if (line.isControlSupported(FloatControl.Type.SAMPLE_RATE)) { + rateControl = (FloatControl) line.getControl(FloatControl.Type.SAMPLE_RATE); + } else { + log.warn("Rate control is NOT supported, hacking around it for now - might sound a bit weird until fixed properly"); + } + if (line.isControlSupported(FloatControl.Type.PAN)) { + panControl = (FloatControl) line.getControl(FloatControl.Type.PAN); + } else { + // todo to fix this we need to make the voice stereo instead (identical channels) + log.warn("Pan control is NOT supported, voices will not be stereo positioned"); + } + } catch (Throwable t) { + throw new IllegalStateException("can't get line for voice " + index, t); + } + state = OFF; + } + + public void on() { + if (!voiceAudio) return; + //if (index!=0) return; + if (debugVoiceOnOff) System.out.println("voice on " + this); + if (isActive()) { +// System.out.println(this+" VOICE ON WHEN ACTIVE!"); + } + state = OFF; + line.flush(); + line.stop(); + //line.drain(); + + repeatOffset = 0; + sample = 0; + currentBlockSample = -28; + blockOffset = startOffset - 2; + currentMS = 0; + currentSubMS = 1000; + + slow = pitch < 0x1000; + if (rateControl == null) { + // temp hack to get around loss of RateControl is JDK7 + // surprised this works, but as far as I recall, I must + // have done the frequency myself for anything higher than + // the SAMPLE_RATE, so forcing slow = false makes + // us do it in software, which might sound bad without filtering + // but is good enough for now + slow = false; + } + sampleRate = slow ? ((SAMPLE_RATE * pitch) >> 12) : SAMPLE_RATE; + int min = sampleRate < MIN_BUFFER_SAMPLE_RATE ? MIN_BUFFER_SAMPLE_RATE : sampleRate; + BUFFER_MAX_REFILL_SAMPLES = (min * BUFFER_MAX_REFILL_MS) / 1000; + BUFFER_MAX_FILL_SAMPLES = (min * BUFFER_MAX_FILL_MS) / 1000; + //System.out.println("slow="+slow+" sample rate="+sampleRate+" max samples="+BUFFER_MAX_REFILL_SAMPLES); + if (rateControl != null) { + rateControl.setValue(sampleRate); + } + if (!noVoices) { + line.start(); + } + + envelope = 0; + //System.out.println("onTime "+onTime); + onTime = quartz.nanoTime(); + offTime = Long.MAX_VALUE; + state = ATTACK; + if (debugEnvelope) System.out.println("voice " + index + " to ATTACK"); + fill(buffer, true); + } + + public void off() { + if (!voiceAudio) return; + if (debugVoiceOnOff) System.out.println("voice off " + this); + if (state != OFF) { + if (debugEnvelope) System.out.println("voice " + index + " to RELEASE"); + state = RELEASE; + } + } + + public void setMute(boolean nMute) { + if (mute != nMute) { + mute = nMute; + //System.out.println( this + " mute changed" ); + } + } + + public boolean isActive() { + return state != OFF; + } + + public void setReverb(boolean nReverb) { + reverb = nReverb; + } + + public void setNoise(boolean nNoise) { + noise = nNoise; + if (noise) throw new IllegalStateException(this + " NOISE!"); + } + + public void setFM(boolean nFM) { + fm = nFM; + if (fm) throw new IllegalStateException(this + " FM!"); + } + + public void setLeftVol(int nVol) { + leftVol = decodeVolume(nVol); + updateVolume(); + } + + public void setRightVol(int nVol) { + rightVol = decodeVolume(nVol); + updateVolume(); + } + + public int getLeftVol() { + return leftVol; + } + + public int getRightVol() { + return leftVol; + } + + public void updateVolume() { + if (!voiceAudio) return; + // set volume to max of left/right, then set pan + // assuming that: + // lscale = (pan<0)?1:(1-pan); + // rscale = (pan<0)?(1+pan):1; + + int l = (leftVol * mainLeftVol) >> 15; + int r = (rightVol * mainRightVol) >> 15; + if (panControl == null) { + // todo fix this, for now without pan control, just average l/r volume + vol = (l + r) / 2; + } else { + if (l == r) { + vol = l; + panControl.setValue(0.0f); + } else if (l > r) { + vol = l; + panControl.setValue(((float) r) / l - 1.0f); + } else { + vol = r; + panControl.setValue(1.0f - ((float) l) / r); + } + } + } + + public void setPitch(int nPitch) { + pitch = nPitch; + sampleDelta = pitch >> 1; + if (state != OFF) { + //System.out.println("XXX SET PITCH WHILE ON: "+this+" pitch is now "+nPitch); + } + } + + public int getPitch() { + return pitch; + } + + public void setStartOffset(int nOffset) { + startOffset = nOffset; + } + + public int getStartOffset() { + return startOffset; + } + + public void setADSLevel(int val) { + adslevel = val; + expA = (val & 0x8000) != 0; + rateA = (val >> 8) & 0x7f; + rateA ^= 0x7f; + rateD = (val >> 4) & 0xf; + // todo - is this really correct? + rateD ^= 0x1f; + levelS = val & 0xf; + } + + public int getADSLevel() { + return adslevel; + } + + public void setSRRate(int val) { + srrate = val; + expS = (val & 0x8000) != 0; + decS = (val & 0x4000) != 0; + rateS = (val >> 6) & 0x7f; + rateS ^= 0x7f; + expR = (val & 0x20) != 0; + rateR = val & 0x1f; + rateR ^= 0x1f; + } + + public int getSRRate() { + return srrate; + } + + public int getADSRVol() { + if (!voiceAudio) return 0; + long time = quartz.nanoTime(); + if (state == OFF && time >= offTime) { + return 0; + } + int ms = (int) ((time - onTime) / Quartz.MSEC); + if (ms > currentMS) + return 0; + int delta = (currentMS - ms) >> 2; + // if we're too far behind, then pick something back towards the beginning of the buffer + // + // note, we can get further behind because our ticks are potentially slower than real time + // due to gc/compilation etc. + if (delta >= ENVELOPE_HISTORY_SIZE) + ms = currentMS - ((ENVELOPE_HISTORY_SIZE - 4) << 2); +// System.out.println( this+" "+(envelopeHistory[(ms>>2)%ENVELOPE_HISTORY_SIZE]>>16)); + return envelopeHistory[(ms >> 2) % ENVELOPE_HISTORY_SIZE] >> 16; + } + + public void setRepeatOffset(int nRepeat) { + repeatOffset = nRepeat; + } + + public int getRepeatOffset() { + return repeatOffset; + } + + public synchronized boolean lock() { + if (locked) + return false; + locked = true; + return true; + } + + public synchronized void unlock() { + locked = false; + } + + private static final int[] expIndex = new int[]{ + 0, 4, 6, 8, 9, 10, 11, 12 + }; + + private final void updateADSR() { + //assert(0==(envelope&0x80000000)); + + switch (state) { + case ATTACK: + if (!expA || envelope < 0x60000000) { + envelope += adsrRates[rateA + 32 - 0x10]; + } else { + envelope += adsrRates[rateA + 32 - 0x18]; + } + if (envelope < 0) { + envelope = 0x7fffffff; + if (debugEnvelope) System.out.println("voice " + index + " to DECAY"); + state = DECAY; + } + return; + case DECAY: + envelope -= adsrRates[4 * rateD + 32 - 0x18 + expIndex[envelope >> 28]]; + if (envelope > 0) { + if (levelS >= (envelope >> 27)) { + state = SUSTAIN; + if (debugEnvelope) System.out.println("voice " + index + " to SUSTAIN"); + } + } else { + envelope = 0; + state = SUSTAIN; + if (debugEnvelope) System.out.println("voice " + index + " to SUSTAIN"); + } + return; + case SUSTAIN: + if (decS) { + // decrementing + if (expS) { + envelope -= adsrRates[rateS + 32 - 0x1b + expIndex[envelope >> 28]]; + } else { + envelope -= adsrRates[rateS + 32 - 0x0f]; + } + if (envelope < 0) { + envelope = 0; + } + } else { + // incrementing + if (!expS || envelope < 0x60000000) { + envelope += adsrRates[rateS + 32 - 0x10]; + } else { + envelope += adsrRates[rateS + 32 - 0x18]; + } + if (envelope < 0) { + envelope = 0x7fffffff; + } + } + return; + case RELEASE: + if (expR) { + envelope -= adsrRates[4 * rateR + 32 - 0x18 + expIndex[envelope >> 28]]; + } else { + envelope -= adsrRates[4 * rateR + 32 - 0x0c]; + } + if (envelope < 0) { + envelope = 0; + } + return; + } + } + + public void fill(byte[] buffer, boolean unlimited) { + int max = unlimited ? BUFFER_MAX_FILL_SAMPLES : BUFFER_MAX_REFILL_SAMPLES; + fill(buffer, max); + } + + public void fill(byte[] buffer, int max) { + if (noVoices) { + return; + } + if (lock()) { + if (state == OFF || sampleDelta == 0) { + //if (line.isActive() && line.available()==line.getBufferSize()) { + // System.out.println(this+" line is drained and off, stopping!"); + // line.close(); + //} + unlock(); + return; + } + //System.out.println( Thread.currentThread().getName()+" thread fills"); + int sampleCount = line.available() >> 1; + if (sampleCount == 0) { + unlock(); + return; + } + if (sampleCount > max) { + sampleCount = max; + } + int bufferBytes = 0; + if (slow) { + // todo removed this because it keeps failing! + //assert sampleDelta <= 0x800; + //System.out.println( this + " filling "+sampleCount+" slow samples"); + for (int count = 0; count < sampleCount; count++) { + int s = sample >> 11; + int sold = s; + do { + updateADSR(); + sample += sampleDelta; + s = sample >> 11; + } while (s == sold); + //updateADSR(); + int decodeIndex = blockOffset << 4; + if (s >= currentBlockSample + 28) { + currentBlockSample += 28; + blockOffset += 2; + decodeIndex += 32; + + int srcIndex = blockOffset << 1; + int code = (m_ram[srcIndex] >> 8) & 0xff; + if (0 != (code & 1)) { + state = OFF; + if (debugEnvelope) System.out.println("voice " + index + " to OFF (sample ended)"); + offTime = onTime + currentMS * Quartz.MSEC; + //System.out.println("offTime "+offTime+" ("+((offTime-onTime)>>4)+")"); + break; + } + if (m_decoded[decodeIndex] == 0) { + //System.out.g(this+" decode block at "+MiscUtil.toHex( nextBlockOffset, 4)+" code "+code); + // System.out.println(" decompress"); + decompressBlock(blockOffset); + } + // note maximum sample step is 16 samples, so we can't skip a block + } + int val = m_decoded[decodeIndex + 4 + s - currentBlockSample]; + val = (val * vol) >> 14; + val = (val * (envelope >> 16)) >> 15; + //if (index==0) System.out.println(index+" "+state+" "+MiscUtil.toHex( envelope, 8)+" "+MiscUtil.toHex( val, 4)); + buffer[bufferBytes++] = (byte) val; + buffer[bufferBytes++] = (byte) (val >> 8); + currentSubMS -= 1000; + if (currentSubMS <= 0) { + envelopeHistory[(currentMS >> 2) % ENVELOPE_HISTORY_SIZE] = envelope; + currentMS += 4; + currentSubMS += sampleRate * 4; + //if (index==0) System.out.println(currentMS+" "+MiscUtil.toHex(envelope>>16,4)); + } + } + } else { + //System.out.println( this + " filling "+sampleCount+" fast samples"); + for (int count = 0; count < sampleCount; count++) { + updateADSR(); + int s = (sample >> 11); + int decodeIndex = blockOffset << 4; + if (s >= currentBlockSample + 28) { + currentBlockSample += 28; + blockOffset += 2; + decodeIndex += 32; + + int srcIndex = blockOffset << 1; + int code = (m_ram[srcIndex] >> 8) & 0xff; + if (0 != (code & 1)) { + state = OFF; + offTime = onTime + (currentMS << 4); + if (debugEnvelope) System.out.println("voice " + index + " to OFF (sample ended)"); + //System.out.println("offTime "+offTime+" ("+((offTime-onTime)>>4)+")"); + break; + } + if (m_decoded[decodeIndex] == 0) { + //System.out.println(this+" decode block at "+MiscUtil.toHex( nextBlockOffset, 4)+" code "+code); + // System.out.println(" decompress"); + decompressBlock(blockOffset); + } + // note maximum sample step is 16 samples, so we can't skip a block + } + int val = m_decoded[decodeIndex + 4 + s - currentBlockSample]; + val = (val * vol) >> 14; + val = (val * (envelope >> 16)) >> 15; + //if (index==0) System.out.println(index+" "+state+" "+MiscUtil.toHex( envelope, 8)+" "+MiscUtil.toHex( val, 4)); + buffer[bufferBytes++] = (byte) val; + buffer[bufferBytes++] = (byte) (val >> 8); + sample += sampleDelta; + currentSubMS -= 1000; + if (currentSubMS <= 0) { + envelopeHistory[(currentMS >> 2) % ENVELOPE_HISTORY_SIZE] = envelope; + currentMS += 4; + currentSubMS += SAMPLE_RATE * 4; + //System.out.println(currentMS+" "+MiscUtil.toHex(envelope>>16,4)); + } + } + } + line.write(buffer, 0, bufferBytes); + unlock(); + } + } + } + + private static final int[] predict1 = new int[]{ + 0, 60, 115, 98, 122 + }; + + private static final int[] predict2 = new int[]{ + 0, 0, -52, -55, -60 + }; + + // blockOffset is in multiples of 8 bytes in src ram. + private static void decompressBlock(int blockOffset) { + int decodeIndex = blockOffset << 4; + int srcIndex = blockOffset << 1; + + int s_1, s_2; + if (false) { + if (decodeIndex < 32) { + s_1 = 0; + s_2 = 0; + } else { + s_1 = m_decoded[decodeIndex - 31]; + s_2 = m_decoded[decodeIndex - 30]; + } + + int dword = m_ram[srcIndex]; + int predictIndex = (dword >> 4) & 0xf; + int shift = dword & 0xf; + + for (int i = 4; i < 32; i++) { + int i7 = i & 7; + int s = (dword >> (i7 << 2)) & 0xf; + //s <<= 12; + //if ((s&0x8000)!=0) s|= 0xffff0000; + //s >>= shift; + //s = (((s<<6) + s_1*predict1[predictIndex] + s_2*predict2[predictIndex])+32)>>6; + + // note this isn't quite the same as above; we include sub bits if shift >12 + s = ((((s << 28) >> (shift + 10)) + s_1 * predict1[predictIndex] + s_2 * predict2[predictIndex]) + 32) >> 6; + + + m_decoded[decodeIndex + i] = (short) s; + s_2 = s_1; + s_1 = s; + if (7 == (i7)) { + dword = m_ram[srcIndex + ((i + 1) >> 3)]; + } + //System.out.print(MiscUtil.toHex(s,4)+" "); + } + m_decoded[decodeIndex] = 1; + m_decoded[decodeIndex + 1] = (short) s_1; + m_decoded[decodeIndex + 2] = (short) s_2; + } else { + if (decodeIndex < 32) { + s_1 = 0; + s_2 = 0; + } else { + s_1 = ((int) m_decoded[decodeIndex - 31] & 0xffff) + (((int) m_decoded[decodeIndex - 29] & 0xff) << 16); + s_2 = ((int) m_decoded[decodeIndex - 30] & 0xffff) + (((int) m_decoded[decodeIndex - 29] & 0xff00) << 8); + s_1 = (s_1 << 8) >> 8; + s_2 = (s_2 << 8) >> 8; + } + + int dword = m_ram[srcIndex]; + int predictIndex = (dword >> 4) & 0xf; + int shift = (dword & 0xf) + 12; + + int ik0 = -predict1[predictIndex]; + int ik1 = -predict2[predictIndex]; + for (int i = 4; i < 32; i++) { + int i7 = i & 7; + int x0 = (dword >> (i7 << 2)) & 0xf; + x0 = (x0 << 28) >> shift; + x0 -= (ik0 * s_1 + ik1 * s_2) >> 6; + m_decoded[decodeIndex + i] = (short) (x0 >> 4); + s_2 = s_1; + s_1 = x0; + if (7 == (i7)) { + dword = m_ram[srcIndex + ((i + 1) >> 3)]; + } + //System.out.print(MiscUtil.toHex(s,4)+" "); + } + m_decoded[decodeIndex] = 1; + m_decoded[decodeIndex + 1] = (short) s_1; + m_decoded[decodeIndex + 2] = (short) s_2; + m_decoded[decodeIndex + 3] = (short) (((s_1 >> 16) & 0xff) | ((s_2 >> 8) & 0xff00)); + } + //System.out.println(); + } + + public int getCDAudioLatency() { + return 0; + } + + private static boolean reBuffer = false; + + public void newCDAudio() { + sectorsSinceReset = 0; + base = System.nanoTime(); + if (cdline != null) { + cdline.flush(); + cdline.stop(); + } + } + + // we can get up to 8 sectors at a time; make slightly bigger for safety + private static final int SECTORS_TO_BUFFER = 10; + private static final int SECTORS_TO_DELAY = 4; + int sectorsSinceReset; + int bytesPerSector; + + public synchronized void setCDAudioRate(int hz) { + if (cdAudio) { + if (hz != cdlineFreq) { + newCDAudio(); + cdline = null; + bytesPerSector = (hz / 75) * 4; + int bytesToBuffer = bytesPerSector * SECTORS_TO_BUFFER; + + DataLine.Info desiredCdLine = new DataLine.Info(SourceDataLine.class, + new AudioFormat[]{new AudioFormat(hz, 16, 2, true, false)}, + bytesToBuffer * 4, bytesToBuffer * 4); + try { + cdline = (SourceDataLine) AudioSystem.getLine(desiredCdLine); + cdline.open(); + //System.out.println(cdline); + reBuffer = true; + cdPanControl = (FloatControl) cdline.getControl(FloatControl.Type.PAN); + cdGainControl = (FloatControl) cdline.getControl(FloatControl.Type.MASTER_GAIN); + updateCDVolume(); + } catch (Throwable t) { + throw new IllegalStateException("can't get line for media audio", t); + } + cdlineFreq = hz; + } + } + } + + static long base; + + public boolean cdAudioData(byte[] data, int offset, int length) { + long now = System.nanoTime(); + double delta = (now - base) / 1000000.0; + if (log.isDebugEnabled()) { + log.debug("AUDIO AT " + delta + " buffer space " + cdline.available() + " length " + length + " in sectors = " + (length / (1.0 * bytesPerSector))); + } + assert (bytesPerSector > 0); + while (length > 0) { + // write one sectors worth at a time + int toWrite = length > bytesPerSector ? bytesPerSector : length; + cdline.write(data, offset, toWrite); + offset += toWrite; + length -= toWrite; + sectorsSinceReset++; + if (sectorsSinceReset == SECTORS_TO_DELAY) { + cdline.start(); + } + } + return sectorsSinceReset >= SECTORS_TO_DELAY; + } + + public void setExternalCDAudioVolumeLeft(int vol) { + vol /= 2; + if (vol > 0x3fff) vol = 0x3fff; + cdLeftVolExternal = vol; + updateCDVolume(); + } + + public void setExternalCDAudioVolumeRight(int vol) { + vol /= 2; + if (vol > 0x3fff) vol = 0x3fff; + cdRightVolExternal = vol; + updateCDVolume(); + } + + private static int volMul(int v1, int v2) { + if (v1 == 0x3fff) v1++; + if (v2 == 0x3fff) v2++; + return (v1 * v2) >> 14; + } + + private static synchronized void updateCDVolume() { + if (cdline != null) { + int l = volMul(mainLeftVol, volMul(cdLeftVol, cdLeftVolExternal)); + int r = volMul(mainRightVol, volMul(cdRightVol, cdRightVolExternal)); + if (log.isDebugEnabled()) { + log.debug("CD Volume L=" + MiscUtil.toHex(mainLeftVol, 4) + "," + MiscUtil.toHex(cdLeftVol, 4) + "," + MiscUtil.toHex(cdLeftVolExternal, 4) + " R=" + MiscUtil.toHex(r, 4)); + } + int vol; + if (l == r) { + vol = l; + cdPanControl.setValue(0.0f); + } else if (l > r) { + vol = l; + cdPanControl.setValue(((float) r) / l - 1.0f); + } else { + vol = r; + cdPanControl.setValue(1.0f - ((float) l) / r); + } + // todo fix this; it is just made up + float db = -10 + (vol - 16384) / 512f; + if (db < -80) db = -80; + cdGainControl.setValue(db); + } + } + + public boolean isCDAudible() { + return cdline != null; + } + + private static int decodeVolume(int vol) { + int rc; + if (0 == (vol & 0x8000)) { + // non sweep + rc = vol & 0x3fff; + } else { + // sweep not supported, just go straight to min/max + if ((vol & 0x2000) == 0) { + // increase + rc = 0x3fff; + } else { + // decrease + rc = 0; + } + } + // phase not yet supported + return rc; + } +} + diff --git a/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java new file mode 100644 index 0000000..6f8f083 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.debugcomponents.core; + +import org.apache.bcel.generic.ClassGen; +import org.apache.log4j.Logger; +import org.jpsx.api.CPUListener; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.addressspace.AddressSpaceRegistrar; +import org.jpsx.api.components.core.addressspace.Pollable; +import org.jpsx.bootstrap.classloader.ClassModifier; +import org.jpsx.bootstrap.util.CollectionsFactory; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.SingletonJPSXComponent; +import org.jpsx.runtime.components.core.AddressSpaceImpl; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.util.ClassUtil; + +import java.util.List; + +/** + * A debug implementation of address space that gives you the ability to set RAM breakpoints and other goodies. + */ +public final class DebugAddressSpaceImpl extends SingletonJPSXComponent implements ClassModifier, AddressSpace, AddressSpaceRegistrar, CPUListener { + private static final Logger logger = Logger.getLogger(DebugAddressSpaceImpl.class); + private static final AddressSpaceImpl realAddressSpace = new AddressSpaceImpl(); + private static final String HARDWARE_CLASS = ClassUtil.innerClassName(DebugAddressSpaceImpl.class, "Hardware"); + private static List ramBreakpoints = CollectionsFactory.newArrayList(); + private static boolean cpuActive = true; + private static boolean ramBreakpointsActive = false; + public static int[] ramD = realAddressSpace.ramD; + public static final int[] scratch = realAddressSpace.scratch; + public static final int[] bios = realAddressSpace.bios; + + public DebugAddressSpaceImpl() { + super("Debug JPSX Address Space"); + } + + private static void processAddressWrite(int address) { + if (ramBreakpointsActive && ramBreakpoints.contains(address)) { + logger.info("RAM address 0x" + Integer.toHexString(address) + " about to be written; pausing the CPU..."); + // Pause the CPU. + RuntimeConnections.CPU_CONTROL.resolve().pause(); + } + } + + public static void activateRAMBreakpoint(int address) { + ramBreakpoints.add(address); + logger.info("Adding breakpoint at: 0x" + Integer.toHexString(address)); + ramBreakpointsActive = true && cpuActive; + } + + public static void deactivateRAMBreakpoint(int address) { + int index = ramBreakpoints.indexOf(address); + if (index >= 0) { + ramBreakpoints.remove(index); + logger.info("Breakpoint at 0x" + Integer.toHexString(address) + " has been removed."); + ramBreakpointsActive = ramBreakpoints.size() > 0 && cpuActive; + } else { + logger.info("Breakpoint at 0x" + Integer.toHexString(address) + " does not exist."); + } + } + + public static int[] getActiveRAMBreakpoints() { + final int numBreakpoints = ramBreakpoints.size(); + final int[] breakpoints = new int[numBreakpoints]; + for (int i = 0; i < numBreakpoints; i++) { + breakpoints[i] = ramBreakpoints.get(i); + } + return breakpoints; + } + + @Override + public void resolveConnections() { + super.resolveConnections(); + realAddressSpace.resolveConnections(); + } + + @Override + public void init() { + super.init(); + realAddressSpace.init(); + CoreComponentConnections.ADDRESS_SPACE.set(this); + CoreComponentConnections.CPU_LISTENERS.add(this); + } + + @Override + public int internalRead32(int address) { + return realAddressSpace.internalRead32(address); + } + + public static int _internalRead32(int address) { + return AddressSpaceImpl._internalRead32(address); + } + + @Override + public void internalWrite32(int address, int value) { + realAddressSpace.internalWrite32(address, value); + } + + public static void _internalWrite32(int address, int value) { + AddressSpaceImpl._internalWrite32(address, value); + } + + @Override + public int read8(int address) { + return realAddressSpace.read8(address); + } + + public static int _read8(int address) { + return AddressSpaceImpl._read8(address); + } + + @Override + public int read16(int address) { + return realAddressSpace.read16(address); + } + + public static int _read16(int address) { + return AddressSpaceImpl._read16(address); + } + + @Override + public int read32(int address) { + return realAddressSpace.read32(address); + } + + public static int _read32(int address) { + return AddressSpaceImpl._read32(address); + } + + @Override + public void write8(int address, int value) { + realAddressSpace.write8(address, value); + } + + public static void _write8(int address, int value) { + AddressSpaceImpl._write8(address, value); + } + + @Override + public void write16(int address, int value) { + realAddressSpace.write16(address, value); + } + + public static void _write16(int address, int value) { + AddressSpaceImpl._write16(address, value); + } + + @Override + public void write32(int address, int value) { + realAddressSpace.write32(address, value); + } + + public static void _write32(int address, int value) { + AddressSpaceImpl._write32(address, value); + } + + @Override + public void enableMemoryWrite(boolean enable) { + realAddressSpace.enableMemoryWrite(enable); + // RAM might now be a dummy array. + ramD = realAddressSpace.ramD; + } + + @Override + public byte getTag(int pc) { + return realAddressSpace.getTag(pc); + } + + @Override + public void orTag(int pc, byte val) { + realAddressSpace.orTag(pc, val); + } + + @Override + public void resolve(int address, ResolveResult result) { + realAddressSpace.resolve(address, result); + } + + @Override + public void resolve(int address, int size, boolean write, ResolveResult result) { + realAddressSpace.resolve(address, size, write, result); + } + + @Override + public int[] getMainRAM() { + // TODO: Support RAM breakpoints for DMA! + return realAddressSpace.getMainRAM(); + } + + @Override + public void tagAddressAccessWrite(int pc, int address) { + processAddressWrite(address); + realAddressSpace.tagAddressAccessWrite(pc, address); + } + + public static void _tagAddressAccessWrite(int pc, int address) { + processAddressWrite(address); + AddressSpaceImpl._tagAddressAccessWrite(pc, address); + } + + @Override + public void tagAddressAccessRead8(int pc, int address) { + realAddressSpace.tagAddressAccessRead8(pc, address); + } + + public static void _tagAddressAccessRead8(int pc, int address) { + AddressSpaceImpl._tagAddressAccessRead8(pc, address); + } + + @Override + public void tagAddressAccessRead16(int pc, int address) { + realAddressSpace.tagAddressAccessRead16(pc, address); + } + + public static void _tagAddressAccessRead16(int pc, int address) { + AddressSpaceImpl._tagAddressAccessRead16(pc, address); + } + + @Override + public void tagAddressAccessRead32(int pc, int address) { + realAddressSpace.tagAddressAccessRead32(pc, address); + } + + public static void _tagAddressAccessRead32(int pc, int address) { + AddressSpaceImpl._tagAddressAccessRead32(pc, address); + } + + @Override + public void tagClearPollCounters() { + realAddressSpace.tagClearPollCounters(); + } + + public static void _tagClearPollCounters() { + AddressSpaceImpl._tagClearPollCounters(); + } + + @Override + public String getMainStaticInterfaceClassName() { + return DebugAddressSpaceImpl.class.getName(); + } + + @Override + public String getHardwareStaticInterfaceClassName() { + return HARDWARE_CLASS; + } + + @Override + public void registerRead8Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerRead8Callback(address, clazz, methodName); + } + + @Override + public void registerRead16Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerRead16Callback(address, clazz, methodName); + } + + @Override + public void registerRead16Callback(int address, Class clazz, String methodName, boolean allowSubRead) { + realAddressSpace.registerRead16Callback(address, clazz, methodName, allowSubRead); + } + + @Override + public void registerRead32Callback(int address, Class clazz, String methodName, boolean allowSubRead) { + realAddressSpace.registerRead32Callback(address, clazz, methodName, allowSubRead); + } + + @Override + public void registerRead32Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerRead32Callback(address, clazz, methodName); + } + + @Override + public void registerWrite8Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerWrite8Callback(address, clazz, methodName); + } + + @Override + public void registerWrite16Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerWrite16Callback(address, clazz, methodName); + } + + @Override + public void registerWrite16Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { + realAddressSpace.registerWrite16Callback(address, clazz, methodName, allowSubWrite); + } + + @Override + public void registerWrite32Callback(int address, Class clazz, String methodName) { + realAddressSpace.registerWrite32Callback(address, clazz, methodName); + } + + @Override + public void registerWrite32Callback(int address, Class clazz, String methodName, boolean allowSubWrite) { + realAddressSpace.registerWrite32Callback(address, clazz, methodName, allowSubWrite); + } + + @Override + public void registerPoll32Callback(int address, Pollable pollable) { + realAddressSpace.registerPoll32Callback(address, pollable); + } + + @Override + public ClassGen modifyClass(String classname, ClassGen original) { + return realAddressSpace.modifyClass(classname, original); + } + + @Override + public void cpuResumed() { + cpuActive = true; + ramBreakpointsActive = ramBreakpoints.size() > 0; + } + + @Override + public void cpuPaused() { + cpuActive = false; + ramBreakpointsActive = false; + } + + public static class Hardware { + public static void write8(int address, int value) { + AddressSpaceImpl.Hardware.write8(address, value); + } + + public static void write16(int address, int value) { + AddressSpaceImpl.Hardware.write16(address, value); + } + + public static void write32(int address, int value) { + AddressSpaceImpl.Hardware.write32(address, value); + } + + public static int read8(int address) { + return AddressSpaceImpl.Hardware.read8(address); + } + + public static int read16(int address) { + return AddressSpaceImpl.Hardware.read16(address); + } + + public static int read32(int address) { + return AddressSpaceImpl.Hardware.read32(address); + } + + public static int defaultRead32(int address) { + return AddressSpaceImpl.Hardware.defaultRead32(address); + } + + public static void defaultWrite32(int address, int value) { + AddressSpaceImpl.Hardware.defaultWrite32(address, value); + } + + public static int defaultRead16(int address) { + return AddressSpaceImpl.Hardware.defaultRead16(address); + } + + public static void defaultWrite16(final int address, int value) { + AddressSpaceImpl.Hardware.defaultWrite16(address, value); + } + + public static int defaultRead8(int address) { + return AddressSpaceImpl.Hardware.defaultRead8(address); + } + + public static void defaultWrite8(final int address, int value) { + AddressSpaceImpl.Hardware.defaultWrite8(address, value); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java new file mode 100644 index 0000000..5976b2b --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.debugcomponents.emulator.console; + +import org.jpsx.api.CPUControl; +import org.jpsx.api.CPUListener; +import org.jpsx.api.components.core.addressspace.AddressSpace; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.api.components.core.scheduler.Quartz; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.components.core.CoreComponentConnections; +import org.jpsx.runtime.debugcomponents.core.DebugAddressSpaceImpl; +import org.jpsx.runtime.components.hardware.gte.GTE; +import org.jpsx.runtime.util.MiscUtil; + +import java.io.*; + +public class Console extends JPSXComponent implements Runnable, CPUListener { + protected int lastDisAddress; + protected boolean skipShow = true; + + private AddressSpace addressSpace; + private R3000 r3000; + private CPUControl cpuControl; + private Quartz quartz; + + public void init() { + super.init(); + RuntimeConnections.MAIN.set(this); + CoreComponentConnections.CPU_LISTENERS.add(this); + } + + + public void resolveConnections() { + super.resolveConnections(); + addressSpace = CoreComponentConnections.ADDRESS_SPACE.resolve(); + r3000 = CoreComponentConnections.R3000.resolve(); + cpuControl = RuntimeConnections.CPU_CONTROL.resolve(); + quartz = CoreComponentConnections.QUARTZ.resolve(); + } + + public Console() { + super("JPSX Basic Console"); + } + + public void run() { + System.out.println("JPSX Copyright (C) 2003, 2014 Graham Sanderson"); + System.out.println("This program comes with ABSOLUTELY NO WARRANTY; type 'l' for details."); + System.out.println("This is free software, and you are welcome to redistribute it"); + System.out.println("under certain conditions; type 'l' for details."); + System.out.println(); + dumpMainRegs(); + + int lastDumpAddress = 0; + DataInputStream input = new DataInputStream(System.in); + boolean quit = false; + + long msBase = System.currentTimeMillis(); + long clockBase = quartz.nanoTime(); + showCurrentInstruction(); + try { + while (!quit) { + String line = input.readLine(); + if (line == null || line.length() == 0) { + continue; + } + switch (line.charAt(0)) { + case'r': + dumpMainRegs(); + break; + case'2': + dumpGTERegs(); + break; + case't': + long deltans = 1000000L * (System.currentTimeMillis() - msBase); + long deltaClock = quartz.nanoTime() - clockBase; + System.out.println("Clocks: " + deltans + " " + deltaClock + " " + (1.0 * deltaClock) / deltans); + msBase = System.currentTimeMillis(); + clockBase = quartz.nanoTime(); + break; + case'g': + cpuControl.go(); + break; + case'u': { + String addr = line.substring(1).trim(); + if (addr.length() > 0) + lastDisAddress = MiscUtil.parseHex(addr); + for (int i = 0; i < 20; i++) { + int ci = addressSpace.internalRead32(lastDisAddress); + String dis = r3000.disassemble(lastDisAddress, ci); + System.out.println(MiscUtil.toHex(lastDisAddress, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); + lastDisAddress += 4; + } + break; + } + case'o': { + String sStart = line.substring(1).trim(); + int pos = sStart.indexOf(' '); + if (pos != -1) { + int start = MiscUtil.parseHex(sStart); + int end = MiscUtil.parseHex(sStart.substring(pos).trim()); + try { + PrintWriter fw = new PrintWriter(new FileOutputStream("o.dis")); + for (int i = start; i < end; i += 4) { + int ci = addressSpace.internalRead32(i); + String dis = MiscUtil.toHex(i, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + r3000.disassemble(i, ci); + fw.println(dis); + } + fw.close(); + } catch (IOException e) { + } + } + break; + } + case'l': + LineNumberReader reader = new LineNumberReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("LICENSE"))); + String licenseLine; + while (null != (licenseLine = reader.readLine())) { + System.out.println(licenseLine); + } + break; + case'b': + if (line.length() > 1) { + try { + switch (line.charAt(1)) { + case 'l': { + int[] bps = cpuControl.getBreakpoints(); + for (int i = 0; i < bps.length; i++) { + System.out.println(Integer.toHexString(i) + ": " + MiscUtil.toHex(bps[i], 8)); + } + break; + } + case 'p': + case ' ': { + int address = MiscUtil.parseHex(line.substring(2)); + cpuControl.addBreakpoint(address); + break; + } + case 'c': { + int address = MiscUtil.parseHex(line.substring(2)); + cpuControl.removeBreakpoint(address); + break; + } + } + } catch (Throwable t) { + System.out.println("Failed to set breakpoint: " + t); + } + } else { + cpuControl.pause(); + } + break; + // RAM breakpoints + case'm': + if (line.length() > 1 && addressSpace.getClass() == DebugAddressSpaceImpl.class) { + DebugAddressSpaceImpl debugAddressSpace = (DebugAddressSpaceImpl) addressSpace; + try { + switch (line.charAt(1)) { + case 'l': { + int[] bps = debugAddressSpace.getActiveRAMBreakpoints(); + for (int i = 0; i < bps.length; i++) { + System.out.println(Integer.toHexString(i) + ": " + MiscUtil.toHex(bps[i], 8)); + } + break; + } + case 'p': + case ' ': { + int address = MiscUtil.parseHex(line.substring(2)); + debugAddressSpace.activateRAMBreakpoint(address); + break; + } + case 'c': { + int address = MiscUtil.parseHex(line.substring(2)); + debugAddressSpace.deactivateRAMBreakpoint(address); + break; + } + } + } catch (Throwable t) { + System.out.println("Failed to set breakpoint: " + t); + } + } else if (addressSpace.getClass() != DebugAddressSpaceImpl.class) { + System.out.println("You must use DebugAddressSpaceImpl in order to use this feature. Currently using: " + addressSpace.getClass().getName()); + } + break; + case'c': + System.out.println("calling for gc"); + System.gc(); + break; + case'i': + try { + int i = Integer.parseInt(line.substring(1).trim()); + System.out.println("Raising IRQ " + i); + CoreComponentConnections.IRQ_CONTROLLER.resolve().raiseIRQ(i); + } catch (Throwable t) { + } + break; + case'w': { + int type = 'd'; + int base = 1; + if (base < line.length()) { + if (line.charAt(base) == 'w') { + type = 'w'; + base++; + } else if (line.charAt(base) == 'b') { + type = 'b'; + base++; + } + } + String parse = line.substring(base); + parse = parse.trim(); + if (parse.length() > 0) { + int split = parse.indexOf(' '); + try { + if (split >= 0) { + int address = MiscUtil.parseHex(parse.substring(0, split).trim()); + int value = MiscUtil.parseHex(parse.substring(split).trim()); + //System.out.println("address = "+MiscUtil.toHex( address, 8)+" value = "+MiscUtil.toHex( value, 8)); + switch (type) { + case'd': + addressSpace.write32(address, value); + break; + case'w': + addressSpace.write16(address, value & 0xffff); + break; + case'b': + addressSpace.write8(address, value & 0xff); + break; + } + } + } catch (Throwable t) { + } + } + break; + } + case'd': { + int type = 'd'; + int base = 1; + if (base < line.length()) { + if (line.charAt(base) == 'w') { + type = 'w'; + base++; + } else if (line.charAt(base) == 'b') { + type = 'b'; + base++; + } + } + String parse = line.substring(base); + parse = parse.trim(); + int count = 6; + int address = lastDumpAddress; + if (parse.length() > 0) { + int split = parse.indexOf(' '); + try { + if (split >= 0) { + count = Integer.parseInt(parse.substring(split).trim()); + } + } catch (Throwable t) { + } + address = MiscUtil.parseHex(parse); + } + if (count > 0) { + for (int i = 0; i < count; i++, address += 16) { + int j; + String val = MiscUtil.toHex(address, 8) + ": "; + switch (type) { + case'd': + if (0 != (address & 3)) + address = address & ~3; + for (j = 0; j < 4; j++) { + val += MiscUtil.toHex(addressSpace.read32(address + j * 4), 8) + " "; + } + break; + case'w': + if (0 != (address & 1)) + address = address & ~1; + for (j = 0; j < 8; j++) { + val += MiscUtil.toHex(addressSpace.read16(address + j * 2), 4) + " "; + } + break; + case'b': + for (j = 0; j < 16; j++) { + val += MiscUtil.toHex(addressSpace.read8(address + j), 2) + " "; + } + break; + } + val += " "; + for (j = 0; j < 16; j++) { + int b = addressSpace.read8(address + j); + if (b >= 32 && b < 127) { + val += (char) b; + } else { + val += " "; + } + } + System.out.println(val); + } + lastDumpAddress = address; + } + break; + } + case's': + cpuControl.step(); + break; + case'q': + //if (jsx.core.NativeCompiler.profiling) { + // jsx.core.NativeCompiler.dumpProfiling(); + //} + quit = true; + break; + case'v': + String parse = line.substring(2); + parse = parse.trim(); + if (parse.startsWith("fill")) { + //SPU.fill(); + break; + } + int sp = parse.indexOf(' '); + if (sp > 0) { + try { + int voice = Integer.parseInt(parse.substring(0, sp)); + parse = parse.substring(sp + 1); + if (voice >= 0 && voice < 24) { + if (parse.startsWith("on")) { + if (voice < 16) { + addressSpace.write16(0x1f801d88, 1 << (voice)); + } else { + addressSpace.write16(0x1f801d8a, 1 << (voice - 16)); + } + System.out.println("voice " + voice + " on"); + } else if (parse.startsWith("off")) { + if (voice < 16) { + addressSpace.write16(0x1f801d8c, 1 << (voice)); + } else { + addressSpace.write16(0x1f801d8e, 1 << (voice - 16)); + } + System.out.println("voice " + voice + " off"); + } else if (parse.startsWith("freq")) { + int freq = MiscUtil.parseHex(parse.substring(5)); + addressSpace.write16(0x1f801c04 + (voice * 16), freq); + System.out.println("voice " + voice + " freq set to " + MiscUtil.toHex(freq, 4)); + } + } + } catch (Throwable t) { + } + } + break; + } + } + ; + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public void showCurrentInstruction() { + if (skipShow) { + skipShow = false; + } else { + int pc = r3000.getPC(); + int ci = addressSpace.internalRead32(pc); + String dis = r3000.disassemble(pc, ci); + System.out.println(MiscUtil.toHex(pc, 8) + ": " + MiscUtil.toHex(ci, 8) + " " + dis); + lastDisAddress = pc + 4; + } + } + + public void dumpGTERegs() { + System.out.println("vxy0 " + MiscUtil.toHex(GTE.readRegister(0x00), 8) + " vz0 " + MiscUtil.toHex(GTE.readRegister(0x01), 8) + " vxy1 " + MiscUtil.toHex(GTE.readRegister(0x02), 8) + " vz1 " + MiscUtil.toHex(GTE.readRegister(0x03), 8)); + System.out.println("vxy2 " + MiscUtil.toHex(GTE.readRegister(0x04), 8) + " vz2 " + MiscUtil.toHex(GTE.readRegister(0x05), 8) + " rgb " + MiscUtil.toHex(GTE.readRegister(0x06), 8) + " otz " + MiscUtil.toHex(GTE.readRegister(0x07), 8)); + System.out.println("ir0 " + MiscUtil.toHex(GTE.readRegister(0x08), 8) + " ir1 " + MiscUtil.toHex(GTE.readRegister(0x09), 8) + " ir2 " + MiscUtil.toHex(GTE.readRegister(0x0a), 8) + " ir3 " + MiscUtil.toHex(GTE.readRegister(0x0b), 8)); + System.out.println("sxy0 " + MiscUtil.toHex(GTE.readRegister(0x0c), 8) + " sxy1 " + MiscUtil.toHex(GTE.readRegister(0x0d), 8) + " sxy2 " + MiscUtil.toHex(GTE.readRegister(0x0e), 8) + " sxyp " + MiscUtil.toHex(GTE.readRegister(0x0f), 8)); + System.out.println("sz0 " + MiscUtil.toHex(GTE.readRegister(0x10), 8) + " sz1 " + MiscUtil.toHex(GTE.readRegister(0x11), 8) + " sz2 " + MiscUtil.toHex(GTE.readRegister(0x12), 8) + " sz3 " + MiscUtil.toHex(GTE.readRegister(0x13), 8)); + System.out.println("rgb0 " + MiscUtil.toHex(GTE.readRegister(0x14), 8) + " rgb1 " + MiscUtil.toHex(GTE.readRegister(0x15), 8) + " rgb2 " + MiscUtil.toHex(GTE.readRegister(0x16), 8) + " res1 " + MiscUtil.toHex(GTE.readRegister(0x17), 8)); + System.out.println("mac0 " + MiscUtil.toHex(GTE.readRegister(0x18), 8) + " mac1 " + MiscUtil.toHex(GTE.readRegister(0x19), 8) + " mac2 " + MiscUtil.toHex(GTE.readRegister(0x1a), 8) + " mac3 " + MiscUtil.toHex(GTE.readRegister(0x1b), 8)); + System.out.println("irgb " + MiscUtil.toHex(GTE.readRegister(0x1c), 8) + " orgb " + MiscUtil.toHex(GTE.readRegister(0x1d), 8) + " lzcs " + MiscUtil.toHex(GTE.readRegister(0x1e), 8) + " lzcr " + MiscUtil.toHex(GTE.readRegister(0x1f), 8)); + System.out.println("r11r12 " + MiscUtil.toHex(GTE.readRegister(0x20), 8) + " r13r21 " + MiscUtil.toHex(GTE.readRegister(0x21), 8) + " r22r23 " + MiscUtil.toHex(GTE.readRegister(0x22), 8) + " r31r32 " + MiscUtil.toHex(GTE.readRegister(0x23), 8)); + System.out.println("r33 " + MiscUtil.toHex(GTE.readRegister(0x24), 8) + " trx " + MiscUtil.toHex(GTE.readRegister(0x25), 8) + " try " + MiscUtil.toHex(GTE.readRegister(0x26), 8) + " trz " + MiscUtil.toHex(GTE.readRegister(0x27), 8)); + System.out.println("l11r12 " + MiscUtil.toHex(GTE.readRegister(0x28), 8) + " l13r21 " + MiscUtil.toHex(GTE.readRegister(0x29), 8) + " l22r23 " + MiscUtil.toHex(GTE.readRegister(0x2a), 8) + " l31r32 " + MiscUtil.toHex(GTE.readRegister(0x2b), 8)); + System.out.println("l33 " + MiscUtil.toHex(GTE.readRegister(0x2c), 8) + " rbk " + MiscUtil.toHex(GTE.readRegister(0x2d), 8) + " gbk " + MiscUtil.toHex(GTE.readRegister(0x2e), 8) + " bbk " + MiscUtil.toHex(GTE.readRegister(0x2f), 8)); + System.out.println("lr1lr2 " + MiscUtil.toHex(GTE.readRegister(0x30), 8) + " lr3lg1 " + MiscUtil.toHex(GTE.readRegister(0x31), 8) + " lg2lg3 " + MiscUtil.toHex(GTE.readRegister(0x32), 8) + " lb1lb2 " + MiscUtil.toHex(GTE.readRegister(0x33), 8)); + System.out.println("lb3 " + MiscUtil.toHex(GTE.readRegister(0x34), 8) + " rfc " + MiscUtil.toHex(GTE.readRegister(0x35), 8) + " gfc " + MiscUtil.toHex(GTE.readRegister(0x36), 8) + " bfc " + MiscUtil.toHex(GTE.readRegister(0x37), 8)); + System.out.println("ofx " + MiscUtil.toHex(GTE.readRegister(0x38), 8) + " ofy " + MiscUtil.toHex(GTE.readRegister(0x39), 8) + " h " + MiscUtil.toHex(GTE.readRegister(0x3a), 8) + " dqa " + MiscUtil.toHex(GTE.readRegister(0x3b), 8)); + System.out.println("dqb " + MiscUtil.toHex(GTE.readRegister(0x3c), 8) + " zsf3 " + MiscUtil.toHex(GTE.readRegister(0x3d), 8) + " zsf4 " + MiscUtil.toHex(GTE.readRegister(0x3e), 8) + " flag " + MiscUtil.toHex(GTE.readRegister(0x3f), 8)); + } + + public void dumpMainRegs() { + System.out.println("r0 " + MiscUtil.toHex(r3000.getReg(0), 8) + " r1 " + MiscUtil.toHex(r3000.getReg(1), 8) + " r2 " + MiscUtil.toHex(r3000.getReg(2), 8) + " r3 " + MiscUtil.toHex(r3000.getReg(3), 8) + " pc " + MiscUtil.toHex(r3000.getPC(), 8)); + System.out.println("r4 " + MiscUtil.toHex(r3000.getReg(4), 8) + " r5 " + MiscUtil.toHex(r3000.getReg(5), 8) + " r6 " + MiscUtil.toHex(r3000.getReg(6), 8) + " r7 " + MiscUtil.toHex(r3000.getReg(7), 8) + " lo " + MiscUtil.toHex(r3000.getLO(), 8)); + System.out.println("r8 " + MiscUtil.toHex(r3000.getReg(8), 8) + " r9 " + MiscUtil.toHex(r3000.getReg(9), 8) + " r10 " + MiscUtil.toHex(r3000.getReg(10), 8) + " r11 " + MiscUtil.toHex(r3000.getReg(11), 8) + " hi " + MiscUtil.toHex(r3000.getHI(), 8)); + System.out.println("r12 " + MiscUtil.toHex(r3000.getReg(12), 8) + " r13 " + MiscUtil.toHex(r3000.getReg(13), 8) + " r14 " + MiscUtil.toHex(r3000.getReg(14), 8) + " r15 " + MiscUtil.toHex(r3000.getReg(15), 8)); + System.out.println("r16 " + MiscUtil.toHex(r3000.getReg(16), 8) + " r17 " + MiscUtil.toHex(r3000.getReg(17), 8) + " r18 " + MiscUtil.toHex(r3000.getReg(18), 8) + " r19 " + MiscUtil.toHex(r3000.getReg(19), 8)); + System.out.println("r20 " + MiscUtil.toHex(r3000.getReg(20), 8) + " r21 " + MiscUtil.toHex(r3000.getReg(21), 8) + " r22 " + MiscUtil.toHex(r3000.getReg(22), 8) + " r23 " + MiscUtil.toHex(r3000.getReg(23), 8)); + System.out.println("r24 " + MiscUtil.toHex(r3000.getReg(24), 8) + " r25 " + MiscUtil.toHex(r3000.getReg(25), 8) + " r26 " + MiscUtil.toHex(r3000.getReg(26), 8) + " r27 " + MiscUtil.toHex(r3000.getReg(27), 8)); + System.out.println("r28 " + MiscUtil.toHex(r3000.getReg(28), 8) + " r29 " + MiscUtil.toHex(r3000.getReg(29), 8) + " r30 " + MiscUtil.toHex(r3000.getReg(30), 8) + " r31 " + MiscUtil.toHex(r3000.getReg(31), 8)); + } + + public void cpuResumed() { + } + + public void cpuPaused() { + showCurrentInstruction(); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java new file mode 100644 index 0000000..2cb7064 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.debugcomponents.emulator.disassemblers; + +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; +import org.jpsx.api.components.core.cpu.InstructionProvider; +import org.jpsx.api.components.core.cpu.InstructionRegistrar; +import org.jpsx.runtime.JPSXComponent; +import org.jpsx.runtime.components.core.CoreComponentConnections; + +public abstract class DisassemblerComponent extends JPSXComponent implements InstructionProvider { + protected DisassemblerComponent(String description) { + super(description); + } + + @Override + public void init() { + super.init(); + CoreComponentConnections.INSTRUCTION_PROVIDERS.add(this); + } + + protected static String padString(String s) { + return padString(s, 8); + } + + protected static String padString(String val, int chars) { + String rc = val + " "; + return rc.substring(0, chars); + } + + protected static class DIS implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()); + } + } + + public abstract void addInstructions(InstructionRegistrar registrar); +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java new file mode 100644 index 0000000..7e73e5d --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.debugcomponents.emulator.disassemblers; + +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; +import org.jpsx.api.components.core.cpu.InstructionRegistrar; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.runtime.util.MiscUtil; + +public class GTEInstructionDisassembler extends DisassemblerComponent { + public GTEInstructionDisassembler() { + super("JPSX Disassembler for GTE Instructions"); + } + + public void addInstructions(InstructionRegistrar registrar) { + DIS dis = new DIS(); + registrar.setInstructionDisassembler("eret", dis); + registrar.setInstructionDisassembler("mtc2", new DIS_MTC2()); + registrar.setInstructionDisassembler("mfc2", new DIS_MFC2()); + registrar.setInstructionDisassembler("ctc2", new DIS_CTC2()); + registrar.setInstructionDisassembler("cfc2", new DIS_CFC2()); + registrar.setInstructionDisassembler("lwc2", new DIS_LWC2()); + registrar.setInstructionDisassembler("swc2", new DIS_SWC2()); + registrar.setInstructionDisassembler("rtpt", dis); + registrar.setInstructionDisassembler("rtps", dis); + registrar.setInstructionDisassembler("mvmva", dis); + registrar.setInstructionDisassembler("op", dis); + registrar.setInstructionDisassembler("avsz3", dis); + registrar.setInstructionDisassembler("avsz4", dis); + registrar.setInstructionDisassembler("nclip", dis); + registrar.setInstructionDisassembler("ncct", dis); + registrar.setInstructionDisassembler("gpf", dis); + registrar.setInstructionDisassembler("dcpl", dis); + registrar.setInstructionDisassembler("dpcs", dis); + registrar.setInstructionDisassembler("intpl", dis); + registrar.setInstructionDisassembler("sqr", dis); + registrar.setInstructionDisassembler("ncs", dis); + registrar.setInstructionDisassembler("nct", dis); + registrar.setInstructionDisassembler("ncds", dis); + registrar.setInstructionDisassembler("ncdt", dis); + registrar.setInstructionDisassembler("dpct", dis); + registrar.setInstructionDisassembler("nccs", dis); + registrar.setInstructionDisassembler("cdp", dis); + registrar.setInstructionDisassembler("cc", dis); + registrar.setInstructionDisassembler("gpl", dis); + } + + + private static final String gteNames[] = new String[]{ + "vxy0", "vz0", "vxy1", "vz1", "vxy2", "vz2", "rgb", "otz", + "ir0", "ir1", "ir2", "ir3", "sxy0", "sxy1", "sxy2", "sxyp", + "szx", "sz0", "sz1", "sz2", "rgb0", "rgb1", "rgb2", "res1", + "mac0", "mac1", "mac2", "mac3", "irgb", "orgb", "lzcs", "lzcr", + "r11r12", "r13r21", "r22r23", "r31r32", "r33", "trx", "try", "trz", + "l11l12", "l13l21", "l22l23", "l31l32", "l33", "rbk", "gbk", "bbk", + "lr1lr2", "lr3lg1", "lg2lg3", "lb1lb2", "lb3", "rfc", "gfc", "bfc", + "ofx", "ofy", "h", "dqa", "dqb", "zsf3", "zsf4", "flag" + }; + + private static class DIS_LWC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + return padString(inst.getName()) + " " + gteNames[R3000.Util.bits_rt(ci)] + ", r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "]"; + } + } + + private static class DIS_SWC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "], " + gteNames[R3000.Util.bits_rt(ci)]; + } + } + + private static class DIS_MTC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + return padString(inst.getName()) + " " + gteNames[rd] + ", r" + rt; + } + } + + private static class DIS_MFC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + return padString(inst.getName()) + " r" + rt + ", " + gteNames[rd]; + } + } + + private static class DIS_CTC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + return padString(inst.getName()) + " " + gteNames[rd + 32] + ", r" + rt; + } + } + + private static class DIS_CFC2 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + return padString(inst.getName()) + " r" + rt + ", " + gteNames[rd + 32]; + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java new file mode 100644 index 0000000..89885bf --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.debugcomponents.emulator.disassemblers; + +import org.jpsx.api.components.core.cpu.CPUInstruction; +import org.jpsx.api.components.core.cpu.CPUInstructionDisassembler; +import org.jpsx.api.components.core.cpu.InstructionRegistrar; +import org.jpsx.api.components.core.cpu.R3000; +import org.jpsx.runtime.util.MiscUtil; + +// TODO move setting of instructions elsewhere + +public class R3000InstructionDisassembler extends DisassemblerComponent { + public R3000InstructionDisassembler() { + super("JPSX Disassembler for R3000 Instructions"); + } + + public void addInstructions(InstructionRegistrar registrar) { + DIS_TSB disTSB = new DIS_TSB(); + DIS_SB disSB = new DIS_SB(); + DIS_TSI disTSI = new DIS_TSI(); + DIS_TSIU disTSIU = new DIS_TSIU(); + DIS_TIU disTIU = new DIS_TIU(); + DIS_TSA disTSA = new DIS_TSA(); + DIS_SAT disSAT = new DIS_SAT(); + DIS_ST disST = new DIS_ST(); + DIS_DTH disDTH = new DIS_DTH(); + DIS_DST disDST = new DIS_DST(); + DIS_DTS disDTS = new DIS_DTS(); + DIS_J disJ = new DIS_J(); + DIS_S disS = new DIS_S(); + DIS_D disD = new DIS_D(); + DIS_SD disSD = new DIS_SD(); + DIS_C disC = new DIS_C(); + DIS dis = new DIS(); + + registrar.setInstructionDisassembler("bne", disTSB); + registrar.setInstructionDisassembler("beq", disTSB); + registrar.setInstructionDisassembler("addi", disTSI); + registrar.setInstructionDisassembler("addiu", disTSI); + registrar.setInstructionDisassembler("slti", disTSI); + registrar.setInstructionDisassembler("sltiu", disTSI); + registrar.setInstructionDisassembler("andi", disTSIU); + registrar.setInstructionDisassembler("ori", disTSIU); + registrar.setInstructionDisassembler("xori", disTSIU); + registrar.setInstructionDisassembler("sll", disDTH); + registrar.setInstructionDisassembler("srl", disDTH); + registrar.setInstructionDisassembler("sra", disDTH); + registrar.setInstructionDisassembler("bltz", disSB); + registrar.setInstructionDisassembler("bgez", disSB); + registrar.setInstructionDisassembler("blez", disSB); + registrar.setInstructionDisassembler("bgtz", disSB); + registrar.setInstructionDisassembler("bltzal", disSB); + registrar.setInstructionDisassembler("bgezal", disSB); + registrar.setInstructionDisassembler("add", disDST); + registrar.setInstructionDisassembler("addu", disDST); + registrar.setInstructionDisassembler("sub", disDST); + registrar.setInstructionDisassembler("subu", disDST); + registrar.setInstructionDisassembler("and", disDST); + registrar.setInstructionDisassembler("or", disDST); + registrar.setInstructionDisassembler("xor", disDST); + registrar.setInstructionDisassembler("nor", disDST); + registrar.setInstructionDisassembler("slt", disDST); + registrar.setInstructionDisassembler("sltu", disDST); + registrar.setInstructionDisassembler("lb", disTSA); + registrar.setInstructionDisassembler("lh", disTSA); + registrar.setInstructionDisassembler("lwl", disTSA); + registrar.setInstructionDisassembler("lw", disTSA); + registrar.setInstructionDisassembler("lbu", disTSA); + registrar.setInstructionDisassembler("lhu", disTSA); + registrar.setInstructionDisassembler("lwr", disTSA); + registrar.setInstructionDisassembler("sb", disSAT); + registrar.setInstructionDisassembler("sh", disSAT); + registrar.setInstructionDisassembler("swl", disSAT); + registrar.setInstructionDisassembler("sw", disSAT); + registrar.setInstructionDisassembler("swr", disSAT); + registrar.setInstructionDisassembler("lui", disTIU); + registrar.setInstructionDisassembler("sllv", disDTS); + registrar.setInstructionDisassembler("srlv", disDTS); + registrar.setInstructionDisassembler("srav", disDTS); + registrar.setInstructionDisassembler("mult", disST); + registrar.setInstructionDisassembler("multu", disST); + registrar.setInstructionDisassembler("div", disST); + registrar.setInstructionDisassembler("divu", disST); + registrar.setInstructionDisassembler("j", disJ); + registrar.setInstructionDisassembler("jal", disJ); + registrar.setInstructionDisassembler("jr", disS); + registrar.setInstructionDisassembler("mthi", disS); + registrar.setInstructionDisassembler("mtlo", disS); + registrar.setInstructionDisassembler("mfhi", disD); + registrar.setInstructionDisassembler("mflo", disD); + registrar.setInstructionDisassembler("jalr", disSD); + + registrar.setInstructionDisassembler("syscall", disC); + registrar.setInstructionDisassembler("break", disC); + registrar.setInstructionDisassembler("eret", dis); + registrar.setInstructionDisassembler("mtc0", new DIS_MTC0()); + registrar.setInstructionDisassembler("mfc0", new DIS_MFC0()); + } + + public static class DIS_TSB implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + " 0x" + MiscUtil.toHex(address + 4 + R3000.Util.signed_branch_delta(ci), 8); + } + } + + public static class DIS_SB implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + " 0x" + MiscUtil.toHex(address + 4 + R3000.Util.signed_branch_delta(ci), 8); + } + } + + public static class DIS_TSI implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.sign_extend(ci); + String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + ", 0x" + MiscUtil.toHex(val, 4); + return padString(rc, 32) + " ;" + val; + } + } + + public static class DIS_TSIU implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + ", 0x" + MiscUtil.toHex(val, 4); + return padString(rc, 32) + " ;" + val; + } + } + + public static class DIS_TIU implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + String rc = padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", 0x" + MiscUtil.toHex(val, 4); + return padString(rc, 32) + " ;" + val; + } + } + + public static class DIS_TSA implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + return padString(inst.getName()) + " r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "]"; + } + } + + public static class DIS_SAT implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int val = R3000.Util.lo(ci); + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + "[0x" + MiscUtil.toHex(val, 4) + "], r" + R3000.Util.bits_rt(ci); + } + } + + public static class DIS_ST implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rt(ci); + } + } + + public static class DIS_DTH implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + if (ci == 0) + return padString("nop"); + else + return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rt(ci) + ", " + R3000.Util.bits_sa(ci); + } + } + + public static class DIS_DST implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rt(ci); + } + } + + public static class DIS_DTS implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci) + ", r" + R3000.Util.bits_rt(ci) + ", r" + R3000.Util.bits_rs(ci); + } + } + + public static class DIS_J implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " 0x" + MiscUtil.toHex(((address + 4) & 0xf0000000) + ((ci & 0x3ffffff) << 2), 8); + } + } + + public static class DIS_S implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci); + } + } + + public static class DIS_D implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rd(ci); + } + } + + public static class DIS_C implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " 0x" + Integer.toHexString(R3000.Util.bits25_6(ci)); + } + } + + public static class DIS_SD implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + return padString(inst.getName()) + " r" + R3000.Util.bits_rs(ci) + ", r" + R3000.Util.bits_rd(ci); + } + } + + protected static String getCOP0Name(int reg, int sel) { + + switch ((sel << 16) + reg) { + case 0: + return "index"; + case 1: + return "random"; + case 2: + return "entryLow0"; + case 3: + return "entryLow1"; + case 4: + return "context"; + case 5: + return "pageMask"; + case 6: + return "wired"; + case 8: + return "badVAddr"; + case 9: + return "count"; + case 10: + return "entryHi"; + case 11: + return "compare"; + case 12: + return "status"; + case 13: + return "cause"; + case 14: + return "epc"; + case 15: + return "progId"; + case 16: + return "config"; + case 0x10010: + return "config1"; + case 0x20010: + return "config2"; + case 0x30010: + return "config3"; + case 30: + return "errorEPC"; + default: + return reg + ":" + sel; + } + } + + protected static class DIS_MTC0 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int sel = ci & 0x7; + return padString(inst.getName()) + " " + getCOP0Name(rd, sel) + ", r" + rt; + } + } + + protected static class DIS_MFC0 implements CPUInstructionDisassembler { + public String disassemble(CPUInstruction inst, int address, int ci) { + int rt = R3000.Util.bits_rt(ci); + int rd = R3000.Util.bits_rd(ci); + int sel = ci & 0x7; + return padString(inst.getName()) + " r" + rt + ", " + getCOP0Name(rd, sel); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/util/ByteCodeUtil.java b/src/runtime/src/main/java/org/jpsx/runtime/util/ByteCodeUtil.java new file mode 100644 index 0000000..4544b8c --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/util/ByteCodeUtil.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.util; + +import org.apache.bcel.generic.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.SortedMap; + +// todo client VM only + +public class ByteCodeUtil { + public static void emitSwitch(ConstantPoolGen cp, InstructionList il, int localIndex, SortedMap cases, int resolution, int lowBound, int highBound) { + if (cases.size() == 0) return; + if (true) { + emitBinaryTree(cp, il, localIndex, cases, resolution, lowBound, highBound); + } + } + + public static void emitBinaryTree(ConstantPoolGen cp, InstructionList il, int localIndex, SortedMap cases, int resolution, int lowBound, int highBound) { + List keys = new ArrayList(); + keys.addAll(cases.keySet()); + emitBinaryTree(cp, il, localIndex, keys, cases, resolution, lowBound, highBound, 0, keys.size() - 1); + } + + public static void emitBinaryTree(ConstantPoolGen cp, InstructionList il, int localIndex, List keys, SortedMap cases, int resolution, int lowBound, int highBound, int start, int end) { + if (start == end) { + IF_ICMPNE cmpne = null; + Integer key = keys.get(start); + boolean requireIf = key != lowBound || key != highBound; + if (requireIf) { + il.append(new ILOAD(localIndex)); + il.append(new PUSH(cp, key)); + cmpne = new IF_ICMPNE(null); + il.append(cmpne); + } + il.append(cases.get(key)); + if (requireIf) { + cmpne.setTarget(il.append(new NOP())); + } + } else { + int middle = (start + end + 1) / 2; + int middleValue = keys.get(middle); + + il.append(new ILOAD(localIndex)); + il.append(new PUSH(cp, middleValue)); + IF_ICMPGE cmpge = new IF_ICMPGE(null); + il.append(cmpge); + emitBinaryTree(cp, il, localIndex, keys, cases, resolution, lowBound, middleValue - resolution, start, middle - 1); + GOTO gt = new GOTO(null); + InstructionHandle gthandle = il.append(gt); + emitBinaryTree(cp, il, localIndex, keys, cases, resolution, middleValue, highBound, middle, end); + gt.setTarget(il.append(new NOP())); + cmpge.setTarget(gthandle.getNext()); + } + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/util/CDUtil.java b/src/runtime/src/main/java/org/jpsx/runtime/util/CDUtil.java new file mode 100644 index 0000000..895538f --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/util/CDUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.util; + +import org.jpsx.api.components.hardware.cd.CDMedia; +import org.jpsx.api.components.hardware.cd.MediaException; + +public class CDUtil { + // flags ORed together + public static final int MEDIA_PRESENT = 0x0001; + public static final int MEDIA_HAS_DATA = 0x0002; + public static final int MEDIA_HAS_AUDIO = 0x0004; + public static final int MEDIA_PLAYSTATION = 0x0008; + public static final int MEDIA_REGION_EUROPE = 0x0010; + public static final int MEDIA_REGION_USA = 0x0020; + public static final int MEDIA_REGION_JAPAN = 0x0040; + + public static int toBCD(int x) { + return (x % 10) + ((x / 10) << 4); + } + + public static int fromBCD(int x) { + return (x >> 4) * 10 + (x & 15); + } + + // todo fix up this method to return all types + public static int getMediaType(CDMedia media) { + int rc = 0; + if (media != null) { + rc |= MEDIA_PRESENT; + for (int i = media.getFirstTrack(); i <= media.getLastTrack(); i++) { + CDMedia.TrackType tt = media.getTrackType(i); + if (tt == CDMedia.TrackType.AUDIO) { + rc |= MEDIA_HAS_AUDIO; + } else if (tt == CDMedia.TrackType.MODE2_2352) { + rc |= MEDIA_HAS_DATA; + } + } + if (0 != (rc & MEDIA_HAS_DATA)) { + try { + int[] sector = new int[2352 / 4]; + media.readSector(4, sector); + int countryCode = (sector[0x15] & 0xff); + if (countryCode == 'E') { + rc |= MEDIA_REGION_EUROPE; + } else { + } + } catch (MediaException e) { + } + } + } + return rc; + } + + public static int toMSF(int m, int s, int f) { + return (toBCD(m) << 16) | (toBCD(s) << 8) | toBCD(f); + } + + public static int toSector(int m, int s, int f) { + return (m * 60 + s) * 75 + f - 150; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/util/ClassUtil.java b/src/runtime/src/main/java/org/jpsx/runtime/util/ClassUtil.java new file mode 100644 index 0000000..5756480 --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/util/ClassUtil.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.util; + +public class ClassUtil { + + public static String signatureOfClass(String clazz) { + return "L" + clazz.replace('.', '/') + ";"; + } + + public static String innerClassName(Class clazz, String innerClass) { + return clazz.getName() + "$" + innerClass; + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/util/MiscUtil.java b/src/runtime/src/main/java/org/jpsx/runtime/util/MiscUtil.java new file mode 100644 index 0000000..c5624bb --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/util/MiscUtil.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.util; + +import org.jpsx.runtime.RuntimeConnections; +import org.jpsx.runtime.components.core.CoreComponentConnections; + +public class MiscUtil { + public static String toHex(int val, int digits) { + String rc = Integer.toHexString(val); + if (rc.length() != digits) { + rc = "0000000000000000" + rc; + rc = rc.substring(rc.length() - digits, rc.length()); + } + return rc; + } + + protected static String ALPHA = "0123456789abcdef"; + + public static int parseHex(String hex) { + int rc = 0; + hex = hex.trim().toLowerCase(); + for (int i = 0; i < hex.length(); i++) { + int val = ALPHA.indexOf(hex.charAt(i)); + if (val == -1) { + break; + } + rc = (rc << 4) + val; + } + return rc; + } + + private static int assertionCounter; + + /** + * Note the intention is not to pass a boolean flag here, since the check cannot be elided by the compiler + * if it is known to be false at the call site + * + * @param message + */ + public static void assertionMessage(String message) { + int pc = CoreComponentConnections.R3000.resolve().getPC(); + System.out.println(toHex(assertionCounter++, 8) + " " + toHex(pc, 8) + ": " + message); + + // we may want to have a version that pauses - note this now works correctly from execution thread. + //RuntimeConnections.CPU_CONTROL.resolve().pause(); + } +} diff --git a/src/runtime/src/main/java/org/jpsx/runtime/util/Timing.java b/src/runtime/src/main/java/org/jpsx/runtime/util/Timing.java new file mode 100644 index 0000000..a9d73fc --- /dev/null +++ b/src/runtime/src/main/java/org/jpsx/runtime/util/Timing.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2003, 2014 Graham Sanderson + * + * This file is part of JPSX. + * + * JPSX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JPSX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JPSX. If not, see . + */ +package org.jpsx.runtime.util; + +public class Timing { + public static final String CATEGORY = "Timing"; + + public static long nanos() { + return System.nanoTime(); + } +} + From 9c303a8666cd1f7122fce4e07857c22d7517e1e7 Mon Sep 17 00:00:00 2001 From: neoexpert Date: Fri, 10 Jul 2020 09:43:59 +0200 Subject: [PATCH 3/6] port to maven --- src/bootstrap/pom.xml | 2 -- src/pom.xml | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/pom.xml b/src/bootstrap/pom.xml index 37f1130..fab81ef 100644 --- a/src/bootstrap/pom.xml +++ b/src/bootstrap/pom.xml @@ -39,6 +39,4 @@ - - diff --git a/src/pom.xml b/src/pom.xml index 1579d76..ce22818 100644 --- a/src/pom.xml +++ b/src/pom.xml @@ -23,6 +23,26 @@ 4.11 test + + org.jpsx + api + 1.0-SNAPSHOT + + + org.jpsx + bootstrap + 1.0-SNAPSHOT + + + org.jpsx + runtime + 1.0-SNAPSHOT + + + org.jpsx + lwjgl + 1.0-SNAPSHOT + @@ -31,4 +51,32 @@ lwjgl runtime + + jpsx + + + maven-assembly-plugin + 3.1.1 + + + jar-with-dependencies + + + + org.jpsx.bootstrap.JPSXLauncher + + + + + + make-assembly + package + + single + + + + + + From 95d4df06ae132041c38b41d2c5bb956fc026d7af Mon Sep 17 00:00:00 2001 From: neoexpert Date: Fri, 10 Jul 2020 10:21:05 +0200 Subject: [PATCH 4/6] port to maven --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bac46c6..6ed84df 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ should only really be needed on very slow machines, and breaks some code that us ## Building the Emulator -JPSX is very simple to build. Just run `ant`, and it will build `jar` files in the `ship` folder. +JPSX is very simple to build. Just run `mvn clean install` in the src folder, and it will build a `jar` file in the `src/target` folder. ## Running the Emulator From e685533b5bf0d16e640c4212ac95b49ffacf6277 Mon Sep 17 00:00:00 2001 From: neoexpert Date: Fri, 10 Jul 2020 18:00:38 +0200 Subject: [PATCH 5/6] maven port --- {src/api => api}/pom.xml | 0 .../main/java/org/jpsx/api/CPUControl.java | 0 .../main/java/org/jpsx/api/CPUListener.java | 0 .../api/InvalidConfigurationException.java | 0 .../core/ContinueExecutionException.java | 0 .../core/ImmediateBreakoutException.java | 0 .../core/ReturnFromExceptionException.java | 0 .../core/addressspace/AddressSpace.java | 0 .../addressspace/AddressSpaceListener.java | 0 .../addressspace/AddressSpaceRegistrar.java | 0 .../core/addressspace/MemoryMapped.java | 0 .../core/addressspace/Pollable.java | 0 .../components/core/cpu/CPUInstruction.java | 0 .../core/cpu/CPUInstructionDisassembler.java | 0 .../core/cpu/CompilationContext.java | 0 .../core/cpu/InstructionProvider.java | 0 .../core/cpu/InstructionRegistrar.java | 0 .../components/core/cpu/NativeCompiler.java | 0 .../core/cpu/PollBlockListener.java | 0 .../jpsx/api/components/core/cpu/R3000.java | 0 .../org/jpsx/api/components/core/cpu/SCP.java | 0 .../components/core/dma/DMAChannelOwner.java | 0 .../components/core/dma/DMAController.java | 0 .../components/core/irq/IRQController.java | 0 .../api/components/core/irq/IRQOwner.java | 0 .../api/components/core/scheduler/Quartz.java | 0 .../core/scheduler/ScheduledAction.java | 0 .../components/core/scheduler/Scheduler.java | 0 .../components/hardware/cd/CDAudioSink.java | 0 .../api/components/hardware/cd/CDDrive.java | 0 .../api/components/hardware/cd/CDMedia.java | 0 .../hardware/cd/MediaException.java | 0 .../api/components/hardware/gpu/Display.java | 0 .../hardware/gpu/DisplayManager.java | 0 .../components/hardware/sio/SerialDevice.java | 0 .../components/hardware/sio/SerialPort.java | 0 {src/bootstrap => bootstrap}/pom.xml | 0 .../java/org/jpsx/bootstrap/JPSXLauncher.java | 0 .../org/jpsx/bootstrap/JPSXLauncher2.java | 0 .../jpsx/bootstrap/JPSXMachineLifecycle.java | 0 .../bootstrap/classloader/ClassGenerator.java | 0 .../bootstrap/classloader/ClassModifier.java | 0 .../classloader/JPSXClassLoader.java | 0 .../configuration/ComponentDefinition.java | 0 .../configuration/MachineDefinition.java | 0 .../XMLMachineDefinitionParser.java | 0 .../jpsx/bootstrap/connection/Connection.java | 0 .../connection/MultipleConnection.java | 0 .../connection/SimpleConnection.java | 0 .../bootstrap/util/CollectionsFactory.java | 0 build.xml | 124 - external/bcel-5.1/BCEL.iml | 15 - external/bcel-5.1/LICENSE.txt | 53 - external/bcel-5.1/build.xml | 350 --- external/bcel-5.1/project.xml | 94 - .../src/java/org/apache/bcel/Constants.java | 785 ----- .../org/apache/bcel/ExceptionConstants.java | 123 - .../src/java/org/apache/bcel/Repository.java | 248 -- .../apache/bcel/classfile/AccessFlags.java | 171 -- .../org/apache/bcel/classfile/Attribute.java | 302 -- .../bcel/classfile/AttributeReader.java | 97 - .../bcel/classfile/ClassFormatException.java | 69 - .../apache/bcel/classfile/ClassParser.java | 328 -- .../java/org/apache/bcel/classfile/Code.java | 373 --- .../apache/bcel/classfile/CodeException.java | 229 -- .../org/apache/bcel/classfile/Constant.java | 148 - .../org/apache/bcel/classfile/ConstantCP.java | 154 - .../apache/bcel/classfile/ConstantClass.java | 154 - .../apache/bcel/classfile/ConstantDouble.java | 142 - .../bcel/classfile/ConstantFieldref.java | 104 - .../apache/bcel/classfile/ConstantFloat.java | 141 - .../bcel/classfile/ConstantInteger.java | 148 - .../classfile/ConstantInterfaceMethodref.java | 104 - .../apache/bcel/classfile/ConstantLong.java | 139 - .../bcel/classfile/ConstantMethodref.java | 104 - .../bcel/classfile/ConstantNameAndType.java | 171 -- .../apache/bcel/classfile/ConstantObject.java | 69 - .../apache/bcel/classfile/ConstantPool.java | 372 --- .../apache/bcel/classfile/ConstantString.java | 147 - .../apache/bcel/classfile/ConstantUtf8.java | 147 - .../apache/bcel/classfile/ConstantValue.java | 178 -- .../org/apache/bcel/classfile/Deprecated.java | 169 -- .../bcel/classfile/DescendingVisitor.java | 357 --- .../apache/bcel/classfile/EmptyVisitor.java | 105 - .../apache/bcel/classfile/ExceptionTable.java | 202 -- .../java/org/apache/bcel/classfile/Field.java | 165 - .../apache/bcel/classfile/FieldOrMethod.java | 223 -- .../org/apache/bcel/classfile/InnerClass.java | 221 -- .../apache/bcel/classfile/InnerClasses.java | 181 -- .../org/apache/bcel/classfile/JavaClass.java | 815 ----- .../org/apache/bcel/classfile/LineNumber.java | 164 - .../bcel/classfile/LineNumberTable.java | 240 -- .../apache/bcel/classfile/LocalVariable.java | 259 -- .../bcel/classfile/LocalVariableTable.java | 196 -- .../org/apache/bcel/classfile/Method.java | 228 -- .../java/org/apache/bcel/classfile/Node.java | 65 - .../org/apache/bcel/classfile/PMGClass.java | 189 -- .../org/apache/bcel/classfile/Signature.java | 296 -- .../org/apache/bcel/classfile/SourceFile.java | 173 -- .../org/apache/bcel/classfile/StackMap.java | 185 -- .../apache/bcel/classfile/StackMapEntry.java | 209 -- .../apache/bcel/classfile/StackMapType.java | 172 -- .../org/apache/bcel/classfile/Synthetic.java | 176 -- .../org/apache/bcel/classfile/Unknown.java | 213 -- .../org/apache/bcel/classfile/Utility.java | 1416 --------- .../org/apache/bcel/classfile/Visitor.java | 101 - .../org/apache/bcel/classfile/package.html | 14 - .../java/org/apache/bcel/generic/AALOAD.java | 87 - .../java/org/apache/bcel/generic/AASTORE.java | 87 - .../org/apache/bcel/generic/ACONST_NULL.java | 94 - .../java/org/apache/bcel/generic/ALOAD.java | 92 - .../org/apache/bcel/generic/ANEWARRAY.java | 114 - .../java/org/apache/bcel/generic/ARETURN.java | 88 - .../org/apache/bcel/generic/ARRAYLENGTH.java | 92 - .../java/org/apache/bcel/generic/ASTORE.java | 92 - .../java/org/apache/bcel/generic/ATHROW.java | 92 - .../bcel/generic/AllocationInstruction.java | 64 - .../bcel/generic/ArithmeticInstruction.java | 106 - .../apache/bcel/generic/ArrayInstruction.java | 106 - .../org/apache/bcel/generic/ArrayType.java | 156 - .../java/org/apache/bcel/generic/BALOAD.java | 87 - .../java/org/apache/bcel/generic/BASTORE.java | 87 - .../java/org/apache/bcel/generic/BIPUSH.java | 131 - .../org/apache/bcel/generic/BREAKPOINT.java | 79 - .../org/apache/bcel/generic/BasicType.java | 101 - .../org/apache/bcel/generic/BranchHandle.java | 168 -- .../bcel/generic/BranchInstruction.java | 246 -- .../java/org/apache/bcel/generic/CALOAD.java | 87 - .../java/org/apache/bcel/generic/CASTORE.java | 87 - .../org/apache/bcel/generic/CHECKCAST.java | 117 - .../apache/bcel/generic/CPInstruction.java | 166 -- .../org/apache/bcel/generic/ClassGen.java | 451 --- .../bcel/generic/ClassGenException.java | 68 - .../apache/bcel/generic/ClassObserver.java | 67 - .../apache/bcel/generic/CodeExceptionGen.java | 202 -- .../bcel/generic/CompoundInstruction.java | 76 - .../apache/bcel/generic/ConstantPoolGen.java | 786 ----- .../bcel/generic/ConstantPushInstruction.java | 70 - .../bcel/generic/ConversionInstruction.java | 102 - .../src/java/org/apache/bcel/generic/D2F.java | 87 - .../src/java/org/apache/bcel/generic/D2I.java | 87 - .../src/java/org/apache/bcel/generic/D2L.java | 87 - .../java/org/apache/bcel/generic/DADD.java | 88 - .../java/org/apache/bcel/generic/DALOAD.java | 87 - .../java/org/apache/bcel/generic/DASTORE.java | 87 - .../java/org/apache/bcel/generic/DCMPG.java | 93 - .../java/org/apache/bcel/generic/DCMPL.java | 92 - .../java/org/apache/bcel/generic/DCONST.java | 111 - .../java/org/apache/bcel/generic/DDIV.java | 88 - .../java/org/apache/bcel/generic/DLOAD.java | 92 - .../java/org/apache/bcel/generic/DMUL.java | 88 - .../java/org/apache/bcel/generic/DNEG.java | 85 - .../java/org/apache/bcel/generic/DREM.java | 88 - .../java/org/apache/bcel/generic/DRETURN.java | 87 - .../java/org/apache/bcel/generic/DSTORE.java | 92 - .../java/org/apache/bcel/generic/DSUB.java | 88 - .../src/java/org/apache/bcel/generic/DUP.java | 84 - .../java/org/apache/bcel/generic/DUP2.java | 84 - .../java/org/apache/bcel/generic/DUP2_X1.java | 82 - .../java/org/apache/bcel/generic/DUP2_X2.java | 82 - .../java/org/apache/bcel/generic/DUP_X1.java | 82 - .../java/org/apache/bcel/generic/DUP_X2.java | 82 - .../org/apache/bcel/generic/EmptyVisitor.java | 244 -- .../apache/bcel/generic/ExceptionThrower.java | 79 - .../src/java/org/apache/bcel/generic/F2D.java | 87 - .../src/java/org/apache/bcel/generic/F2I.java | 87 - .../src/java/org/apache/bcel/generic/F2L.java | 87 - .../java/org/apache/bcel/generic/FADD.java | 87 - .../java/org/apache/bcel/generic/FALOAD.java | 87 - .../java/org/apache/bcel/generic/FASTORE.java | 87 - .../java/org/apache/bcel/generic/FCMPG.java | 91 - .../java/org/apache/bcel/generic/FCMPL.java | 91 - .../java/org/apache/bcel/generic/FCONST.java | 113 - .../java/org/apache/bcel/generic/FDIV.java | 87 - .../java/org/apache/bcel/generic/FLOAD.java | 92 - .../java/org/apache/bcel/generic/FMUL.java | 87 - .../java/org/apache/bcel/generic/FNEG.java | 85 - .../java/org/apache/bcel/generic/FREM.java | 87 - .../java/org/apache/bcel/generic/FRETURN.java | 87 - .../java/org/apache/bcel/generic/FSTORE.java | 92 - .../java/org/apache/bcel/generic/FSUB.java | 87 - .../org/apache/bcel/generic/FieldGen.java | 310 -- .../bcel/generic/FieldGenOrMethodGen.java | 135 - .../apache/bcel/generic/FieldInstruction.java | 116 - .../apache/bcel/generic/FieldObserver.java | 67 - .../apache/bcel/generic/FieldOrMethod.java | 117 - .../org/apache/bcel/generic/GETFIELD.java | 117 - .../org/apache/bcel/generic/GETSTATIC.java | 113 - .../java/org/apache/bcel/generic/GOTO.java | 122 - .../java/org/apache/bcel/generic/GOTO_W.java | 110 - .../apache/bcel/generic/GotoInstruction.java | 75 - .../src/java/org/apache/bcel/generic/I2B.java | 87 - .../src/java/org/apache/bcel/generic/I2C.java | 87 - .../src/java/org/apache/bcel/generic/I2D.java | 87 - .../src/java/org/apache/bcel/generic/I2F.java | 87 - .../src/java/org/apache/bcel/generic/I2L.java | 87 - .../src/java/org/apache/bcel/generic/I2S.java | 85 - .../java/org/apache/bcel/generic/IADD.java | 87 - .../java/org/apache/bcel/generic/IALOAD.java | 88 - .../java/org/apache/bcel/generic/IAND.java | 85 - .../java/org/apache/bcel/generic/IASTORE.java | 88 - .../java/org/apache/bcel/generic/ICONST.java | 109 - .../java/org/apache/bcel/generic/IDIV.java | 94 - .../java/org/apache/bcel/generic/IFEQ.java | 98 - .../java/org/apache/bcel/generic/IFGE.java | 98 - .../java/org/apache/bcel/generic/IFGT.java | 98 - .../java/org/apache/bcel/generic/IFLE.java | 98 - .../java/org/apache/bcel/generic/IFLT.java | 98 - .../java/org/apache/bcel/generic/IFNE.java | 98 - .../org/apache/bcel/generic/IFNONNULL.java | 97 - .../java/org/apache/bcel/generic/IFNULL.java | 98 - .../org/apache/bcel/generic/IF_ACMPEQ.java | 97 - .../org/apache/bcel/generic/IF_ACMPNE.java | 98 - .../org/apache/bcel/generic/IF_ICMPEQ.java | 98 - .../org/apache/bcel/generic/IF_ICMPGE.java | 98 - .../org/apache/bcel/generic/IF_ICMPGT.java | 98 - .../org/apache/bcel/generic/IF_ICMPLE.java | 98 - .../org/apache/bcel/generic/IF_ICMPLT.java | 98 - .../org/apache/bcel/generic/IF_ICMPNE.java | 98 - .../java/org/apache/bcel/generic/IINC.java | 183 -- .../java/org/apache/bcel/generic/ILOAD.java | 92 - .../java/org/apache/bcel/generic/IMPDEP1.java | 80 - .../java/org/apache/bcel/generic/IMPDEP2.java | 80 - .../java/org/apache/bcel/generic/IMUL.java | 87 - .../java/org/apache/bcel/generic/INEG.java | 85 - .../org/apache/bcel/generic/INSTANCEOF.java | 106 - .../apache/bcel/generic/INVOKEINTERFACE.java | 163 - .../apache/bcel/generic/INVOKESPECIAL.java | 113 - .../org/apache/bcel/generic/INVOKESTATIC.java | 110 - .../apache/bcel/generic/INVOKEVIRTUAL.java | 112 - .../src/java/org/apache/bcel/generic/IOR.java | 85 - .../java/org/apache/bcel/generic/IREM.java | 94 - .../java/org/apache/bcel/generic/IRETURN.java | 87 - .../java/org/apache/bcel/generic/ISHL.java | 85 - .../java/org/apache/bcel/generic/ISHR.java | 85 - .../java/org/apache/bcel/generic/ISTORE.java | 92 - .../java/org/apache/bcel/generic/ISUB.java | 87 - .../java/org/apache/bcel/generic/IUSHR.java | 85 - .../java/org/apache/bcel/generic/IXOR.java | 85 - .../apache/bcel/generic/IfInstruction.java | 82 - .../bcel/generic/IndexedInstruction.java | 68 - .../org/apache/bcel/generic/Instruction.java | 305 -- .../bcel/generic/InstructionComparator.java | 109 - .../bcel/generic/InstructionConstants.java | 326 -- .../bcel/generic/InstructionFactory.java | 623 ---- .../bcel/generic/InstructionHandle.java | 301 -- .../apache/bcel/generic/InstructionList.java | 1287 -------- .../bcel/generic/InstructionListObserver.java | 67 - .../bcel/generic/InstructionTargeter.java | 70 - .../bcel/generic/InvokeInstruction.java | 146 - .../src/java/org/apache/bcel/generic/JSR.java | 119 - .../java/org/apache/bcel/generic/JSR_W.java | 110 - .../apache/bcel/generic/JsrInstruction.java | 115 - .../src/java/org/apache/bcel/generic/L2D.java | 85 - .../src/java/org/apache/bcel/generic/L2F.java | 85 - .../src/java/org/apache/bcel/generic/L2I.java | 85 - .../java/org/apache/bcel/generic/LADD.java | 86 - .../java/org/apache/bcel/generic/LALOAD.java | 87 - .../java/org/apache/bcel/generic/LAND.java | 86 - .../java/org/apache/bcel/generic/LASTORE.java | 87 - .../java/org/apache/bcel/generic/LCMP.java | 92 - .../java/org/apache/bcel/generic/LCONST.java | 111 - .../src/java/org/apache/bcel/generic/LDC.java | 172 -- .../java/org/apache/bcel/generic/LDC2_W.java | 116 - .../java/org/apache/bcel/generic/LDC_W.java | 88 - .../java/org/apache/bcel/generic/LDIV.java | 91 - .../java/org/apache/bcel/generic/LLOAD.java | 89 - .../java/org/apache/bcel/generic/LMUL.java | 86 - .../java/org/apache/bcel/generic/LNEG.java | 85 - .../org/apache/bcel/generic/LOOKUPSWITCH.java | 133 - .../src/java/org/apache/bcel/generic/LOR.java | 85 - .../java/org/apache/bcel/generic/LREM.java | 88 - .../java/org/apache/bcel/generic/LRETURN.java | 85 - .../java/org/apache/bcel/generic/LSHL.java | 85 - .../java/org/apache/bcel/generic/LSHR.java | 85 - .../java/org/apache/bcel/generic/LSTORE.java | 89 - .../java/org/apache/bcel/generic/LSUB.java | 86 - .../java/org/apache/bcel/generic/LUSHR.java | 85 - .../java/org/apache/bcel/generic/LXOR.java | 85 - .../apache/bcel/generic/LineNumberGen.java | 131 - .../org/apache/bcel/generic/LoadClass.java | 86 - .../apache/bcel/generic/LoadInstruction.java | 101 - .../apache/bcel/generic/LocalVariableGen.java | 204 -- .../generic/LocalVariableInstruction.java | 226 -- .../org/apache/bcel/generic/MONITORENTER.java | 88 - .../org/apache/bcel/generic/MONITOREXIT.java | 88 - .../apache/bcel/generic/MULTIANEWARRAY.java | 172 -- .../org/apache/bcel/generic/MethodGen.java | 975 ------ .../apache/bcel/generic/MethodObserver.java | 67 - .../src/java/org/apache/bcel/generic/NEW.java | 111 - .../org/apache/bcel/generic/NEWARRAY.java | 140 - .../src/java/org/apache/bcel/generic/NOP.java | 80 - .../apache/bcel/generic/NamedAndTyped.java | 71 - .../org/apache/bcel/generic/ObjectType.java | 136 - .../src/java/org/apache/bcel/generic/POP.java | 85 - .../java/org/apache/bcel/generic/POP2.java | 85 - .../java/org/apache/bcel/generic/PUSH.java | 196 -- .../org/apache/bcel/generic/PUTFIELD.java | 118 - .../org/apache/bcel/generic/PUTSTATIC.java | 114 - .../apache/bcel/generic/PopInstruction.java | 68 - .../apache/bcel/generic/PushInstruction.java | 73 - .../src/java/org/apache/bcel/generic/RET.java | 161 - .../java/org/apache/bcel/generic/RETURN.java | 85 - .../apache/bcel/generic/ReferenceType.java | 349 --- .../bcel/generic/ReturnInstruction.java | 104 - .../bcel/generic/ReturnaddressType.java | 102 - .../java/org/apache/bcel/generic/SALOAD.java | 85 - .../java/org/apache/bcel/generic/SASTORE.java | 85 - .../java/org/apache/bcel/generic/SIPUSH.java | 128 - .../java/org/apache/bcel/generic/SWAP.java | 84 - .../java/org/apache/bcel/generic/SWITCH.java | 183 -- .../java/org/apache/bcel/generic/Select.java | 254 -- .../apache/bcel/generic/StackConsumer.java | 68 - .../apache/bcel/generic/StackInstruction.java | 83 - .../apache/bcel/generic/StackProducer.java | 69 - .../apache/bcel/generic/StoreInstruction.java | 101 - .../org/apache/bcel/generic/TABLESWITCH.java | 147 - .../bcel/generic/TargetLostException.java | 100 - .../java/org/apache/bcel/generic/Type.java | 306 -- .../apache/bcel/generic/TypedInstruction.java | 67 - .../bcel/generic/UnconditionalBranch.java | 67 - .../generic/VariableLengthInstruction.java | 70 - .../java/org/apache/bcel/generic/Visitor.java | 247 -- .../java/org/apache/bcel/generic/package.html | 16 - .../src/java/org/apache/bcel/package.html | 17 - .../org/apache/bcel/util/AttributeHTML.java | 255 -- .../org/apache/bcel/util/BCELFactory.java | 357 --- .../java/org/apache/bcel/util/BCELifier.java | 304 -- .../org/apache/bcel/util/ByteSequence.java | 82 - .../java/org/apache/bcel/util/Class2HTML.java | 262 -- .../org/apache/bcel/util/ClassLoader.java | 221 -- .../bcel/util/ClassLoaderRepository.java | 155 - .../java/org/apache/bcel/util/ClassPath.java | 372 --- .../java/org/apache/bcel/util/ClassQueue.java | 81 - .../java/org/apache/bcel/util/ClassSet.java | 96 - .../java/org/apache/bcel/util/ClassStack.java | 73 - .../org/apache/bcel/util/ClassVector.java | 79 - .../java/org/apache/bcel/util/CodeHTML.java | 618 ---- .../org/apache/bcel/util/ConstantHTML.java | 262 -- .../apache/bcel/util/InstructionFinder.java | 441 --- .../org/apache/bcel/util/JavaWrapper.java | 152 - .../java/org/apache/bcel/util/MethodHTML.java | 199 -- .../java/org/apache/bcel/util/Repository.java | 105 - .../apache/bcel/util/SyntheticRepository.java | 204 -- .../java/org/apache/bcel/util/package.html | 25 - .../bcel/verifier/GraphicalVerifier.java | 109 - .../apache/bcel/verifier/NativeVerifier.java | 116 - .../apache/bcel/verifier/PassVerifier.java | 143 - .../apache/bcel/verifier/TransitiveHull.java | 138 - .../bcel/verifier/VerificationResult.java | 135 - .../org/apache/bcel/verifier/Verifier.java | 286 -- .../bcel/verifier/VerifierAppFrame.java | 392 --- .../apache/bcel/verifier/VerifierFactory.java | 143 - .../verifier/VerifierFactoryListModel.java | 107 - .../verifier/VerifierFactoryObserver.java | 76 - .../apache/bcel/verifier/VerifyDialog.java | 559 ---- .../exc/AssertionViolatedException.java | 107 - .../exc/ClassConstraintException.java | 79 - .../verifier/exc/CodeConstraintException.java | 77 - .../verifier/exc/InvalidMethodException.java | 69 - .../exc/LinkingConstraintException.java | 74 - .../bcel/verifier/exc/LoadingException.java | 79 - ...ocalVariableInfoInconsistentException.java | 81 - .../exc/StaticCodeConstraintException.java | 71 - ...ticCodeInstructionConstraintException.java | 74 - ...InstructionOperandConstraintException.java | 74 - .../StructuralCodeConstraintException.java | 82 - .../org/apache/bcel/verifier/exc/Utility.java | 76 - .../verifier/exc/VerificationException.java | 82 - .../VerifierConstraintViolatedException.java | 107 - .../org/apache/bcel/verifier/exc/package.html | 24 - .../org/apache/bcel/verifier/package.html | 25 - .../bcel/verifier/statics/DOUBLE_Upper.java | 79 - .../apache/bcel/verifier/statics/IntList.java | 85 - .../bcel/verifier/statics/LONG_Upper.java | 79 - .../verifier/statics/LocalVariableInfo.java | 144 - .../verifier/statics/LocalVariablesInfo.java | 106 - .../bcel/verifier/statics/Pass1Verifier.java | 213 -- .../bcel/verifier/statics/Pass2Verifier.java | 1336 --------- .../bcel/verifier/statics/Pass3aVerifier.java | 1098 ------- .../statics/StringRepresentation.java | 224 -- .../apache/bcel/verifier/statics/package.html | 26 - .../structurals/ControlFlowGraph.java | 466 --- .../structurals/ExceptionHandler.java | 93 - .../structurals/ExceptionHandlers.java | 107 - .../structurals/ExecutionVisitor.java | 1126 ------- .../bcel/verifier/structurals/Frame.java | 153 - .../verifier/structurals/GenericArray.java | 66 - .../structurals/InstConstraintVisitor.java | 2650 ----------------- .../structurals/InstructionContext.java | 141 - .../verifier/structurals/LocalVariables.java | 229 -- .../verifier/structurals/OperandStack.java | 275 -- .../verifier/structurals/Pass3bVerifier.java | 365 --- .../bcel/verifier/structurals/Subroutine.java | 126 - .../verifier/structurals/Subroutines.java | 668 ----- .../structurals/UninitializedObjectType.java | 97 - .../bcel/verifier/structurals/package.html | 27 - external/log4j-1.2.13.jar | Bin 358180 -> 0 bytes .../doc/3rdparty/jinput_license.txt | 32 - .../lwjgl-2.9.1/doc/3rdparty/jogl_license.txt | 152 - .../lwjgl-2.9.1/doc/3rdparty/lzma_license.txt | 15 - .../doc/3rdparty/openal_license.txt | 437 --- external/lwjgl-2.9.1/doc/CREDITS | 38 - external/lwjgl-2.9.1/doc/LICENSE | 31 - external/lwjgl-2.9.1/doc/README | 50 - .../doc/lwjgl_hidden_switches.text | 28 - .../lwjgl-2.9.1/jar/AppleJavaExtensions.jar | Bin 4189 -> 0 bytes external/lwjgl-2.9.1/jar/asm-debug-all.jar | Bin 321450 -> 0 bytes external/lwjgl-2.9.1/jar/jinput.jar | Bin 214859 -> 0 bytes external/lwjgl-2.9.1/jar/lwjgl-debug.jar | Bin 1030793 -> 0 bytes external/lwjgl-2.9.1/jar/lwjgl.jar | Bin 1014790 -> 0 bytes external/lwjgl-2.9.1/jar/lwjgl_test.jar | Bin 283689 -> 0 bytes external/lwjgl-2.9.1/jar/lwjgl_util.jar | Bin 173909 -> 0 bytes .../lwjgl-2.9.1/jar/lwjgl_util_applet.jar | Bin 35975 -> 0 bytes external/lwjgl-2.9.1/jar/lzma.jar | Bin 5848 -> 0 bytes .../native/linux/libjinput-linux.so | Bin 13824 -> 0 bytes .../native/linux/libjinput-linux64.so | Bin 14512 -> 0 bytes external/lwjgl-2.9.1/native/linux/liblwjgl.so | Bin 378724 -> 0 bytes .../lwjgl-2.9.1/native/linux/liblwjgl64.so | Bin 449456 -> 0 bytes .../lwjgl-2.9.1/native/linux/libopenal.so | Bin 368392 -> 0 bytes .../lwjgl-2.9.1/native/linux/libopenal64.so | Bin 404085 -> 0 bytes .../native/macosx/libjinput-osx.jnilib | Bin 64608 -> 0 bytes .../lwjgl-2.9.1/native/macosx/liblwjgl.jnilib | Bin 954384 -> 0 bytes .../lwjgl-2.9.1/native/macosx/openal.dylib | Bin 731648 -> 0 bytes .../lwjgl-2.9.1/native/solaris/liblwjgl.so | Bin 359332 -> 0 bytes .../lwjgl-2.9.1/native/solaris/liblwjgl64.so | Bin 557824 -> 0 bytes .../lwjgl-2.9.1/native/solaris/libopenal.so | Bin 341608 -> 0 bytes .../lwjgl-2.9.1/native/solaris/libopenal64.so | Bin 391368 -> 0 bytes .../lwjgl-2.9.1/native/windows/OpenAL32.dll | Bin 390144 -> 0 bytes .../lwjgl-2.9.1/native/windows/OpenAL64.dll | Bin 382464 -> 0 bytes .../lwjgl-2.9.1/native/windows/jinput-dx8.dll | Bin 61952 -> 0 bytes .../native/windows/jinput-dx8_64.dll | Bin 65024 -> 0 bytes .../lwjgl-2.9.1/native/windows/jinput-raw.dll | Bin 59392 -> 0 bytes .../native/windows/jinput-raw_64.dll | Bin 62464 -> 0 bytes external/lwjgl-2.9.1/native/windows/lwjgl.dll | Bin 298496 -> 0 bytes .../lwjgl-2.9.1/native/windows/lwjgl64.dll | Bin 310272 -> 0 bytes {src/lwjgl => lwjgl}/pom.xml | 0 .../components/hardware/gpu/LWJGLDisplay.java | 0 src/pom.xml => pom.xml | 0 {src/runtime => runtime}/pom.xml | 0 .../org/jpsx/runtime/EmulationException.java | 0 .../jpsx/runtime/FinalComponentSettings.java | 0 .../runtime/FinalResolvedConnectionCache.java | 0 .../java/org/jpsx/runtime/JPSXComponent.java | 0 .../java/org/jpsx/runtime/JPSXMachine.java | 0 .../org/jpsx/runtime/JPSXMachineImpl.java | 0 .../org/jpsx/runtime/RuntimeConnections.java | 0 .../jpsx/runtime/SingletonJPSXComponent.java | 0 .../components/core/AddressSpaceImpl.java | 0 .../core/CoreComponentConnections.java | 0 .../components/core/DMAChannelOwnerBase.java | 0 .../components/core/DMAControllerImpl.java | 0 .../components/core/DefaultQuartz.java | 0 .../components/core/IRQControllerImpl.java | 0 .../runtime/components/core/IRQOwnerBase.java | 0 .../runtime/components/core/MTScheduler.java | 0 .../runtime/components/core/R3000Impl.java | 0 .../jpsx/runtime/components/core/SCPImpl.java | 0 .../emulator/compiler/CodeUnit.java | 0 .../compiler/CompilerClassLoader.java | 0 .../emulator/compiler/Executable.java | 0 .../emulator/compiler/FlowAnalyzer.java | 0 .../emulator/compiler/MultiStageCompiler.java | 0 .../emulator/compiler/Stage1Generator.java | 0 .../emulator/compiler/Stage2Generator.java | 0 .../HardwareComponentConnections.java | 0 .../components/hardware/bios/ImageBIOS.java | 0 .../runtime/components/hardware/cd/CD.java | 0 .../components/hardware/cd/XADecoder.java | 0 .../hardware/counters/Counters.java | 0 .../components/hardware/gpu/AWTDisplay.java | 0 .../hardware/gpu/DefaultDisplayManager.java | 0 .../runtime/components/hardware/gpu/GPU.java | 0 .../components/hardware/gpu/GPUGenerated.java | 0 .../runtime/components/hardware/gte/GTE.java | 0 .../components/hardware/mdec/IDCT.java | 0 .../components/hardware/mdec/MDEC.java | 0 .../hardware/media/CueBinImageDrive.java | 0 .../hardware/r3000/R3000InstructionSet.java | 0 .../hardware/sio/AWTKeyboardController.java | 0 .../components/hardware/sio/BasicPad.java | 0 .../runtime/components/hardware/sio/SIO0.java | 0 .../hardware/sio/StandardController.java | 0 .../components/hardware/spu/NullSPU.java | 0 .../runtime/components/hardware/spu/SPU.java | 0 .../core/DebugAddressSpaceImpl.java | 0 .../emulator/console/Console.java | 0 .../disassemblers/DisassemblerComponent.java | 0 .../GTEInstructionDisassembler.java | 0 .../R3000InstructionDisassembler.java | 0 .../org/jpsx/runtime/util/ByteCodeUtil.java | 0 .../java/org/jpsx/runtime/util/CDUtil.java | 0 .../java/org/jpsx/runtime/util/ClassUtil.java | 0 .../java/org/jpsx/runtime/util/MiscUtil.java | 0 .../java/org/jpsx/runtime/util/Timing.java | 0 495 files changed, 57795 deletions(-) rename {src/api => api}/pom.xml (100%) rename {src/api => api}/src/main/java/org/jpsx/api/CPUControl.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/CPUListener.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/InvalidConfigurationException.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/R3000.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/cpu/SCP.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/dma/DMAController.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/irq/IRQController.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java (100%) rename {src/api => api}/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java (100%) rename {src/bootstrap => bootstrap}/pom.xml (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/connection/Connection.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java (100%) rename {src/bootstrap => bootstrap}/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java (100%) delete mode 100644 build.xml delete mode 100644 external/bcel-5.1/BCEL.iml delete mode 100644 external/bcel-5.1/LICENSE.txt delete mode 100644 external/bcel-5.1/build.xml delete mode 100644 external/bcel-5.1/project.xml delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/Constants.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/ExceptionConstants.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/Repository.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/AccessFlags.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Attribute.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/AttributeReader.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassFormatException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassParser.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Code.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/CodeException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Constant.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantCP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantClass.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantDouble.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFieldref.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFloat.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInteger.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInterfaceMethodref.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantLong.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantMethodref.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantNameAndType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantObject.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantPool.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantString.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantUtf8.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantValue.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Deprecated.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/DescendingVisitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/EmptyVisitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/ExceptionTable.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Field.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/FieldOrMethod.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClass.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClasses.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/JavaClass.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumber.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumberTable.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariable.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariableTable.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Method.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Node.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/PMGClass.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Signature.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/SourceFile.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMap.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapEntry.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Synthetic.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Unknown.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Utility.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/Visitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/classfile/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/AALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/AASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ACONST_NULL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ANEWARRAY.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ARETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ARRAYLENGTH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ATHROW.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/AllocationInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ArithmeticInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ArrayInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ArrayType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BIPUSH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BREAKPOINT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BasicType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BranchHandle.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/BranchInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CHECKCAST.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CPInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ClassGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ClassGenException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ClassObserver.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CodeExceptionGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/CompoundInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ConstantPoolGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ConstantPushInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ConversionInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/D2F.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/D2I.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/D2L.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DADD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DCMPG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DCMPL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DCONST.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DDIV.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DLOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DMUL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DNEG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DREM.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DRETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DSTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DSUB.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP2.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP2_X1.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP2_X2.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP_X1.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/DUP_X2.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/EmptyVisitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ExceptionThrower.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/F2D.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/F2I.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/F2L.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FADD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FCMPG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FCMPL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FCONST.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FDIV.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FLOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FMUL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FNEG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FREM.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FRETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FSTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FSUB.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FieldGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FieldGenOrMethodGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FieldInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FieldObserver.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/FieldOrMethod.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/GETFIELD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/GETSTATIC.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/GOTO.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/GOTO_W.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/GotoInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2B.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2C.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2D.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2F.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2L.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/I2S.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IADD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IAND.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ICONST.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IDIV.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFEQ.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFGE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFGT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFLE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFLT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFNE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFNONNULL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IFNULL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ACMPEQ.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ACMPNE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPEQ.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPGE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPGT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPLE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPLT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IF_ICMPNE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IINC.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ILOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IMPDEP1.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IMPDEP2.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IMUL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INEG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INSTANCEOF.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INVOKEINTERFACE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INVOKESPECIAL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INVOKESTATIC.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/INVOKEVIRTUAL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IOR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IREM.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IRETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ISHL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ISHR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ISTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ISUB.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IUSHR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IXOR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IfInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/IndexedInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/Instruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionComparator.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionConstants.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionFactory.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionHandle.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionList.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionListObserver.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InstructionTargeter.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/InvokeInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/JSR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/JSR_W.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/JsrInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/L2D.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/L2F.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/L2I.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LADD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LAND.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LCMP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LCONST.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LDC.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LDC2_W.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LDC_W.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LDIV.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LLOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LMUL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LNEG.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LOOKUPSWITCH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LOR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LREM.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LRETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LSHL.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LSHR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LSTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LSUB.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LUSHR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LXOR.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LineNumberGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LoadClass.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LoadInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LocalVariableGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/LocalVariableInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/MONITORENTER.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/MONITOREXIT.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/MULTIANEWARRAY.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/MethodGen.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/MethodObserver.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/NEW.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/NEWARRAY.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/NOP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/NamedAndTyped.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ObjectType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/POP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/POP2.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/PUSH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/PUTFIELD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/PUTSTATIC.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/PopInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/PushInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/RET.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/RETURN.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ReferenceType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ReturnInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/ReturnaddressType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/SALOAD.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/SASTORE.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/SIPUSH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/SWAP.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/SWITCH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/Select.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/StackConsumer.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/StackInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/StackProducer.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/StoreInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/TABLESWITCH.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/TargetLostException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/Type.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/TypedInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/UnconditionalBranch.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/VariableLengthInstruction.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/Visitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/generic/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/AttributeHTML.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/BCELFactory.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/BCELifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ByteSequence.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/Class2HTML.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassLoader.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassLoaderRepository.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassPath.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassQueue.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassSet.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassStack.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ClassVector.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/CodeHTML.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/ConstantHTML.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/InstructionFinder.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/JavaWrapper.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/MethodHTML.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/Repository.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/SyntheticRepository.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/util/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/GraphicalVerifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/NativeVerifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/PassVerifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/TransitiveHull.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerificationResult.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/Verifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerifierAppFrame.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerifierFactory.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerifierFactoryListModel.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerifierFactoryObserver.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/VerifyDialog.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/AssertionViolatedException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/ClassConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/CodeConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/InvalidMethodException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/LinkingConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/LoadingException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/LocalVariableInfoInconsistentException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/StaticCodeConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/StaticCodeInstructionConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/StaticCodeInstructionOperandConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/StructuralCodeConstraintException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/Utility.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/VerificationException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/VerifierConstraintViolatedException.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/exc/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/DOUBLE_Upper.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/IntList.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/LONG_Upper.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/LocalVariableInfo.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/LocalVariablesInfo.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/Pass1Verifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/Pass2Verifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/StringRepresentation.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/statics/package.html delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/ControlFlowGraph.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/ExceptionHandler.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/ExceptionHandlers.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/ExecutionVisitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/Frame.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/GenericArray.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/InstructionContext.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/LocalVariables.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/OperandStack.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/Pass3bVerifier.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/Subroutine.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/Subroutines.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/UninitializedObjectType.java delete mode 100644 external/bcel-5.1/src/java/org/apache/bcel/verifier/structurals/package.html delete mode 100644 external/log4j-1.2.13.jar delete mode 100644 external/lwjgl-2.9.1/doc/3rdparty/jinput_license.txt delete mode 100644 external/lwjgl-2.9.1/doc/3rdparty/jogl_license.txt delete mode 100644 external/lwjgl-2.9.1/doc/3rdparty/lzma_license.txt delete mode 100644 external/lwjgl-2.9.1/doc/3rdparty/openal_license.txt delete mode 100644 external/lwjgl-2.9.1/doc/CREDITS delete mode 100644 external/lwjgl-2.9.1/doc/LICENSE delete mode 100644 external/lwjgl-2.9.1/doc/README delete mode 100644 external/lwjgl-2.9.1/doc/lwjgl_hidden_switches.text delete mode 100644 external/lwjgl-2.9.1/jar/AppleJavaExtensions.jar delete mode 100644 external/lwjgl-2.9.1/jar/asm-debug-all.jar delete mode 100644 external/lwjgl-2.9.1/jar/jinput.jar delete mode 100644 external/lwjgl-2.9.1/jar/lwjgl-debug.jar delete mode 100644 external/lwjgl-2.9.1/jar/lwjgl.jar delete mode 100644 external/lwjgl-2.9.1/jar/lwjgl_test.jar delete mode 100644 external/lwjgl-2.9.1/jar/lwjgl_util.jar delete mode 100644 external/lwjgl-2.9.1/jar/lwjgl_util_applet.jar delete mode 100644 external/lwjgl-2.9.1/jar/lzma.jar delete mode 100644 external/lwjgl-2.9.1/native/linux/libjinput-linux.so delete mode 100644 external/lwjgl-2.9.1/native/linux/libjinput-linux64.so delete mode 100644 external/lwjgl-2.9.1/native/linux/liblwjgl.so delete mode 100644 external/lwjgl-2.9.1/native/linux/liblwjgl64.so delete mode 100644 external/lwjgl-2.9.1/native/linux/libopenal.so delete mode 100644 external/lwjgl-2.9.1/native/linux/libopenal64.so delete mode 100644 external/lwjgl-2.9.1/native/macosx/libjinput-osx.jnilib delete mode 100644 external/lwjgl-2.9.1/native/macosx/liblwjgl.jnilib delete mode 100644 external/lwjgl-2.9.1/native/macosx/openal.dylib delete mode 100644 external/lwjgl-2.9.1/native/solaris/liblwjgl.so delete mode 100644 external/lwjgl-2.9.1/native/solaris/liblwjgl64.so delete mode 100644 external/lwjgl-2.9.1/native/solaris/libopenal.so delete mode 100644 external/lwjgl-2.9.1/native/solaris/libopenal64.so delete mode 100644 external/lwjgl-2.9.1/native/windows/OpenAL32.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/OpenAL64.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/jinput-dx8.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/jinput-dx8_64.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/jinput-raw.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/jinput-raw_64.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/lwjgl.dll delete mode 100644 external/lwjgl-2.9.1/native/windows/lwjgl64.dll rename {src/lwjgl => lwjgl}/pom.xml (100%) rename {src/lwjgl => lwjgl}/src/main/java/org/jpsx/runtime/components/hardware/gpu/LWJGLDisplay.java (100%) rename src/pom.xml => pom.xml (100%) rename {src/runtime => runtime}/pom.xml (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/EmulationException.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/FinalComponentSettings.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/FinalResolvedConnectionCache.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/JPSXComponent.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/JPSXMachine.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/JPSXMachineImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/RuntimeConnections.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/SingletonJPSXComponent.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/AddressSpaceImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/CoreComponentConnections.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/DMAChannelOwnerBase.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/DMAControllerImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/DefaultQuartz.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/IRQControllerImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/IRQOwnerBase.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/MTScheduler.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/R3000Impl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/core/SCPImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/CodeUnit.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/CompilerClassLoader.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/Executable.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/FlowAnalyzer.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/MultiStageCompiler.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage1Generator.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/emulator/compiler/Stage2Generator.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/HardwareComponentConnections.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/bios/ImageBIOS.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/cd/CD.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/cd/XADecoder.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/counters/Counters.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/gpu/AWTDisplay.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/gpu/DefaultDisplayManager.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPU.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/gpu/GPUGenerated.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/gte/GTE.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/mdec/IDCT.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/mdec/MDEC.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/media/CueBinImageDrive.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/r3000/R3000InstructionSet.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/sio/AWTKeyboardController.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/sio/BasicPad.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/sio/SIO0.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/sio/StandardController.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/spu/NullSPU.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/components/hardware/spu/SPU.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/debugcomponents/core/DebugAddressSpaceImpl.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/debugcomponents/emulator/console/Console.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/DisassemblerComponent.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/GTEInstructionDisassembler.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/debugcomponents/emulator/disassemblers/R3000InstructionDisassembler.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/util/ByteCodeUtil.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/util/CDUtil.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/util/ClassUtil.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/util/MiscUtil.java (100%) rename {src/runtime => runtime}/src/main/java/org/jpsx/runtime/util/Timing.java (100%) diff --git a/src/api/pom.xml b/api/pom.xml similarity index 100% rename from src/api/pom.xml rename to api/pom.xml diff --git a/src/api/src/main/java/org/jpsx/api/CPUControl.java b/api/src/main/java/org/jpsx/api/CPUControl.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/CPUControl.java rename to api/src/main/java/org/jpsx/api/CPUControl.java diff --git a/src/api/src/main/java/org/jpsx/api/CPUListener.java b/api/src/main/java/org/jpsx/api/CPUListener.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/CPUListener.java rename to api/src/main/java/org/jpsx/api/CPUListener.java diff --git a/src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java b/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/InvalidConfigurationException.java rename to api/src/main/java/org/jpsx/api/InvalidConfigurationException.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java b/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java rename to api/src/main/java/org/jpsx/api/components/core/ContinueExecutionException.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java b/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java rename to api/src/main/java/org/jpsx/api/components/core/ImmediateBreakoutException.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java b/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java rename to api/src/main/java/org/jpsx/api/components/core/ReturnFromExceptionException.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java b/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java rename to api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpace.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java b/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java rename to api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceListener.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java b/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java rename to api/src/main/java/org/jpsx/api/components/core/addressspace/AddressSpaceRegistrar.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java b/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java rename to api/src/main/java/org/jpsx/api/components/core/addressspace/MemoryMapped.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java b/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java rename to api/src/main/java/org/jpsx/api/components/core/addressspace/Pollable.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java b/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstruction.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java b/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/CPUInstructionDisassembler.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java b/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/CompilationContext.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java b/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/InstructionProvider.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java b/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/InstructionRegistrar.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java b/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/NativeCompiler.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java b/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/PollBlockListener.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java b/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/R3000.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java b/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java rename to api/src/main/java/org/jpsx/api/components/core/cpu/SCP.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java b/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java rename to api/src/main/java/org/jpsx/api/components/core/dma/DMAChannelOwner.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java b/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java rename to api/src/main/java/org/jpsx/api/components/core/dma/DMAController.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java b/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java rename to api/src/main/java/org/jpsx/api/components/core/irq/IRQController.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java b/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java rename to api/src/main/java/org/jpsx/api/components/core/irq/IRQOwner.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java b/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java rename to api/src/main/java/org/jpsx/api/components/core/scheduler/Quartz.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java b/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java rename to api/src/main/java/org/jpsx/api/components/core/scheduler/ScheduledAction.java diff --git a/src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java b/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java rename to api/src/main/java/org/jpsx/api/components/core/scheduler/Scheduler.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java b/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java rename to api/src/main/java/org/jpsx/api/components/hardware/cd/CDAudioSink.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java b/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java rename to api/src/main/java/org/jpsx/api/components/hardware/cd/CDDrive.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java b/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java rename to api/src/main/java/org/jpsx/api/components/hardware/cd/CDMedia.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java b/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java rename to api/src/main/java/org/jpsx/api/components/hardware/cd/MediaException.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java b/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java rename to api/src/main/java/org/jpsx/api/components/hardware/gpu/Display.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java b/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java rename to api/src/main/java/org/jpsx/api/components/hardware/gpu/DisplayManager.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java b/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java rename to api/src/main/java/org/jpsx/api/components/hardware/sio/SerialDevice.java diff --git a/src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java b/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java similarity index 100% rename from src/api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java rename to api/src/main/java/org/jpsx/api/components/hardware/sio/SerialPort.java diff --git a/src/bootstrap/pom.xml b/bootstrap/pom.xml similarity index 100% rename from src/bootstrap/pom.xml rename to bootstrap/pom.xml diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java b/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java b/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/JPSXLauncher2.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java b/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/JPSXMachineLifecycle.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java b/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassGenerator.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java b/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/classloader/ClassModifier.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java b/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/classloader/JPSXClassLoader.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java b/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/configuration/ComponentDefinition.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java b/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/configuration/MachineDefinition.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java b/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/configuration/XMLMachineDefinitionParser.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java b/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/connection/Connection.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java b/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/connection/MultipleConnection.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java b/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/connection/SimpleConnection.java diff --git a/src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java b/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java similarity index 100% rename from src/bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java rename to bootstrap/src/main/java/org/jpsx/bootstrap/util/CollectionsFactory.java diff --git a/build.xml b/build.xml deleted file mode 100644 index ad8c73a..0000000 --- a/build.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/external/bcel-5.1/BCEL.iml b/external/bcel-5.1/BCEL.iml deleted file mode 100644 index 50bfe29..0000000 --- a/external/bcel-5.1/BCEL.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/external/bcel-5.1/LICENSE.txt b/external/bcel-5.1/LICENSE.txt deleted file mode 100644 index 66e7119..0000000 --- a/external/bcel-5.1/LICENSE.txt +++ /dev/null @@ -1,53 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ diff --git a/external/bcel-5.1/build.xml b/external/bcel-5.1/build.xml deleted file mode 100644 index 218039c..0000000 --- a/external/bcel-5.1/build.xml +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The Jakarta-Site2 module is not present! Please check - to make sure that you have checked it out from CVS. - - <http://jakarta.apache.org/site/jakarta-site2.html> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-------------------------------------------------------+ - | C R E A T I N G B I N A R Y D I S T R I B U T I O N | - +-------------------------------------------------------+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-------------------------------------------------------+ - | C R E A T I N G S O U R C E D I S T R I B U T I O N | - +-------------------------------------------------------+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/external/bcel-5.1/project.xml b/external/bcel-5.1/project.xml deleted file mode 100644 index 8f02c4d..0000000 --- a/external/bcel-5.1/project.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - 3 - jakarta-bcel - bcel - 5.1 - - Apache Software Foundation - http://www.apache.org - - 2002 - org.apache.bcel - - /images/bcel-logo.gif - - Bytecode Engineering Library - - - Bytecode Engineering Library - - - http://jakarta.apache.org/bcel/ - http://cvs.apache.org/viewcvs/jakarta-bcel/ - jakarta.apache.org - /www/jakarta.apache.org/bcel/ - - - scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-bcel - http://cvs.apache.org/viewcvs/jakarta-bcel/ - - - - - BCEL User List - bcel-user-subscribe@jakarta.apache.org - bcel-user-unsubscribe@jakarta.apache.org - http://www.mail-archive.com/bcel-user@jakarta.apache.org/ - - - BCEL Developer List - bcel-dev-subscribe@jakarta.apache.org - bcel-dev-unsubscribe@jakarta.apache.org - http://www.mail-archive.com/bcel-dev@jakarta.apache.org/ - - - - - - - Markus Dahm - mdahm - m.dahm@gmx.de - it-frameworksolutions - - - - Jason van Zyl - jvanzyl - jason@zenplex.com - Zenplex - - - - - - - regexp - 1.2 - - - - - - src/java - - src/java - - - - exclude = **/*.class - - - - - - - - - - - - - diff --git a/external/bcel-5.1/src/java/org/apache/bcel/Constants.java b/external/bcel-5.1/src/java/org/apache/bcel/Constants.java deleted file mode 100644 index eab92eb..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/Constants.java +++ /dev/null @@ -1,785 +0,0 @@ -package org.apache.bcel; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * Constants for the project, mostly defined in the JVM specification. - * - * @version $Id: Constants.java,v 1.3 2002/06/06 11:30:27 mdahm Exp $ - * @author M. Dahm - */ -public interface Constants { - /** Major and minor version of the code. - */ - public final static short MAJOR_1_1 = 45; - public final static short MINOR_1_1 = 3; - public final static short MAJOR_1_2 = 46; - public final static short MINOR_1_2 = 0; - public final static short MAJOR_1_3 = 47; - public final static short MINOR_1_3 = 0; - public final static short MAJOR = MAJOR_1_1; // Defaults - public final static short MINOR = MINOR_1_1; - - /** Maximum value for an unsigned short. - */ - public final static int MAX_SHORT = 65535; // 2^16 - 1 - - /** Maximum value for an unsigned byte. - */ - public final static int MAX_BYTE = 255; // 2^8 - 1 - - /** Access flags for classes, fields and methods. - */ - public final static short ACC_PUBLIC = 0x0001; - public final static short ACC_PRIVATE = 0x0002; - public final static short ACC_PROTECTED = 0x0004; - public final static short ACC_STATIC = 0x0008; - - public final static short ACC_FINAL = 0x0010; - public final static short ACC_SYNCHRONIZED = 0x0020; - public final static short ACC_VOLATILE = 0x0040; - public final static short ACC_TRANSIENT = 0x0080; - - public final static short ACC_NATIVE = 0x0100; - public final static short ACC_INTERFACE = 0x0200; - public final static short ACC_ABSTRACT = 0x0400; - public final static short ACC_STRICT = 0x0800; - - // Applies to classes compiled by new compilers only - public final static short ACC_SUPER = 0x0020; - - public final static short MAX_ACC_FLAG = ACC_STRICT; - - public final static String[] ACCESS_NAMES = { - "public", "private", "protected", "static", "final", "synchronized", - "volatile", "transient", "native", "interface", "abstract", "strictfp" - }; - - /** Tags in constant pool to denote type of constant. - */ - public final static byte CONSTANT_Utf8 = 1; - public final static byte CONSTANT_Integer = 3; - public final static byte CONSTANT_Float = 4; - public final static byte CONSTANT_Long = 5; - public final static byte CONSTANT_Double = 6; - public final static byte CONSTANT_Class = 7; - public final static byte CONSTANT_Fieldref = 9; - public final static byte CONSTANT_String = 8; - public final static byte CONSTANT_Methodref = 10; - public final static byte CONSTANT_InterfaceMethodref = 11; - public final static byte CONSTANT_NameAndType = 12; - - public final static String[] CONSTANT_NAMES = { - "", "CONSTANT_Utf8", "", "CONSTANT_Integer", - "CONSTANT_Float", "CONSTANT_Long", "CONSTANT_Double", - "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref", - "CONSTANT_Methodref", "CONSTANT_InterfaceMethodref", - "CONSTANT_NameAndType" }; - - /** The name of the static initializer, also called "class - * initialization method" or "interface initialization - * method". This is "<clinit>". - */ - public final static String STATIC_INITIALIZER_NAME = ""; - - /** The name of every constructor method in a class, also called - * "instance initialization method". This is "<init>". - */ - public final static String CONSTRUCTOR_NAME = ""; - - /** The names of the interfaces implemented by arrays */ - public final static String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"}; - - /** - * Limitations of the Java Virtual Machine. - * See The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10. - */ - public static final int MAX_CP_ENTRIES = 65535; - public static final int MAX_CODE_SIZE = 65536; //bytes - - /** Java VM opcodes. - */ - public static final short NOP = 0; - public static final short ACONST_NULL = 1; - public static final short ICONST_M1 = 2; - public static final short ICONST_0 = 3; - public static final short ICONST_1 = 4; - public static final short ICONST_2 = 5; - public static final short ICONST_3 = 6; - public static final short ICONST_4 = 7; - public static final short ICONST_5 = 8; - public static final short LCONST_0 = 9; - public static final short LCONST_1 = 10; - public static final short FCONST_0 = 11; - public static final short FCONST_1 = 12; - public static final short FCONST_2 = 13; - public static final short DCONST_0 = 14; - public static final short DCONST_1 = 15; - public static final short BIPUSH = 16; - public static final short SIPUSH = 17; - public static final short LDC = 18; - public static final short LDC_W = 19; - public static final short LDC2_W = 20; - public static final short ILOAD = 21; - public static final short LLOAD = 22; - public static final short FLOAD = 23; - public static final short DLOAD = 24; - public static final short ALOAD = 25; - public static final short ILOAD_0 = 26; - public static final short ILOAD_1 = 27; - public static final short ILOAD_2 = 28; - public static final short ILOAD_3 = 29; - public static final short LLOAD_0 = 30; - public static final short LLOAD_1 = 31; - public static final short LLOAD_2 = 32; - public static final short LLOAD_3 = 33; - public static final short FLOAD_0 = 34; - public static final short FLOAD_1 = 35; - public static final short FLOAD_2 = 36; - public static final short FLOAD_3 = 37; - public static final short DLOAD_0 = 38; - public static final short DLOAD_1 = 39; - public static final short DLOAD_2 = 40; - public static final short DLOAD_3 = 41; - public static final short ALOAD_0 = 42; - public static final short ALOAD_1 = 43; - public static final short ALOAD_2 = 44; - public static final short ALOAD_3 = 45; - public static final short IALOAD = 46; - public static final short LALOAD = 47; - public static final short FALOAD = 48; - public static final short DALOAD = 49; - public static final short AALOAD = 50; - public static final short BALOAD = 51; - public static final short CALOAD = 52; - public static final short SALOAD = 53; - public static final short ISTORE = 54; - public static final short LSTORE = 55; - public static final short FSTORE = 56; - public static final short DSTORE = 57; - public static final short ASTORE = 58; - public static final short ISTORE_0 = 59; - public static final short ISTORE_1 = 60; - public static final short ISTORE_2 = 61; - public static final short ISTORE_3 = 62; - public static final short LSTORE_0 = 63; - public static final short LSTORE_1 = 64; - public static final short LSTORE_2 = 65; - public static final short LSTORE_3 = 66; - public static final short FSTORE_0 = 67; - public static final short FSTORE_1 = 68; - public static final short FSTORE_2 = 69; - public static final short FSTORE_3 = 70; - public static final short DSTORE_0 = 71; - public static final short DSTORE_1 = 72; - public static final short DSTORE_2 = 73; - public static final short DSTORE_3 = 74; - public static final short ASTORE_0 = 75; - public static final short ASTORE_1 = 76; - public static final short ASTORE_2 = 77; - public static final short ASTORE_3 = 78; - public static final short IASTORE = 79; - public static final short LASTORE = 80; - public static final short FASTORE = 81; - public static final short DASTORE = 82; - public static final short AASTORE = 83; - public static final short BASTORE = 84; - public static final short CASTORE = 85; - public static final short SASTORE = 86; - public static final short POP = 87; - public static final short POP2 = 88; - public static final short DUP = 89; - public static final short DUP_X1 = 90; - public static final short DUP_X2 = 91; - public static final short DUP2 = 92; - public static final short DUP2_X1 = 93; - public static final short DUP2_X2 = 94; - public static final short SWAP = 95; - public static final short IADD = 96; - public static final short LADD = 97; - public static final short FADD = 98; - public static final short DADD = 99; - public static final short ISUB = 100; - public static final short LSUB = 101; - public static final short FSUB = 102; - public static final short DSUB = 103; - public static final short IMUL = 104; - public static final short LMUL = 105; - public static final short FMUL = 106; - public static final short DMUL = 107; - public static final short IDIV = 108; - public static final short LDIV = 109; - public static final short FDIV = 110; - public static final short DDIV = 111; - public static final short IREM = 112; - public static final short LREM = 113; - public static final short FREM = 114; - public static final short DREM = 115; - public static final short INEG = 116; - public static final short LNEG = 117; - public static final short FNEG = 118; - public static final short DNEG = 119; - public static final short ISHL = 120; - public static final short LSHL = 121; - public static final short ISHR = 122; - public static final short LSHR = 123; - public static final short IUSHR = 124; - public static final short LUSHR = 125; - public static final short IAND = 126; - public static final short LAND = 127; - public static final short IOR = 128; - public static final short LOR = 129; - public static final short IXOR = 130; - public static final short LXOR = 131; - public static final short IINC = 132; - public static final short I2L = 133; - public static final short I2F = 134; - public static final short I2D = 135; - public static final short L2I = 136; - public static final short L2F = 137; - public static final short L2D = 138; - public static final short F2I = 139; - public static final short F2L = 140; - public static final short F2D = 141; - public static final short D2I = 142; - public static final short D2L = 143; - public static final short D2F = 144; - public static final short I2B = 145; - public static final short INT2BYTE = 145; // Old notion - public static final short I2C = 146; - public static final short INT2CHAR = 146; // Old notion - public static final short I2S = 147; - public static final short INT2SHORT = 147; // Old notion - public static final short LCMP = 148; - public static final short FCMPL = 149; - public static final short FCMPG = 150; - public static final short DCMPL = 151; - public static final short DCMPG = 152; - public static final short IFEQ = 153; - public static final short IFNE = 154; - public static final short IFLT = 155; - public static final short IFGE = 156; - public static final short IFGT = 157; - public static final short IFLE = 158; - public static final short IF_ICMPEQ = 159; - public static final short IF_ICMPNE = 160; - public static final short IF_ICMPLT = 161; - public static final short IF_ICMPGE = 162; - public static final short IF_ICMPGT = 163; - public static final short IF_ICMPLE = 164; - public static final short IF_ACMPEQ = 165; - public static final short IF_ACMPNE = 166; - public static final short GOTO = 167; - public static final short JSR = 168; - public static final short RET = 169; - public static final short TABLESWITCH = 170; - public static final short LOOKUPSWITCH = 171; - public static final short IRETURN = 172; - public static final short LRETURN = 173; - public static final short FRETURN = 174; - public static final short DRETURN = 175; - public static final short ARETURN = 176; - public static final short RETURN = 177; - public static final short GETSTATIC = 178; - public static final short PUTSTATIC = 179; - public static final short GETFIELD = 180; - public static final short PUTFIELD = 181; - public static final short INVOKEVIRTUAL = 182; - public static final short INVOKESPECIAL = 183; - public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0 - public static final short INVOKESTATIC = 184; - public static final short INVOKEINTERFACE = 185; - public static final short NEW = 187; - public static final short NEWARRAY = 188; - public static final short ANEWARRAY = 189; - public static final short ARRAYLENGTH = 190; - public static final short ATHROW = 191; - public static final short CHECKCAST = 192; - public static final short INSTANCEOF = 193; - public static final short MONITORENTER = 194; - public static final short MONITOREXIT = 195; - public static final short WIDE = 196; - public static final short MULTIANEWARRAY = 197; - public static final short IFNULL = 198; - public static final short IFNONNULL = 199; - public static final short GOTO_W = 200; - public static final short JSR_W = 201; - - /** - * Non-legal opcodes, may be used by JVM internally. - */ - public static final short BREAKPOINT = 202; - public static final short LDC_QUICK = 203; - public static final short LDC_W_QUICK = 204; - public static final short LDC2_W_QUICK = 205; - public static final short GETFIELD_QUICK = 206; - public static final short PUTFIELD_QUICK = 207; - public static final short GETFIELD2_QUICK = 208; - public static final short PUTFIELD2_QUICK = 209; - public static final short GETSTATIC_QUICK = 210; - public static final short PUTSTATIC_QUICK = 211; - public static final short GETSTATIC2_QUICK = 212; - public static final short PUTSTATIC2_QUICK = 213; - public static final short INVOKEVIRTUAL_QUICK = 214; - public static final short INVOKENONVIRTUAL_QUICK = 215; - public static final short INVOKESUPER_QUICK = 216; - public static final short INVOKESTATIC_QUICK = 217; - public static final short INVOKEINTERFACE_QUICK = 218; - public static final short INVOKEVIRTUALOBJECT_QUICK = 219; - public static final short NEW_QUICK = 221; - public static final short ANEWARRAY_QUICK = 222; - public static final short MULTIANEWARRAY_QUICK = 223; - public static final short CHECKCAST_QUICK = 224; - public static final short INSTANCEOF_QUICK = 225; - public static final short INVOKEVIRTUAL_QUICK_W = 226; - public static final short GETFIELD_QUICK_W = 227; - public static final short PUTFIELD_QUICK_W = 228; - public static final short IMPDEP1 = 254; - public static final short IMPDEP2 = 255; - - /** - * For internal purposes only. - */ - public static final short PUSH = 4711; - public static final short SWITCH = 4712; - - /** - * Illegal codes - */ - public static final short UNDEFINED = -1; - public static final short UNPREDICTABLE = -2; - public static final short RESERVED = -3; - public static final String ILLEGAL_OPCODE = ""; - public static final String ILLEGAL_TYPE = ""; - - public static final byte T_BOOLEAN = 4; - public static final byte T_CHAR = 5; - public static final byte T_FLOAT = 6; - public static final byte T_DOUBLE = 7; - public static final byte T_BYTE = 8; - public static final byte T_SHORT = 9; - public static final byte T_INT = 10; - public static final byte T_LONG = 11; - - public static final byte T_VOID = 12; // Non-standard - public static final byte T_ARRAY = 13; - public static final byte T_OBJECT = 14; - public static final byte T_REFERENCE = 14; // Deprecated - public static final byte T_UNKNOWN = 15; - public static final byte T_ADDRESS = 16; - - /** The primitive type names corresponding to the T_XX constants, - * e.g., TYPE_NAMES[T_INT] = "int" - */ - public static final String[] TYPE_NAMES = { - ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, - "boolean", "char", "float", "double", "byte", "short", "int", "long", - "void", "array", "object", "unknown" // Non-standard - }; - - /** The primitive class names corresponding to the T_XX constants, - * e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer" - */ - public static final String[] CLASS_TYPE_NAMES = { - ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, - "java.lang.Boolean", "java.lang.Character", "java.lang.Float", - "java.lang.Double", "java.lang.Byte", "java.lang.Short", - "java.lang.Integer", "java.lang.Long", "java.lang.Void", - ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE - }; - - /** The signature characters corresponding to primitive types, - * e.g., SHORT_TYPE_NAMES[T_INT] = "I" - */ - public static final String[] SHORT_TYPE_NAMES = { - ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, - "Z", "C", "F", "D", "B", "S", "I", "J", - "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE - }; - - /** - * Number of byte code operands, i.e., number of bytes after the tag byte - * itself. - */ - public static final short[] NO_OF_OPERANDS = { - 0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/, - 0/*iconst_1*/, 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/, - 0/*iconst_5*/, 0/*lconst_0*/, 0/*lconst_1*/, 0/*fconst_0*/, - 0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, 0/*dconst_1*/, - 1/*bipush*/, 2/*sipush*/, 1/*ldc*/, 2/*ldc_w*/, 2/*ldc2_w*/, - 1/*iload*/, 1/*lload*/, 1/*fload*/, 1/*dload*/, 1/*aload*/, - 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, 0/*iload_3*/, - 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, - 0/*fload_0*/, 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, - 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, 0/*dload_3*/, - 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, - 0/*iaload*/, 0/*laload*/, 0/*faload*/, 0/*daload*/, - 0/*aaload*/, 0/*baload*/, 0/*caload*/, 0/*saload*/, - 1/*istore*/, 1/*lstore*/, 1/*fstore*/, 1/*dstore*/, - 1/*astore*/, 0/*istore_0*/, 0/*istore_1*/, 0/*istore_2*/, - 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, 0/*lstore_2*/, - 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/, - 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, - 0/*dstore_3*/, 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, - 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, 0/*fastore*/, - 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, - 0/*sastore*/, 0/*pop*/, 0/*pop2*/, 0/*dup*/, 0/*dup_x1*/, - 0/*dup_x2*/, 0/*dup2*/, 0/*dup2_x1*/, 0/*dup2_x2*/, 0/*swap*/, - 0/*iadd*/, 0/*ladd*/, 0/*fadd*/, 0/*dadd*/, 0/*isub*/, - 0/*lsub*/, 0/*fsub*/, 0/*dsub*/, 0/*imul*/, 0/*lmul*/, - 0/*fmul*/, 0/*dmul*/, 0/*idiv*/, 0/*ldiv*/, 0/*fdiv*/, - 0/*ddiv*/, 0/*irem*/, 0/*lrem*/, 0/*frem*/, 0/*drem*/, - 0/*ineg*/, 0/*lneg*/, 0/*fneg*/, 0/*dneg*/, 0/*ishl*/, - 0/*lshl*/, 0/*ishr*/, 0/*lshr*/, 0/*iushr*/, 0/*lushr*/, - 0/*iand*/, 0/*land*/, 0/*ior*/, 0/*lor*/, 0/*ixor*/, 0/*lxor*/, - 2/*iinc*/, 0/*i2l*/, 0/*i2f*/, 0/*i2d*/, 0/*l2i*/, 0/*l2f*/, - 0/*l2d*/, 0/*f2i*/, 0/*f2l*/, 0/*f2d*/, 0/*d2i*/, 0/*d2l*/, - 0/*d2f*/, 0/*i2b*/, 0/*i2c*/, 0/*i2s*/, 0/*lcmp*/, 0/*fcmpl*/, - 0/*fcmpg*/, 0/*dcmpl*/, 0/*dcmpg*/, 2/*ifeq*/, 2/*ifne*/, - 2/*iflt*/, 2/*ifge*/, 2/*ifgt*/, 2/*ifle*/, 2/*if_icmpeq*/, - 2/*if_icmpne*/, 2/*if_icmplt*/, 2/*if_icmpge*/, 2/*if_icmpgt*/, - 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, 2/*goto*/, - 2/*jsr*/, 1/*ret*/, UNPREDICTABLE/*tableswitch*/, UNPREDICTABLE/*lookupswitch*/, - 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/, - 0/*dreturn*/, 0/*areturn*/, 0/*return*/, - 2/*getstatic*/, 2/*putstatic*/, 2/*getfield*/, - 2/*putfield*/, 2/*invokevirtual*/, 2/*invokespecial*/, 2/*invokestatic*/, - 4/*invokeinterface*/, UNDEFINED, 2/*new*/, - 1/*newarray*/, 2/*anewarray*/, - 0/*arraylength*/, 0/*athrow*/, 2/*checkcast*/, - 2/*instanceof*/, 0/*monitorenter*/, - 0/*monitorexit*/, UNPREDICTABLE/*wide*/, 3/*multianewarray*/, - 2/*ifnull*/, 2/*ifnonnull*/, 4/*goto_w*/, - 4/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, RESERVED/*impdep1*/, RESERVED/*impdep2*/ - }; - - /** - * How the byte code operands are to be interpreted. - */ - public static final short[][] TYPE_OF_OPERANDS = { - {}/*nop*/, {}/*aconst_null*/, {}/*iconst_m1*/, {}/*iconst_0*/, - {}/*iconst_1*/, {}/*iconst_2*/, {}/*iconst_3*/, {}/*iconst_4*/, - {}/*iconst_5*/, {}/*lconst_0*/, {}/*lconst_1*/, {}/*fconst_0*/, - {}/*fconst_1*/, {}/*fconst_2*/, {}/*dconst_0*/, {}/*dconst_1*/, - {T_BYTE}/*bipush*/, {T_SHORT}/*sipush*/, {T_BYTE}/*ldc*/, - {T_SHORT}/*ldc_w*/, {T_SHORT}/*ldc2_w*/, - {T_BYTE}/*iload*/, {T_BYTE}/*lload*/, {T_BYTE}/*fload*/, - {T_BYTE}/*dload*/, {T_BYTE}/*aload*/, {}/*iload_0*/, - {}/*iload_1*/, {}/*iload_2*/, {}/*iload_3*/, {}/*lload_0*/, - {}/*lload_1*/, {}/*lload_2*/, {}/*lload_3*/, {}/*fload_0*/, - {}/*fload_1*/, {}/*fload_2*/, {}/*fload_3*/, {}/*dload_0*/, - {}/*dload_1*/, {}/*dload_2*/, {}/*dload_3*/, {}/*aload_0*/, - {}/*aload_1*/, {}/*aload_2*/, {}/*aload_3*/, {}/*iaload*/, - {}/*laload*/, {}/*faload*/, {}/*daload*/, {}/*aaload*/, - {}/*baload*/, {}/*caload*/, {}/*saload*/, {T_BYTE}/*istore*/, - {T_BYTE}/*lstore*/, {T_BYTE}/*fstore*/, {T_BYTE}/*dstore*/, - {T_BYTE}/*astore*/, {}/*istore_0*/, {}/*istore_1*/, - {}/*istore_2*/, {}/*istore_3*/, {}/*lstore_0*/, {}/*lstore_1*/, - {}/*lstore_2*/, {}/*lstore_3*/, {}/*fstore_0*/, {}/*fstore_1*/, - {}/*fstore_2*/, {}/*fstore_3*/, {}/*dstore_0*/, {}/*dstore_1*/, - {}/*dstore_2*/, {}/*dstore_3*/, {}/*astore_0*/, {}/*astore_1*/, - {}/*astore_2*/, {}/*astore_3*/, {}/*iastore*/, {}/*lastore*/, - {}/*fastore*/, {}/*dastore*/, {}/*aastore*/, {}/*bastore*/, - {}/*castore*/, {}/*sastore*/, {}/*pop*/, {}/*pop2*/, {}/*dup*/, - {}/*dup_x1*/, {}/*dup_x2*/, {}/*dup2*/, {}/*dup2_x1*/, - {}/*dup2_x2*/, {}/*swap*/, {}/*iadd*/, {}/*ladd*/, {}/*fadd*/, - {}/*dadd*/, {}/*isub*/, {}/*lsub*/, {}/*fsub*/, {}/*dsub*/, - {}/*imul*/, {}/*lmul*/, {}/*fmul*/, {}/*dmul*/, {}/*idiv*/, - {}/*ldiv*/, {}/*fdiv*/, {}/*ddiv*/, {}/*irem*/, {}/*lrem*/, - {}/*frem*/, {}/*drem*/, {}/*ineg*/, {}/*lneg*/, {}/*fneg*/, - {}/*dneg*/, {}/*ishl*/, {}/*lshl*/, {}/*ishr*/, {}/*lshr*/, - {}/*iushr*/, {}/*lushr*/, {}/*iand*/, {}/*land*/, {}/*ior*/, - {}/*lor*/, {}/*ixor*/, {}/*lxor*/, {T_BYTE, T_BYTE}/*iinc*/, - {}/*i2l*/, {}/*i2f*/, {}/*i2d*/, {}/*l2i*/, {}/*l2f*/, {}/*l2d*/, - {}/*f2i*/, {}/*f2l*/, {}/*f2d*/, {}/*d2i*/, {}/*d2l*/, {}/*d2f*/, - {}/*i2b*/, {}/*i2c*/,{}/*i2s*/, {}/*lcmp*/, {}/*fcmpl*/, - {}/*fcmpg*/, {}/*dcmpl*/, {}/*dcmpg*/, {T_SHORT}/*ifeq*/, - {T_SHORT}/*ifne*/, {T_SHORT}/*iflt*/, {T_SHORT}/*ifge*/, - {T_SHORT}/*ifgt*/, {T_SHORT}/*ifle*/, {T_SHORT}/*if_icmpeq*/, - {T_SHORT}/*if_icmpne*/, {T_SHORT}/*if_icmplt*/, - {T_SHORT}/*if_icmpge*/, {T_SHORT}/*if_icmpgt*/, - {T_SHORT}/*if_icmple*/, {T_SHORT}/*if_acmpeq*/, - {T_SHORT}/*if_acmpne*/, {T_SHORT}/*goto*/, {T_SHORT}/*jsr*/, - {T_BYTE}/*ret*/, {}/*tableswitch*/, {}/*lookupswitch*/, - {}/*ireturn*/, {}/*lreturn*/, {}/*freturn*/, {}/*dreturn*/, - {}/*areturn*/, {}/*return*/, {T_SHORT}/*getstatic*/, - {T_SHORT}/*putstatic*/, {T_SHORT}/*getfield*/, - {T_SHORT}/*putfield*/, {T_SHORT}/*invokevirtual*/, - {T_SHORT}/*invokespecial*/, {T_SHORT}/*invokestatic*/, - {T_SHORT, T_BYTE, T_BYTE}/*invokeinterface*/, {}, - {T_SHORT}/*new*/, {T_BYTE}/*newarray*/, - {T_SHORT}/*anewarray*/, {}/*arraylength*/, {}/*athrow*/, - {T_SHORT}/*checkcast*/, {T_SHORT}/*instanceof*/, - {}/*monitorenter*/, {}/*monitorexit*/, {T_BYTE}/*wide*/, - {T_SHORT, T_BYTE}/*multianewarray*/, {T_SHORT}/*ifnull*/, - {T_SHORT}/*ifnonnull*/, {T_INT}/*goto_w*/, {T_INT}/*jsr_w*/, - {}/*breakpoint*/, {}, {}, {}, {}, {}, {}, {}, - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, - {}/*impdep1*/, {}/*impdep2*/ - }; - - /** - * Names of opcodes. - */ - public static final String[] OPCODE_NAMES = { - "nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1", - "iconst_2", "iconst_3", "iconst_4", "iconst_5", "lconst_0", - "lconst_1", "fconst_0", "fconst_1", "fconst_2", "dconst_0", - "dconst_1", "bipush", "sipush", "ldc", "ldc_w", "ldc2_w", "iload", - "lload", "fload", "dload", "aload", "iload_0", "iload_1", "iload_2", - "iload_3", "lload_0", "lload_1", "lload_2", "lload_3", "fload_0", - "fload_1", "fload_2", "fload_3", "dload_0", "dload_1", "dload_2", - "dload_3", "aload_0", "aload_1", "aload_2", "aload_3", "iaload", - "laload", "faload", "daload", "aaload", "baload", "caload", "saload", - "istore", "lstore", "fstore", "dstore", "astore", "istore_0", - "istore_1", "istore_2", "istore_3", "lstore_0", "lstore_1", - "lstore_2", "lstore_3", "fstore_0", "fstore_1", "fstore_2", - "fstore_3", "dstore_0", "dstore_1", "dstore_2", "dstore_3", - "astore_0", "astore_1", "astore_2", "astore_3", "iastore", "lastore", - "fastore", "dastore", "aastore", "bastore", "castore", "sastore", - "pop", "pop2", "dup", "dup_x1", "dup_x2", "dup2", "dup2_x1", - "dup2_x2", "swap", "iadd", "ladd", "fadd", "dadd", "isub", "lsub", - "fsub", "dsub", "imul", "lmul", "fmul", "dmul", "idiv", "ldiv", - "fdiv", "ddiv", "irem", "lrem", "frem", "drem", "ineg", "lneg", - "fneg", "dneg", "ishl", "lshl", "ishr", "lshr", "iushr", "lushr", - "iand", "land", "ior", "lor", "ixor", "lxor", "iinc", "i2l", "i2f", - "i2d", "l2i", "l2f", "l2d", "f2i", "f2l", "f2d", "d2i", "d2l", "d2f", - "i2b", "i2c", "i2s", "lcmp", "fcmpl", "fcmpg", - "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge", "ifgt", "ifle", - "if_icmpeq", "if_icmpne", "if_icmplt", "if_icmpge", "if_icmpgt", - "if_icmple", "if_acmpeq", "if_acmpne", "goto", "jsr", "ret", - "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn", - "dreturn", "areturn", "return", "getstatic", "putstatic", "getfield", - "putfield", "invokevirtual", "invokespecial", "invokestatic", - "invokeinterface", ILLEGAL_OPCODE, "new", "newarray", "anewarray", - "arraylength", "athrow", "checkcast", "instanceof", "monitorenter", - "monitorexit", "wide", "multianewarray", "ifnull", "ifnonnull", - "goto_w", "jsr_w", "breakpoint", ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, - ILLEGAL_OPCODE, "impdep1", "impdep2" - }; - - /** - * Number of words consumed on operand stack by instructions. - */ - public static final int[] CONSUME_STACK = { - 0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/, 0/*iconst_1*/, - 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/, 0/*iconst_5*/, 0/*lconst_0*/, - 0/*lconst_1*/, 0/*fconst_0*/, 0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, - 0/*dconst_1*/, 0/*bipush*/, 0/*sipush*/, 0/*ldc*/, 0/*ldc_w*/, 0/*ldc2_w*/, 0/*iload*/, - 0/*lload*/, 0/*fload*/, 0/*dload*/, 0/*aload*/, 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, - 0/*iload_3*/, 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, 0/*fload_0*/, - 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, - 0/*dload_3*/, 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, 2/*iaload*/, - 2/*laload*/, 2/*faload*/, 2/*daload*/, 2/*aaload*/, 2/*baload*/, 2/*caload*/, 2/*saload*/, - 1/*istore*/, 2/*lstore*/, 1/*fstore*/, 2/*dstore*/, 1/*astore*/, 1/*istore_0*/, - 1/*istore_1*/, 1/*istore_2*/, 1/*istore_3*/, 2/*lstore_0*/, 2/*lstore_1*/, - 2/*lstore_2*/, 2/*lstore_3*/, 1/*fstore_0*/, 1/*fstore_1*/, 1/*fstore_2*/, - 1/*fstore_3*/, 2/*dstore_0*/, 2/*dstore_1*/, 2/*dstore_2*/, 2/*dstore_3*/, - 1/*astore_0*/, 1/*astore_1*/, 1/*astore_2*/, 1/*astore_3*/, 3/*iastore*/, 4/*lastore*/, - 3/*fastore*/, 4/*dastore*/, 3/*aastore*/, 3/*bastore*/, 3/*castore*/, 3/*sastore*/, - 1/*pop*/, 2/*pop2*/, 1/*dup*/, 2/*dup_x1*/, 3/*dup_x2*/, 2/*dup2*/, 3/*dup2_x1*/, - 4/*dup2_x2*/, 2/*swap*/, 2/*iadd*/, 4/*ladd*/, 2/*fadd*/, 4/*dadd*/, 2/*isub*/, 4/*lsub*/, - 2/*fsub*/, 4/*dsub*/, 2/*imul*/, 4/*lmul*/, 2/*fmul*/, 4/*dmul*/, 2/*idiv*/, 4/*ldiv*/, - 2/*fdiv*/, 4/*ddiv*/, 2/*irem*/, 4/*lrem*/, 2/*frem*/, 4/*drem*/, 1/*ineg*/, 2/*lneg*/, - 1/*fneg*/, 2/*dneg*/, 2/*ishl*/, 3/*lshl*/, 2/*ishr*/, 3/*lshr*/, 2/*iushr*/, 3/*lushr*/, - 2/*iand*/, 4/*land*/, 2/*ior*/, 4/*lor*/, 2/*ixor*/, 4/*lxor*/, 0/*iinc*/, - 1/*i2l*/, 1/*i2f*/, 1/*i2d*/, 2/*l2i*/, 2/*l2f*/, 2/*l2d*/, 1/*f2i*/, 1/*f2l*/, - 1/*f2d*/, 2/*d2i*/, 2/*d2l*/, 2/*d2f*/, 1/*i2b*/, 1/*i2c*/, 1/*i2s*/, - 4/*lcmp*/, 2/*fcmpl*/, 2/*fcmpg*/, 4/*dcmpl*/, 4/*dcmpg*/, 1/*ifeq*/, 1/*ifne*/, - 1/*iflt*/, 1/*ifge*/, 1/*ifgt*/, 1/*ifle*/, 2/*if_icmpeq*/, 2/*if_icmpne*/, 2/*if_icmplt*/, - 2 /*if_icmpge*/, 2/*if_icmpgt*/, 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, - 0/*goto*/, 0/*jsr*/, 0/*ret*/, 1/*tableswitch*/, 1/*lookupswitch*/, 1/*ireturn*/, - 2/*lreturn*/, 1/*freturn*/, 2/*dreturn*/, 1/*areturn*/, 0/*return*/, 0/*getstatic*/, - UNPREDICTABLE/*putstatic*/, 1/*getfield*/, UNPREDICTABLE/*putfield*/, - UNPREDICTABLE/*invokevirtual*/, UNPREDICTABLE/*invokespecial*/, - UNPREDICTABLE/*invokestatic*/, - UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 0/*new*/, 1/*newarray*/, 1/*anewarray*/, - 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 1/*monitorenter*/, - 1/*monitorexit*/, 0/*wide*/, UNPREDICTABLE/*multianewarray*/, 1/*ifnull*/, 1/*ifnonnull*/, - 0/*goto_w*/, 0/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/ - }; - - /** - * Number of words produced onto operand stack by instructions. - */ - public static final int[] PRODUCE_STACK = { - 0/*nop*/, 1/*aconst_null*/, 1/*iconst_m1*/, 1/*iconst_0*/, 1/*iconst_1*/, - 1/*iconst_2*/, 1/*iconst_3*/, 1/*iconst_4*/, 1/*iconst_5*/, 2/*lconst_0*/, - 2/*lconst_1*/, 1/*fconst_0*/, 1/*fconst_1*/, 1/*fconst_2*/, 2/*dconst_0*/, - 2/*dconst_1*/, 1/*bipush*/, 1/*sipush*/, 1/*ldc*/, 1/*ldc_w*/, 2/*ldc2_w*/, 1/*iload*/, - 2/*lload*/, 1/*fload*/, 2/*dload*/, 1/*aload*/, 1/*iload_0*/, 1/*iload_1*/, 1/*iload_2*/, - 1/*iload_3*/, 2/*lload_0*/, 2/*lload_1*/, 2/*lload_2*/, 2/*lload_3*/, 1/*fload_0*/, - 1/*fload_1*/, 1/*fload_2*/, 1/*fload_3*/, 2/*dload_0*/, 2/*dload_1*/, 2/*dload_2*/, - 2/*dload_3*/, 1/*aload_0*/, 1/*aload_1*/, 1/*aload_2*/, 1/*aload_3*/, 1/*iaload*/, - 2/*laload*/, 1/*faload*/, 2/*daload*/, 1/*aaload*/, 1/*baload*/, 1/*caload*/, 1/*saload*/, - 0/*istore*/, 0/*lstore*/, 0/*fstore*/, 0/*dstore*/, 0/*astore*/, 0/*istore_0*/, - 0/*istore_1*/, 0/*istore_2*/, 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, - 0/*lstore_2*/, 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/, - 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, 0/*dstore_3*/, - 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, - 0/*fastore*/, 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, 0/*sastore*/, - 0/*pop*/, 0/*pop2*/, 2/*dup*/, 3/*dup_x1*/, 4/*dup_x2*/, 4/*dup2*/, 5/*dup2_x1*/, - 6/*dup2_x2*/, 2/*swap*/, 1/*iadd*/, 2/*ladd*/, 1/*fadd*/, 2/*dadd*/, 1/*isub*/, 2/*lsub*/, - 1/*fsub*/, 2/*dsub*/, 1/*imul*/, 2/*lmul*/, 1/*fmul*/, 2/*dmul*/, 1/*idiv*/, 2/*ldiv*/, - 1/*fdiv*/, 2/*ddiv*/, 1/*irem*/, 2/*lrem*/, 1/*frem*/, 2/*drem*/, 1/*ineg*/, 2/*lneg*/, - 1/*fneg*/, 2/*dneg*/, 1/*ishl*/, 2/*lshl*/, 1/*ishr*/, 2/*lshr*/, 1/*iushr*/, 2/*lushr*/, - 1/*iand*/, 2/*land*/, 1/*ior*/, 2/*lor*/, 1/*ixor*/, 2/*lxor*/, - 0/*iinc*/, 2/*i2l*/, 1/*i2f*/, 2/*i2d*/, 1/*l2i*/, 1/*l2f*/, 2/*l2d*/, 1/*f2i*/, - 2/*f2l*/, 2/*f2d*/, 1/*d2i*/, 2/*d2l*/, 1/*d2f*/, - 1/*i2b*/, 1/*i2c*/, 1/*i2s*/, 1/*lcmp*/, 1/*fcmpl*/, 1/*fcmpg*/, - 1/*dcmpl*/, 1/*dcmpg*/, 0/*ifeq*/, 0/*ifne*/, 0/*iflt*/, 0/*ifge*/, 0/*ifgt*/, 0/*ifle*/, - 0/*if_icmpeq*/, 0/*if_icmpne*/, 0/*if_icmplt*/, 0/*if_icmpge*/, 0/*if_icmpgt*/, - 0/*if_icmple*/, 0/*if_acmpeq*/, 0/*if_acmpne*/, 0/*goto*/, 1/*jsr*/, 0/*ret*/, - 0/*tableswitch*/, 0/*lookupswitch*/, 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/, - 0/*dreturn*/, 0/*areturn*/, 0/*return*/, UNPREDICTABLE/*getstatic*/, 0/*putstatic*/, - UNPREDICTABLE/*getfield*/, 0/*putfield*/, UNPREDICTABLE/*invokevirtual*/, - UNPREDICTABLE/*invokespecial*/, UNPREDICTABLE/*invokestatic*/, - UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 1/*new*/, 1/*newarray*/, 1/*anewarray*/, - 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 0/*monitorenter*/, - 0/*monitorexit*/, 0/*wide*/, 1/*multianewarray*/, 0/*ifnull*/, 0/*ifnonnull*/, - 0/*goto_w*/, 1/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, - UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/ - }; - - /** Attributes and their corresponding names. - */ - public static final byte ATTR_UNKNOWN = -1; - public static final byte ATTR_SOURCE_FILE = 0; - public static final byte ATTR_CONSTANT_VALUE = 1; - public static final byte ATTR_CODE = 2; - public static final byte ATTR_EXCEPTIONS = 3; - public static final byte ATTR_LINE_NUMBER_TABLE = 4; - public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; - public static final byte ATTR_INNER_CLASSES = 6; - public static final byte ATTR_SYNTHETIC = 7; - public static final byte ATTR_DEPRECATED = 8; - public static final byte ATTR_PMG = 9; - public static final byte ATTR_SIGNATURE = 10; - public static final byte ATTR_STACK_MAP = 11; - - public static final short KNOWN_ATTRIBUTES = 12; - - public static final String[] ATTRIBUTE_NAMES = { - "SourceFile", "ConstantValue", "Code", "Exceptions", - "LineNumberTable", "LocalVariableTable", - "InnerClasses", "Synthetic", "Deprecated", - "PMGClass", "Signature", "StackMap" - }; - - /** Constants used in the StackMap attribute. - */ - public static final byte ITEM_Bogus = 0; - public static final byte ITEM_Integer = 1; - public static final byte ITEM_Float = 2; - public static final byte ITEM_Double = 3; - public static final byte ITEM_Long = 4; - public static final byte ITEM_Null = 5; - public static final byte ITEM_InitObject = 6; - public static final byte ITEM_Object = 7; - public static final byte ITEM_NewObject = 8; - - public static final String[] ITEM_NAMES = { - "Bogus", "Integer", "Float", "Double", "Long", - "Null", "InitObject", "Object", "NewObject" - }; -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/ExceptionConstants.java b/external/bcel-5.1/src/java/org/apache/bcel/ExceptionConstants.java deleted file mode 100644 index af4d6ab..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/ExceptionConstants.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.apache.bcel; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * Exception constants. - * - * @version $Id: ExceptionConstants.java,v 1.1.1.1 2001/10/29 19:59:56 jvanzyl Exp $ - * @author E. Haase - */ -public interface ExceptionConstants { - /** The mother of all exceptions - */ - public static final Class THROWABLE = Throwable.class; - - /** Super class of any run-time exception - */ - public static final Class RUNTIME_EXCEPTION = RuntimeException.class; - - /** Super class of any linking exception (aka Linkage Error) - */ - public static final Class LINKING_EXCEPTION = LinkageError.class; - - /** Linking Exceptions - */ - public static final Class CLASS_CIRCULARITY_ERROR = ClassCircularityError.class; - public static final Class CLASS_FORMAT_ERROR = ClassFormatError.class; - public static final Class EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class; - public static final Class INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class; - public static final Class ABSTRACT_METHOD_ERROR = AbstractMethodError.class; - public static final Class ILLEGAL_ACCESS_ERROR = IllegalAccessError.class; - public static final Class INSTANTIATION_ERROR = InstantiationError.class; - public static final Class NO_SUCH_FIELD_ERROR = NoSuchFieldError.class; - public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class; - public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class; - public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class; - public static final Class VERIFY_ERROR = VerifyError.class; - - /* UnsupportedClassVersionError is new in JDK 1.2 */ - //public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class; - - /** Run-Time Exceptions - */ - public static final Class NULL_POINTER_EXCEPTION = NullPointerException.class; - public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class; - public static final Class ARITHMETIC_EXCEPTION = ArithmeticException.class; - public static final Class NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class; - public static final Class CLASS_CAST_EXCEPTION = ClassCastException.class; - public static final Class ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class; - - /** Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual - * Machine Specification - */ - public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = { - NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR, - EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR - }; // Chapter 5.1 - - public static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = { - NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR - }; // Chapter 5.2 - - public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below) - public static final Class[] EXCS_STRING_RESOLUTION = new Class[0]; - // Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.) - - public static final Class[] EXCS_ARRAY_EXCEPTION = { - NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION - }; - -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/Repository.java b/external/bcel-5.1/src/java/org/apache/bcel/Repository.java deleted file mode 100644 index 0b6e67c..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/Repository.java +++ /dev/null @@ -1,248 +0,0 @@ -package org.apache.bcel; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.util.*; -import java.io.*; - -/** - * The repository maintains informations about class interdependencies, e.g., - * whether a class is a sub-class of another. Delegates actual class loading - * to SyntheticRepository with current class path by default. - * - * @see org.apache.bcel.util.Repository - * @see org.apache.bcel.util.SyntheticRepository - * - * @version $Id: Repository.java,v 1.11 2002/10/11 20:34:47 mdahm Exp $ - * @author M. Dahm - */ -public abstract class Repository { - private static org.apache.bcel.util.Repository _repository = - SyntheticRepository.getInstance(); - - /** @return currently used repository instance - */ - public static org.apache.bcel.util.Repository getRepository() { - return _repository; - } - - /** Set repository instance to be used for class loading - */ - public static void setRepository(org.apache.bcel.util.Repository rep) { - _repository = rep; - } - - /** Lookup class somewhere found on your CLASSPATH, or whereever the - * repository instance looks for it. - * - * @return class object for given fully qualified class name, or null - * if the class could not be found or parsed correctly - */ - public static JavaClass lookupClass(String class_name) { - try { - JavaClass clazz = _repository.findClass(class_name); - - if(clazz == null) { - return _repository.loadClass(class_name); - } else { - return clazz; - } - } catch(ClassNotFoundException ex) { return null; } - } - - /** - * Try to find class source via getResourceAsStream(). - * @see Class - * @return JavaClass object for given runtime class - */ - public static JavaClass lookupClass(Class clazz) { - try { - return _repository.loadClass(clazz); - } catch(ClassNotFoundException ex) { return null; } - } - - /** @return class file object for given Java class. - */ - public static ClassPath.ClassFile lookupClassFile(String class_name) { - try { - return ClassPath.SYSTEM_CLASS_PATH.getClassFile(class_name); - } catch(IOException e) { return null; } - } - - /** Clear the repository. - */ - public static void clearCache() { - _repository.clear(); - } - - /** - * Add clazz to repository if there isn't an equally named class already in there. - * - * @return old entry in repository - */ - public static JavaClass addClass(JavaClass clazz) { - JavaClass old = _repository.findClass(clazz.getClassName()); - _repository.storeClass(clazz); - return old; - } - - /** - * Remove class with given (fully qualified) name from repository. - */ - public static void removeClass(String clazz) { - _repository.removeClass(_repository.findClass(clazz)); - } - - /** - * Remove given class from repository. - */ - public static void removeClass(JavaClass clazz) { - _repository.removeClass(clazz); - } - - /** - * @return list of super classes of clazz in ascending order, i.e., - * Object is always the last element - */ - public static JavaClass[] getSuperClasses(JavaClass clazz) { - return clazz.getSuperClasses(); - } - - /** - * @return list of super classes of clazz in ascending order, i.e., - * Object is always the last element. return "null", if class - * cannot be found. - */ - public static JavaClass[] getSuperClasses(String class_name) { - JavaClass jc = lookupClass(class_name); - return (jc == null? null : getSuperClasses(jc)); - } - - /** - * @return all interfaces implemented by class and its super - * classes and the interfaces that those interfaces extend, and so on. - * (Some people call this a transitive hull). - */ - public static JavaClass[] getInterfaces(JavaClass clazz) { - return clazz.getAllInterfaces(); - } - - /** - * @return all interfaces implemented by class and its super - * classes and the interfaces that extend those interfaces, and so on - */ - public static JavaClass[] getInterfaces(String class_name) { - return getInterfaces(lookupClass(class_name)); - } - - /** - * Equivalent to runtime "instanceof" operator. - * @return true, if clazz is an instance of super_class - */ - public static boolean instanceOf(JavaClass clazz, JavaClass super_class) { - return clazz.instanceOf(super_class); - } - - /** - * @return true, if clazz is an instance of super_class - */ - public static boolean instanceOf(String clazz, String super_class) { - return instanceOf(lookupClass(clazz), lookupClass(super_class)); - } - - /** - * @return true, if clazz is an instance of super_class - */ - public static boolean instanceOf(JavaClass clazz, String super_class) { - return instanceOf(clazz, lookupClass(super_class)); - } - - /** - * @return true, if clazz is an instance of super_class - */ - public static boolean instanceOf(String clazz, JavaClass super_class) { - return instanceOf(lookupClass(clazz), super_class); - } - - /** - * @return true, if clazz is an implementation of interface inter - */ - public static boolean implementationOf(JavaClass clazz, JavaClass inter) { - return clazz.implementationOf(inter); - } - - /** - * @return true, if clazz is an implementation of interface inter - */ - public static boolean implementationOf(String clazz, String inter) { - return implementationOf(lookupClass(clazz), lookupClass(inter)); - } - - /** - * @return true, if clazz is an implementation of interface inter - */ - public static boolean implementationOf(JavaClass clazz, String inter) { - return implementationOf(clazz, lookupClass(inter)); - } - - /** - * @return true, if clazz is an implementation of interface inter - */ - public static boolean implementationOf(String clazz, JavaClass inter) { - return implementationOf(lookupClass(clazz), inter); - } -} - diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/AccessFlags.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/AccessFlags.java deleted file mode 100644 index 56530b8..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/AccessFlags.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; - -/** - * Super class for all objects that have modifiers like private, final, ... - * I.e. classes, fields, and methods. - * - * @version $Id: AccessFlags.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - */ -public abstract class AccessFlags implements java.io.Serializable { - protected int access_flags; - - public AccessFlags() {} - - /** - * @param a inital access flags - */ - public AccessFlags(int a) { - access_flags = a; - } - - /** - * @return Access flags of the object aka. "modifiers". - */ - public final int getAccessFlags() { return access_flags; } - - /** - * @return Access flags of the object aka. "modifiers". - */ - public final int getModifiers() { return access_flags; } - - /** Set access flags aka "modifiers". - * @param access_flags Access flags of the object. - */ - public final void setAccessFlags(int access_flags) { - this.access_flags = access_flags; - } - - /** Set access flags aka "modifiers". - * @param access_flags Access flags of the object. - */ - public final void setModifiers(int access_flags) { - setAccessFlags(access_flags); - } - - private final void setFlag(int flag, boolean set) { - if((access_flags & flag) != 0) { // Flag is set already - if(!set) // Delete flag ? - access_flags ^= flag; - } else { // Flag not set - if(set) // Set flag ? - access_flags |= flag; - } - } - - public final void isPublic(boolean flag) { setFlag(Constants.ACC_PUBLIC, flag); } - public final boolean isPublic() { - return (access_flags & Constants.ACC_PUBLIC) != 0; - } - - public final void isPrivate(boolean flag) { setFlag(Constants.ACC_PRIVATE, flag); } - public final boolean isPrivate() { - return (access_flags & Constants.ACC_PRIVATE) != 0; - } - - public final void isProtected(boolean flag) { setFlag(Constants.ACC_PROTECTED, flag); } - public final boolean isProtected() { - return (access_flags & Constants.ACC_PROTECTED) != 0; - } - - public final void isStatic(boolean flag) { setFlag(Constants.ACC_STATIC, flag); } - public final boolean isStatic() { - return (access_flags & Constants.ACC_STATIC) != 0; - } - - public final void isFinal(boolean flag) { setFlag(Constants.ACC_FINAL, flag); } - public final boolean isFinal() { - return (access_flags & Constants.ACC_FINAL) != 0; - } - - public final void isSynchronized(boolean flag) { setFlag(Constants.ACC_SYNCHRONIZED, flag); } - public final boolean isSynchronized() { - return (access_flags & Constants.ACC_SYNCHRONIZED) != 0; - } - - public final void isVolatile(boolean flag) { setFlag(Constants.ACC_VOLATILE, flag); } - public final boolean isVolatile() { - return (access_flags & Constants.ACC_VOLATILE) != 0; - } - - public final void isTransient(boolean flag) { setFlag(Constants.ACC_TRANSIENT, flag); } - public final boolean isTransient() { - return (access_flags & Constants.ACC_TRANSIENT) != 0; - } - - public final void isNative(boolean flag) { setFlag(Constants.ACC_NATIVE, flag); } - public final boolean isNative() { - return (access_flags & Constants.ACC_NATIVE) != 0; - } - - public final void isInterface(boolean flag) { setFlag(Constants.ACC_INTERFACE, flag); } - public final boolean isInterface() { - return (access_flags & Constants.ACC_INTERFACE) != 0; - } - - public final void isAbstract(boolean flag) { setFlag(Constants.ACC_ABSTRACT, flag); } - public final boolean isAbstract() { - return (access_flags & Constants.ACC_ABSTRACT) != 0; - } - - public final void isStrictfp(boolean flag) { setFlag(Constants.ACC_STRICT, flag); } - public final boolean isStrictfp() { - return (access_flags & Constants.ACC_STRICT) != 0; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Attribute.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Attribute.java deleted file mode 100644 index 0551dab..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Attribute.java +++ /dev/null @@ -1,302 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; -import java.util.HashMap; - -/** - * Abstract super class for Attribute objects. Currently the - * ConstantValue, SourceFile, Code, - * Exceptiontable, LineNumberTable, - * LocalVariableTable, InnerClasses and - * Synthetic attributes are supported. The - * Unknown attribute stands for non-standard-attributes. - * - * @version $Id: Attribute.java,v 1.8 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - * @see ConstantValue - * @see SourceFile - * @see Code - * @see Unknown - * @see ExceptionTable - * @see LineNumberTable - * @see LocalVariableTable - * @see InnerClasses - * @see Synthetic - * @see Deprecated - * @see Signature -*/ -public abstract class Attribute implements Cloneable, Node, Serializable { - protected int name_index; // Points to attribute name in constant pool - protected int length; // Content length of attribute field - protected byte tag; // Tag to distiguish subclasses - protected ConstantPool constant_pool; - - protected Attribute(byte tag, int name_index, int length, - ConstantPool constant_pool) { - this.tag = tag; - this.name_index = name_index; - this.length = length; - this.constant_pool = constant_pool; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public abstract void accept(Visitor v); - - /** - * Dump attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public void dump(DataOutputStream file) throws IOException - { - file.writeShort(name_index); - file.writeInt(length); - } - - private static HashMap readers = new HashMap(); - - /** Add an Attribute reader capable of parsing (user-defined) attributes - * named "name". You should not add readers for the standard attributes - * such as "LineNumberTable", because those are handled internally. - * - * @param name the name of the attribute as stored in the class file - * @param r the reader object - */ - public static void addAttributeReader(String name, AttributeReader r) { - readers.put(name, r); - } - - /** Remove attribute reader - * - * @param name the name of the attribute as stored in the class file - */ - public static void removeAttributeReader(String name) { - readers.remove(name); - } - - /* Class method reads one attribute from the input data stream. - * This method must not be accessible from the outside. It is - * called by the Field and Method constructor methods. - * - * @see Field - * @see Method - * @param file Input stream - * @param constant_pool Array of constants - * @return Attribute - * @throws IOException - * @throws ClassFormatException - */ - public static final Attribute readAttribute(DataInputStream file, - ConstantPool constant_pool) - throws IOException, ClassFormatException - { - ConstantUtf8 c; - String name; - int name_index; - int length; - byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute - - // Get class name from constant pool via `name_index' indirection - name_index = (int)file.readUnsignedShort(); - c = (ConstantUtf8)constant_pool.getConstant(name_index, - Constants.CONSTANT_Utf8); - name = c.getBytes(); - - // Length of data in bytes - length = file.readInt(); - - // Compare strings to find known attribute - for(byte i=0; i < Constants.KNOWN_ATTRIBUTES; i++) { - if(name.equals(Constants.ATTRIBUTE_NAMES[i])) { - tag = i; // found! - break; - } - } - - // Call proper constructor, depending on `tag' - switch(tag) { - case Constants.ATTR_UNKNOWN: - AttributeReader r = (AttributeReader)readers.get(name); - - if(r != null) - return r.createAttribute(name_index, length, file, constant_pool); - else - return new Unknown(name_index, length, file, constant_pool); - - case Constants.ATTR_CONSTANT_VALUE: - return new ConstantValue(name_index, length, file, constant_pool); - - case Constants.ATTR_SOURCE_FILE: - return new SourceFile(name_index, length, file, constant_pool); - - case Constants.ATTR_CODE: - return new Code(name_index, length, file, constant_pool); - - case Constants.ATTR_EXCEPTIONS: - return new ExceptionTable(name_index, length, file, constant_pool); - - case Constants.ATTR_LINE_NUMBER_TABLE: - return new LineNumberTable(name_index, length, file, constant_pool); - - case Constants.ATTR_LOCAL_VARIABLE_TABLE: - return new LocalVariableTable(name_index, length, file, constant_pool); - - case Constants.ATTR_INNER_CLASSES: - return new InnerClasses(name_index, length, file, constant_pool); - - case Constants.ATTR_SYNTHETIC: - return new Synthetic(name_index, length, file, constant_pool); - - case Constants.ATTR_DEPRECATED: - return new Deprecated(name_index, length, file, constant_pool); - - case Constants.ATTR_PMG: - return new PMGClass(name_index, length, file, constant_pool); - - case Constants.ATTR_SIGNATURE: - return new Signature(name_index, length, file, constant_pool); - - case Constants.ATTR_STACK_MAP: - return new StackMap(name_index, length, file, constant_pool); - - default: // Never reached - throw new IllegalStateException("Ooops! default case reached."); - } - } - - /** - * @return Length of attribute field in bytes. - */ - public final int getLength() { return length; } - - /** - * @param Attribute length in bytes. - */ - public final void setLength(int length) { - this.length = length; - } - - /** - * @param name_index of attribute. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } - - /** - * @return Name index in constant pool of attribute name. - */ - public final int getNameIndex() { return name_index; } - - /** - * @return Tag of attribute, i.e., its type. Value may not be altered, thus - * there is no setTag() method. - */ - public final byte getTag() { return tag; } - - /** - * @return Constant pool used by this object. - * @see ConstantPool - */ - public final ConstantPool getConstantPool() { return constant_pool; } - - /** - * @param constant_pool Constant pool to be used for this object. - * @see ConstantPool - */ - public final void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } - - /** - * Use copy() if you want to have a deep copy(), i.e., with all references - * copied correctly. - * - * @return shallow copy of this attribute - */ - public Object clone() { - Object o = null; - - try { - o = super.clone(); - } catch(CloneNotSupportedException e) { - e.printStackTrace(); // Never occurs - } - - return o; - } - - /** - * @return deep copy of this attribute - */ - public abstract Attribute copy(ConstantPool constant_pool); - - /** - * @return attribute name. - */ - public String toString() { - return Constants.ATTRIBUTE_NAMES[tag]; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/AttributeReader.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/AttributeReader.java deleted file mode 100644 index 68cc8f9..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/AttributeReader.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * Unknown (non-standard) attributes may be read via user-defined factory - * objects that can be registered with the Attribute.addAttributeReader - * method. These factory objects should implement this interface. - - * @see Attribute - * @version $Id: AttributeReader.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - */ -public interface AttributeReader { - /** - When this attribute reader is added via the static method - Attribute.addAttributeReader, an attribute name is associated with it. - As the class file parser parses attributes, it will call various - AttributeReaders based on the name of the attributes it is - constructing. - - @param name_index An index into the constant pool, indexing a - ConstantUtf8 that represents the name of the attribute. - - @param length The length of the data contained in the attribute. This - is written into the constant pool and should agree with what the - factory expects the length to be. - - @param file This is the data input stream that the factory needs to read - its data from. - - @param constant_pool This is the constant pool associated with the - Attribute that we are constructing. - - @return The user-defined AttributeReader should take this data and use - it to construct an attribute. In the case of errors, a null can be - returned which will cause the parsing of the class file to fail. - - @see Attribute#addAttributeReader( String, AttributeReader ) - */ - public Attribute createAttribute(int name_index, - int length, - java.io.DataInputStream file, - ConstantPool constant_pool); -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassFormatException.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassFormatException.java deleted file mode 100644 index a57fdbc..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassFormatException.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * Thrown when the BCEL attempts to read a class file and determines - * that the file is malformed or otherwise cannot be interpreted as a - * class file. - * - * @version $Id: ClassFormatException.java,v 1.1 2002/04/24 11:01:30 mdahm Exp $ - * @author M. Dahm - */ -public class ClassFormatException extends RuntimeException { - public ClassFormatException() { super(); } - public ClassFormatException(String s) { super(s); } -} - diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassParser.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassParser.java deleted file mode 100644 index 1bc9d81..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ClassParser.java +++ /dev/null @@ -1,328 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; -import java.util.zip.*; - -/** - * Wrapper class that parses a given Java .class file. The method parse returns a - * JavaClass object on success. When an I/O error or an - * inconsistency occurs an appropiate exception is propagated back to - * the caller. - * - * The structure and the names comply, except for a few conveniences, - * exactly with the - * JVM specification 1.0. See this paper for - * further details about the structure of a bytecode file. - * - * @version $Id: ClassParser.java,v 1.5 2002/08/09 13:09:31 mdahm Exp $ - * @author M. Dahm - */ -public final class ClassParser { - private DataInputStream file; - private ZipFile zip; - private String file_name; - private int class_name_index, superclass_name_index; - private int major, minor; // Compiler version - private int access_flags; // Access rights of parsed class - private int[] interfaces; // Names of implemented interfaces - private ConstantPool constant_pool; // collection of constants - private Field[] fields; // class fields, i.e., its variables - private Method[] methods; // methods defined in the class - private Attribute[] attributes; // attributes defined in the class - private boolean is_zip; // Loaded from zip file - - private static final int BUFSIZE = 8192; - - /** - * Parse class from the given stream. - * - * @param file Input stream - * @param file_name File name - */ - public ClassParser(InputStream file, String file_name) { - this.file_name = file_name; - - String clazz = file.getClass().getName(); // Not a very clean solution ... - is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar."); - - if(file instanceof DataInputStream) // Is already a data stream - this.file = (DataInputStream)file; - else - this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE)); - } - - /** Parse class from given .class file. - * - * @param file_name file name - * @throws IOException - */ - public ClassParser(String file_name) throws IOException - { - is_zip = false; - this.file_name = file_name; - file = new DataInputStream(new BufferedInputStream - (new FileInputStream(file_name), BUFSIZE)); - } - - /** Parse class from given .class file in a ZIP-archive - * - * @param file_name file name - * @throws IOException - */ - public ClassParser(String zip_file, String file_name) throws IOException - { - is_zip = true; - zip = new ZipFile(zip_file); - ZipEntry entry = zip.getEntry(file_name); - - this.file_name = file_name; - - file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), - BUFSIZE)); - } - - /** - * Parse the given Java class file and return an object that represents - * the contained data, i.e., constants, methods, fields and commands. - * A ClassFormatException is raised, if the file is not a valid - * .class file. (This does not include verification of the byte code as it - * is performed by the java interpreter). - * - * @return Class object representing the parsed class file - * @throws IOException - * @throws ClassFormatException - */ - public JavaClass parse() throws IOException, ClassFormatException - { - /****************** Read headers ********************************/ - // Check magic tag of class file - readID(); - - // Get compiler version - readVersion(); - - /****************** Read constant pool and related **************/ - // Read constant pool entries - readConstantPool(); - - // Get class information - readClassInfo(); - - // Get interface information, i.e., implemented interfaces - readInterfaces(); - - /****************** Read class fields and methods ***************/ - // Read class fields, i.e., the variables of the class - readFields(); - - // Read class methods, i.e., the functions in the class - readMethods(); - - // Read class attributes - readAttributes(); - - // Check for unknown variables - //Unknown[] u = Unknown.getUnknownAttributes(); - //for(int i=0; i < u.length; i++) - // System.err.println("WARNING: " + u[i]); - - // Everything should have been read now - // if(file.available() > 0) { - // int bytes = file.available(); - // byte[] buf = new byte[bytes]; - // file.read(buf); - - // if(!(is_zip && (buf.length == 1))) { - // System.err.println("WARNING: Trailing garbage at end of " + file_name); - // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); - // } - // } - - // Read everything of interest, so close the file - file.close(); - if(zip != null) - zip.close(); - - // Return the information we have gathered in a new object - return new JavaClass(class_name_index, superclass_name_index, - file_name, major, minor, access_flags, - constant_pool, interfaces, fields, - methods, attributes, is_zip? JavaClass.ZIP : JavaClass.FILE); - } - - /** - * Read information about the attributes of the class. - * @throws IOException - * @throws ClassFormatException - */ - private final void readAttributes() throws IOException, ClassFormatException - { - int attributes_count; - - attributes_count = file.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - - for(int i=0; i < attributes_count; i++) - attributes[i] = Attribute.readAttribute(file, constant_pool); - } - - /** - * Read information about the class and its super class. - * @throws IOException - * @throws ClassFormatException - */ - private final void readClassInfo() throws IOException, ClassFormatException - { - access_flags = file.readUnsignedShort(); - - /* Interfaces are implicitely abstract, the flag should be set - * according to the JVM specification. - */ - if((access_flags & Constants.ACC_INTERFACE) != 0) - access_flags |= Constants.ACC_ABSTRACT; - - if(((access_flags & Constants.ACC_ABSTRACT) != 0) && - ((access_flags & Constants.ACC_FINAL) != 0 )) - throw new ClassFormatException("Class can't be both final and abstract"); - - class_name_index = file.readUnsignedShort(); - superclass_name_index = file.readUnsignedShort(); - } - /** - * Read constant pool entries. - * @throws IOException - * @throws ClassFormatException - */ - private final void readConstantPool() throws IOException, ClassFormatException - { - constant_pool = new ConstantPool(file); - } - - /** - * Read information about the fields of the class, i.e., its variables. - * @throws IOException - * @throws ClassFormatException - */ - private final void readFields() throws IOException, ClassFormatException - { - int fields_count; - - fields_count = file.readUnsignedShort(); - fields = new Field[fields_count]; - - for(int i=0; i < fields_count; i++) - fields[i] = new Field(file, constant_pool); - } - - /******************** Private utility methods **********************/ - - /** - * Check whether the header of the file is ok. - * Of course, this has to be the first action on successive file reads. - * @throws IOException - * @throws ClassFormatException - */ - private final void readID() throws IOException, ClassFormatException - { - int magic = 0xCAFEBABE; - - if(file.readInt() != magic) - throw new ClassFormatException(file_name + " is not a Java .class file"); - } - /** - * Read information about the interfaces implemented by this class. - * @throws IOException - * @throws ClassFormatException - */ - private final void readInterfaces() throws IOException, ClassFormatException - { - int interfaces_count; - - interfaces_count = file.readUnsignedShort(); - interfaces = new int[interfaces_count]; - - for(int i=0; i < interfaces_count; i++) - interfaces[i] = file.readUnsignedShort(); - } - /** - * Read information about the methods of the class. - * @throws IOException - * @throws ClassFormatException - */ - private final void readMethods() throws IOException, ClassFormatException - { - int methods_count; - - methods_count = file.readUnsignedShort(); - methods = new Method[methods_count]; - - for(int i=0; i < methods_count; i++) - methods[i] = new Method(file, constant_pool); - } - /** - * Read major and minor version of compiler which created the file. - * @throws IOException - * @throws ClassFormatException - */ - private final void readVersion() throws IOException, ClassFormatException - { - minor = file.readUnsignedShort(); - major = file.readUnsignedShort(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Code.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Code.java deleted file mode 100644 index 6eeea6e..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Code.java +++ /dev/null @@ -1,373 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a chunk of Java byte code contained in a - * method. It is instantiated by the - * Attribute.readAttribute() method. A Code - * attribute contains informations about operand stack, local - * variables, byte code and the exceptions handled within this - * method. - * - * This attribute has attributes itself, namely LineNumberTable which - * is used for debugging purposes and LocalVariableTable which - * contains information about the local variables. - * - * @version $Id: Code.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - * @see CodeException - * @see LineNumberTable - * @see LocalVariableTable - */ -public final class Code extends Attribute { - private int max_stack; // Maximum size of stack used by this method - private int max_locals; // Number of local variables - private int code_length; // Length of code in bytes - private byte[] code; // Actual byte code - - private int exception_table_length; - private CodeException[] exception_table; // Table of handled exceptions - private int attributes_count; // Attributes of code: LineNumber - private Attribute[] attributes; // or LocalVariable - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public Code(Code c) { - this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), - c.getCode(), c.getExceptionTable(), c.getAttributes(), - c.getConstantPool()); - } - - /** - * @param name_index Index pointing to the name Code - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - */ - Code(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - // Initialize with some default values which will be overwritten later - this(name_index, length, - file.readUnsignedShort(), file.readUnsignedShort(), - (byte[])null, (CodeException[])null, (Attribute[])null, - constant_pool); - - code_length = file.readInt(); - code = new byte[code_length]; // Read byte code - file.readFully(code); - - /* Read exception table that contains all regions where an exception - * handler is active, i.e., a try { ... } catch() block. - */ - exception_table_length = file.readUnsignedShort(); - exception_table = new CodeException[exception_table_length]; - - for(int i=0; i < exception_table_length; i++) - exception_table[i] = new CodeException(file); - - /* Read all attributes, currently `LineNumberTable' and - * `LocalVariableTable' - */ - attributes_count = file.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - for(int i=0; i < attributes_count; i++) - attributes[i] = Attribute.readAttribute(file, constant_pool); - - /* Adjust length, because of setAttributes in this(), s.b. length - * is incorrect, because it didn't take the internal attributes - * into account yet! Very subtle bug, fixed in 3.1.1. - */ - this.length = length; - } - - /** - * @param name_index Index pointing to the name Code - * @param length Content length in bytes - * @param max_stack Maximum size of stack - * @param max_locals Number of local variables - * @param code Actual byte code - * @param exception_table Table of handled exceptions - * @param attributes Attributes of code: LineNumber or LocalVariable - * @param constant_pool Array of constants - */ - public Code(int name_index, int length, - int max_stack, int max_locals, - byte[] code, - CodeException[] exception_table, - Attribute[] attributes, - ConstantPool constant_pool) - { - super(Constants.ATTR_CODE, name_index, length, constant_pool); - - this.max_stack = max_stack; - this.max_locals = max_locals; - - setCode(code); - setExceptionTable(exception_table); - setAttributes(attributes); // Overwrites length! - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitCode(this); - } - - /** - * Dump code attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - - file.writeShort(max_stack); - file.writeShort(max_locals); - file.writeInt(code_length); - file.write(code, 0, code_length); - - file.writeShort(exception_table_length); - for(int i=0; i < exception_table_length; i++) - exception_table[i].dump(file); - - file.writeShort(attributes_count); - for(int i=0; i < attributes_count; i++) - attributes[i].dump(file); - } - - /** - * @return Collection of code attributes. - * @see Attribute - */ - public final Attribute[] getAttributes() { return attributes; } - - /** - * @return LineNumberTable of Code, if it has one - */ - public LineNumberTable getLineNumberTable() { - for(int i=0; i < attributes_count; i++) - if(attributes[i] instanceof LineNumberTable) - return (LineNumberTable)attributes[i]; - - return null; - } - - /** - * @return LocalVariableTable of Code, if it has one - */ - public LocalVariableTable getLocalVariableTable() { - for(int i=0; i < attributes_count; i++) - if(attributes[i] instanceof LocalVariableTable) - return (LocalVariableTable)attributes[i]; - - return null; - } - - /** - * @return Actual byte code of the method. - */ - public final byte[] getCode() { return code; } - - /** - * @return Table of handled exceptions. - * @see CodeException - */ - public final CodeException[] getExceptionTable() { return exception_table; } - - /** - * @return Number of local variables. - */ - public final int getMaxLocals() { return max_locals; } - - /** - * @return Maximum size of stack used by this method. - */ - - public final int getMaxStack() { return max_stack; } - - /** - * @return the internal length of this code attribute (minus the first 6 bytes) - * and excluding all its attributes - */ - private final int getInternalLength() { - return 2 /*max_stack*/ + 2 /*max_locals*/ + 4 /*code length*/ - + code_length /*byte-code*/ - + 2 /*exception-table length*/ - + 8 * exception_table_length /* exception table */ - + 2 /* attributes count */; - } - - /** - * @return the full size of this code attribute, minus its first 6 bytes, - * including the size of all its contained attributes - */ - private final int calculateLength() { - int len = 0; - - for(int i=0; i < attributes_count; i++) - len += attributes[i].length + 6 /*attribute header size*/; - - return len + getInternalLength(); - } - - /** - * @param attributes. - */ - public final void setAttributes(Attribute[] attributes) { - this.attributes = attributes; - attributes_count = (attributes == null)? 0 : attributes.length; - length = calculateLength(); // Adjust length - } - - /** - * @param code byte code - */ - public final void setCode(byte[] code) { - this.code = code; - code_length = (code == null)? 0 : code.length; - } - - /** - * @param exception_table exception table - */ - public final void setExceptionTable(CodeException[] exception_table) { - this.exception_table = exception_table; - exception_table_length = (exception_table == null)? 0 : - exception_table.length; - } - - /** - * @param max_locals maximum number of local variables - */ - public final void setMaxLocals(int max_locals) { - this.max_locals = max_locals; - } - - /** - * @param max_stack maximum stack size - */ - public final void setMaxStack(int max_stack) { - this.max_stack = max_stack; - } - - /** - * @return String representation of code chunk. - */ - public final String toString(boolean verbose) { - StringBuffer buf; - - buf = new StringBuffer("Code(max_stack = " + max_stack + - ", max_locals = " + max_locals + - ", code_length = " + code_length + ")\n" + - Utility.codeToString(code, constant_pool, 0, -1, verbose)); - - if(exception_table_length > 0) { - buf.append("\nException handler(s) = \n" + "From\tTo\tHandler\tType\n"); - - for(int i=0; i < exception_table_length; i++) - buf.append(exception_table[i].toString(constant_pool, verbose) + "\n"); - } - - if(attributes_count > 0) { - buf.append("\nAttribute(s) = \n"); - - for(int i=0; i < attributes_count; i++) - buf.append(attributes[i].toString() + "\n"); - } - - return buf.toString(); - } - - /** - * @return String representation of code chunk. - */ - public final String toString() { - return toString(true); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - Code c = (Code)clone(); - c.code = (byte[])code.clone(); - c.constant_pool = constant_pool; - - c.exception_table = new CodeException[exception_table_length]; - for(int i=0; i < exception_table_length; i++) - c.exception_table[i] = exception_table[i].copy(); - - c.attributes = new Attribute[attributes_count]; - for(int i=0; i < attributes_count; i++) - c.attributes[i] = attributes[i].copy(constant_pool); - - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/CodeException.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/CodeException.java deleted file mode 100644 index e41210a..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/CodeException.java +++ /dev/null @@ -1,229 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents an entry in the exception table of the Code - * attribute and is used only there. It contains a range in which a - * particular exception handler is active. - * - * @version $Id: CodeException.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - * @see Code - */ -public final class CodeException - implements Cloneable, Constants, Node, Serializable -{ - private int start_pc; // Range in the code the exception handler is - private int end_pc; // active. start_pc is inclusive, end_pc exclusive - private int handler_pc; /* Starting address of exception handler, i.e., - * an offset from start of code. - */ - private int catch_type; /* If this is zero the handler catches any - * exception, otherwise it points to the - * exception class which is to be caught. - */ - /** - * Initialize from another object. - */ - public CodeException(CodeException c) { - this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - CodeException(DataInputStream file) throws IOException - { - this(file.readUnsignedShort(), file.readUnsignedShort(), - file.readUnsignedShort(), file.readUnsignedShort()); - } - - /** - * @param start_pc Range in the code the exception handler is active, - * start_pc is inclusive while - * @param end_pc is exclusive - * @param handler_pc Starting address of exception handler, i.e., - * an offset from start of code. - * @param catch_type If zero the handler catches any - * exception, otherwise it points to the exception class which is - * to be caught. - */ - public CodeException(int start_pc, int end_pc, int handler_pc, - int catch_type) - { - this.start_pc = start_pc; - this.end_pc = end_pc; - this.handler_pc = handler_pc; - this.catch_type = catch_type; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitCodeException(this); - } - /** - * Dump code exception to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(start_pc); - file.writeShort(end_pc); - file.writeShort(handler_pc); - file.writeShort(catch_type); - } - - /** - * @return 0, if the handler catches any exception, otherwise it points to - * the exception class which is to be caught. - */ - public final int getCatchType() { return catch_type; } - - /** - * @return Exclusive end index of the region where the handler is active. - */ - public final int getEndPC() { return end_pc; } - - /** - * @return Starting address of exception handler, relative to the code. - */ - public final int getHandlerPC() { return handler_pc; } - - /** - * @return Inclusive start index of the region where the handler is active. - */ - public final int getStartPC() { return start_pc; } - - /** - * @param catch_type. - */ - public final void setCatchType(int catch_type) { - this.catch_type = catch_type; - } - - /** - * @param end_pc end of handled block - */ - public final void setEndPC(int end_pc) { - this.end_pc = end_pc; - } - - /** - * @param handler_pc where the actual code is - */ - public final void setHandlerPC(int handler_pc) { - this.handler_pc = handler_pc; - } - - /** - * @param start_pc start of handled block - */ - public final void setStartPC(int start_pc) { - this.start_pc = start_pc; - } - - /** - * @return String representation. - */ - public final String toString() { - return "CodeException(start_pc = " + start_pc + - ", end_pc = " + end_pc + - ", handler_pc = " + handler_pc + ", catch_type = " + catch_type + ")"; - } - - /** - * @return String representation. - */ - public final String toString(ConstantPool cp, boolean verbose) { - String str; - - if(catch_type == 0) - str = "(0)"; - else - str = Utility.compactClassName(cp.getConstantString(catch_type, CONSTANT_Class), false) + - (verbose? "(" + catch_type + ")" : ""); - - return start_pc + "\t" + end_pc + "\t" + handler_pc + "\t" + str; - } - - public final String toString(ConstantPool cp) { - return toString(cp, true); - } - - /** - * @return deep copy of this object - */ - public CodeException copy() { - try { - return (CodeException)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Constant.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Constant.java deleted file mode 100644 index e920d65..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Constant.java +++ /dev/null @@ -1,148 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * Abstract superclass for classes to represent the different constant types - * in the constant pool of a class file. The classes keep closely to - * the JVM specification. - * - * @version $Id: Constant.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - */ -public abstract class Constant implements Cloneable, Node, Serializable { - /* In fact this tag is redundant since we can distinguish different - * `Constant' objects by their type, i.e., via `instanceof'. In some - * places we will use the tag for switch()es anyway. - * - * First, we want match the specification as closely as possible. Second we - * need the tag as an index to select the corresponding class name from the - * `CONSTANT_NAMES' array. - */ - protected byte tag; - - Constant(byte tag) { this.tag = tag; } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public abstract void accept(Visitor v); - - public abstract void dump(DataOutputStream file) throws IOException; - - /** - * @return Tag of constant, i.e., its type. No setTag() method to avoid - * confusion. - */ - public final byte getTag() { return tag; } - - /** - * @return String representation. - */ - public String toString() { - return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; - } - - /** - * @return deep copy of this constant - */ - public Constant copy() { - try { - return (Constant)super.clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - /** - * Read one constant from the given file, the type depends on a tag byte. - * - * @param file Input stream - * @return Constant object - */ - static final Constant readConstant(DataInputStream file) - throws IOException, ClassFormatException - { - byte b = file.readByte(); // Read tag byte - - switch(b) { - case Constants.CONSTANT_Class: return new ConstantClass(file); - case Constants.CONSTANT_Fieldref: return new ConstantFieldref(file); - case Constants.CONSTANT_Methodref: return new ConstantMethodref(file); - case Constants.CONSTANT_InterfaceMethodref: return new - ConstantInterfaceMethodref(file); - case Constants.CONSTANT_String: return new ConstantString(file); - case Constants.CONSTANT_Integer: return new ConstantInteger(file); - case Constants.CONSTANT_Float: return new ConstantFloat(file); - case Constants.CONSTANT_Long: return new ConstantLong(file); - case Constants.CONSTANT_Double: return new ConstantDouble(file); - case Constants.CONSTANT_NameAndType: return new ConstantNameAndType(file); - case Constants.CONSTANT_Utf8: return new ConstantUtf8(file); - default: - throw new ClassFormatException("Invalid byte tag in constant pool: " + b); - } - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantCP.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantCP.java deleted file mode 100644 index 55ca1b2..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantCP.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ -import java.io.*; -import org.apache.bcel.Constants; - -/** - * Abstract super class for Fieldref and Methodref constants. - * - * @version $Id: ConstantCP.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see ConstantFieldref - * @see ConstantMethodref - * @see ConstantInterfaceMethodref - */ -public abstract class ConstantCP extends Constant { - /** References to the constants containing the class and the field signature - */ - protected int class_index, name_and_type_index; - - /** - * Initialize from another object. - */ - public ConstantCP(ConstantCP c) { - this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex()); - } - - /** - * Initialize instance from file data. - * - * @param tag Constant type tag - * @param file Input stream - * @throws IOException - */ - ConstantCP(byte tag, DataInputStream file) throws IOException - { - this(tag, file.readUnsignedShort(), file.readUnsignedShort()); - } - - /** - * @param class_index Reference to the class containing the field - * @param name_and_type_index and the field signature - */ - protected ConstantCP(byte tag, int class_index, - int name_and_type_index) { - super(tag); - this.class_index = class_index; - this.name_and_type_index = name_and_type_index; - } - - /** - * Dump constant field reference to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeShort(class_index); - file.writeShort(name_and_type_index); - } - - /** - * @return Reference (index) to class this field or method belongs to. - */ - public final int getClassIndex() { return class_index; } - - /** - * @return Reference (index) to signature of the field. - */ - public final int getNameAndTypeIndex() { return name_and_type_index; } - - /** - * @param class_index points to Constant_class - */ - public final void setClassIndex(int class_index) { - this.class_index = class_index; - } - - /** - * @return Class this field belongs to. - */ - public String getClass(ConstantPool cp) { - return cp.constantToString(class_index, Constants.CONSTANT_Class); - } - - /** - * @param name_and_type_index points to Constant_NameAndType - */ - public final void setNameAndTypeIndex(int name_and_type_index) { - this.name_and_type_index = name_and_type_index; - } - - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(class_index = " + class_index + - ", name_and_type_index = " + name_and_type_index + ")"; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantClass.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantClass.java deleted file mode 100644 index 3c13846..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantClass.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a (external) class. - * - * @version $Id: ConstantClass.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantClass extends Constant implements ConstantObject { - private int name_index; // Identical to ConstantString except for the name - - /** - * Initialize from another object. - */ - public ConstantClass(ConstantClass c) { - this(c.getNameIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantClass(DataInputStream file) throws IOException - { - this(file.readUnsignedShort()); - } - - /** - * @param name_index Name index in constant pool. Should refer to a - * ConstantUtf8. - */ - public ConstantClass(int name_index) { - super(Constants.CONSTANT_Class); - this.name_index = name_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantClass(this); - } - - /** - * Dump constant class to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeShort(name_index); - } - - /** - * @return Name index in constant pool of class name. - */ - public final int getNameIndex() { return name_index; } - - /** - * @param name_index. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } - - - /** @return String object - */ - public Object getConstantValue(ConstantPool cp) { - Constant c = cp.getConstant(name_index, Constants.CONSTANT_Utf8); - return ((ConstantUtf8)c).getBytes(); - } - - /** @return dereferenced string - */ - public String getBytes(ConstantPool cp) { - return (String)getConstantValue(cp); - } - - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(name_index = " + name_index + ")"; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantDouble.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantDouble.java deleted file mode 100644 index ab1b15f..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantDouble.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a Double object. - * - * @version $Id: ConstantDouble.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantDouble extends Constant implements ConstantObject { - private double bytes; - - /** - * @param bytes Data - */ - public ConstantDouble(double bytes) { - super(Constants.CONSTANT_Double); - this.bytes = bytes; - } - - /** - * Initialize from another object. - */ - public ConstantDouble(ConstantDouble c) { - this(c.getBytes()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantDouble(DataInputStream file) throws IOException - { - this(file.readDouble()); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantDouble(this); - } - /** - * Dump constant double to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeDouble(bytes); - } - /** - * @return data, i.e., 8 bytes. - */ - public final double getBytes() { return bytes; } - /** - * @param bytes. - */ - public final void setBytes(double bytes) { - this.bytes = bytes; - } - /** - * @return String representation. - */ - public final String toString() - { - return super.toString() + "(bytes = " + bytes + ")"; - } - - /** @return Double object - */ - public Object getConstantValue(ConstantPool cp) { - return new Double(bytes); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFieldref.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFieldref.java deleted file mode 100644 index 6ea534e..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFieldref.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a constant pool reference to a field. - * - * @version $Id: ConstantFieldref.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - */ -public final class ConstantFieldref extends ConstantCP { - /** - * Initialize from another object. - */ - public ConstantFieldref(ConstantFieldref c) { - super(Constants.CONSTANT_Fieldref, c.getClassIndex(), c.getNameAndTypeIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file input stream - * @throws IOException - */ - ConstantFieldref(DataInputStream file) throws IOException - { - super(Constants.CONSTANT_Fieldref, file); - } - - /** - * @param class_index Reference to the class containing the Field - * @param name_and_type_index and the Field signature - */ - public ConstantFieldref(int class_index, - int name_and_type_index) { - super(Constants.CONSTANT_Fieldref, class_index, name_and_type_index); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of Fields, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantFieldref(this); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFloat.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFloat.java deleted file mode 100644 index 7de9816..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantFloat.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a float object. - * - * @version $Id: ConstantFloat.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantFloat extends Constant implements ConstantObject { - private float bytes; - - /** - * @param bytes Data - */ - public ConstantFloat(float bytes) - { - super(Constants.CONSTANT_Float); - this.bytes = bytes; - } - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public ConstantFloat(ConstantFloat c) { - this(c.getBytes()); - } - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantFloat(DataInputStream file) throws IOException - { - this(file.readFloat()); - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantFloat(this); - } - /** - * Dump constant float to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeFloat(bytes); - } - /** - * @return data, i.e., 4 bytes. - */ - public final float getBytes() { return bytes; } - /** - * @param bytes. - */ - public final void setBytes(float bytes) { - this.bytes = bytes; - } - - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(bytes = " + bytes + ")"; - } - - /** @return Float object - */ - public Object getConstantValue(ConstantPool cp) { - return new Float(bytes); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInteger.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInteger.java deleted file mode 100644 index a0288a0..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInteger.java +++ /dev/null @@ -1,148 +0,0 @@ - -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to an int object. - * - * @version $Id: ConstantInteger.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantInteger extends Constant implements ConstantObject { - private int bytes; - - /** - * @param bytes Data - */ - public ConstantInteger(int bytes) - { - super(Constants.CONSTANT_Integer); - this.bytes = bytes; - } - - /** - * Initialize from another object. - */ - public ConstantInteger(ConstantInteger c) { - this(c.getBytes()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantInteger(DataInputStream file) throws IOException - { - this(file.readInt()); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantInteger(this); - } - - /** - * Dump constant integer to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeInt(bytes); - } - - /** - * @return data, i.e., 4 bytes. - */ - public final int getBytes() { return bytes; } - - /** - * @param bytes. - */ - public final void setBytes(int bytes) { - this.bytes = bytes; - } - - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(bytes = " + bytes + ")"; - } - - /** @return Integer object - */ - public Object getConstantValue(ConstantPool cp) { - return new Integer(bytes); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInterfaceMethodref.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInterfaceMethodref.java deleted file mode 100644 index b790ddb..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantInterfaceMethodref.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a constant pool reference to an interface method. - * - * @version $Id: ConstantInterfaceMethodref.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - */ -public final class ConstantInterfaceMethodref extends ConstantCP { - /** - * Initialize from another object. - */ - public ConstantInterfaceMethodref(ConstantInterfaceMethodref c) { - super(Constants.CONSTANT_InterfaceMethodref, c.getClassIndex(), c.getNameAndTypeIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file input stream - * @throws IOException - */ - ConstantInterfaceMethodref(DataInputStream file) throws IOException - { - super(Constants.CONSTANT_InterfaceMethodref, file); - } - - /** - * @param class_index Reference to the class containing the method - * @param name_and_type_index and the method signature - */ - public ConstantInterfaceMethodref(int class_index, - int name_and_type_index) { - super(Constants.CONSTANT_InterfaceMethodref, class_index, name_and_type_index); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantInterfaceMethodref(this); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantLong.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantLong.java deleted file mode 100644 index b794afd..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantLong.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a long object. - * - * @version $Id: ConstantLong.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantLong extends Constant implements ConstantObject { - private long bytes; - - /** - * @param bytes Data - */ - public ConstantLong(long bytes) - { - super(Constants.CONSTANT_Long); - this.bytes = bytes; - } - /** - * Initialize from another object. - */ - public ConstantLong(ConstantLong c) { - this(c.getBytes()); - } - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantLong(DataInputStream file) throws IOException - { - this(file.readLong()); - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantLong(this); - } - /** - * Dump constant long to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeLong(bytes); - } - /** - * @return data, i.e., 8 bytes. - */ - public final long getBytes() { return bytes; } - /** - * @param bytes. - */ - public final void setBytes(long bytes) { - this.bytes = bytes; - } - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(bytes = " + bytes + ")"; - } - - /** @return Long object - */ - public Object getConstantValue(ConstantPool cp) { - return new Long(bytes); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantMethodref.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantMethodref.java deleted file mode 100644 index c5101b2..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantMethodref.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a constant pool reference to a method. - * - * @version $Id: ConstantMethodref.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - */ -public final class ConstantMethodref extends ConstantCP { - /** - * Initialize from another object. - */ - public ConstantMethodref(ConstantMethodref c) { - super(Constants.CONSTANT_Methodref, c.getClassIndex(), c.getNameAndTypeIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file input stream - * @throws IOException - */ - ConstantMethodref(DataInputStream file) throws IOException - { - super(Constants.CONSTANT_Methodref, file); - } - - /** - * @param class_index Reference to the class containing the method - * @param name_and_type_index and the method signature - */ - public ConstantMethodref(int class_index, - int name_and_type_index) { - super(Constants.CONSTANT_Methodref, class_index, name_and_type_index); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantMethodref(this); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantNameAndType.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantNameAndType.java deleted file mode 100644 index e45c805..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantNameAndType.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to the name and signature - * of a field or method. - * - * @version $Id: ConstantNameAndType.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantNameAndType extends Constant { - private int name_index; // Name of field/method - private int signature_index; // and its signature. - - /** - * Initialize from another object. - */ - public ConstantNameAndType(ConstantNameAndType c) { - this(c.getNameIndex(), c.getSignatureIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantNameAndType(DataInputStream file) throws IOException - { - this((int)file.readUnsignedShort(), (int)file.readUnsignedShort()); - } - - /** - * @param name_index Name of field/method - * @param signature_index and its signature - */ - public ConstantNameAndType(int name_index, - int signature_index) - { - super(Constants.CONSTANT_NameAndType); - this.name_index = name_index; - this.signature_index = signature_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantNameAndType(this); - } - - /** - * Dump name and signature index to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeShort(name_index); - file.writeShort(signature_index); - } - - /** - * @return Name index in constant pool of field/method name. - */ - public final int getNameIndex() { return name_index; } - - /** @return name - */ - public final String getName(ConstantPool cp) { - return cp.constantToString(getNameIndex(), Constants.CONSTANT_Utf8); - } - - /** - * @return Index in constant pool of field/method signature. - */ - public final int getSignatureIndex() { return signature_index; } - - /** @return signature - */ - public final String getSignature(ConstantPool cp) { - return cp.constantToString(getSignatureIndex(), Constants.CONSTANT_Utf8); - } - - /** - * @param name_index. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } - - /** - * @param signature_index. - */ - public final void setSignatureIndex(int signature_index) { - this.signature_index = signature_index; - } - - /** - * @return String representation - */ - public final String toString() { - return super.toString() + "(name_index = " + name_index + - ", signature_index = " + signature_index + ")"; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantObject.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantObject.java deleted file mode 100644 index b70cde0..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantObject.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * This interface denotes those constants that have a "natural" value, - * such as ConstantLong, ConstantString, etc.. - * - * @version $Id: ConstantObject.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public interface ConstantObject { - /** @return object representing the constant, e.g., Long for ConstantLong - */ - public abstract Object getConstantValue(ConstantPool cp); -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantPool.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantPool.java deleted file mode 100644 index 98a4c41..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantPool.java +++ /dev/null @@ -1,372 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents the constant pool, i.e., a table of constants, of - * a parsed classfile. It may contain null references, due to the JVM - * specification that skips an entry after an 8-byte constant (double, - * long) entry. Those interested in generating constant pools - * programatically should see - * ConstantPoolGen. - - * @version $Id: ConstantPool.java,v 1.6 2002/07/11 19:39:04 mdahm Exp $ - * @see Constant - * @see org.apache.bcel.generic.ConstantPoolGen - * @author M. Dahm - */ -public class ConstantPool implements Cloneable, Node, Serializable { - private int constant_pool_count; - private Constant[] constant_pool; - - /** - * @param constant_pool Array of constants - */ - public ConstantPool(Constant[] constant_pool) - { - setConstantPool(constant_pool); - } - - /** - * Read constants from given file stream. - * - * @param file Input stream - * @throws IOException - * @throws ClassFormatException - */ - ConstantPool(DataInputStream file) throws IOException, ClassFormatException - { - byte tag; - - constant_pool_count = file.readUnsignedShort(); - constant_pool = new Constant[constant_pool_count]; - - /* constant_pool[0] is unused by the compiler and may be used freely - * by the implementation. - */ - for(int i=1; i < constant_pool_count; i++) { - constant_pool[i] = Constant.readConstant(file); - - /* Quote from the JVM specification: - * "All eight byte constants take up two spots in the constant pool. - * If this is the n'th byte in the constant pool, then the next item - * will be numbered n+2" - * - * Thus we have to increment the index counter. - */ - tag = constant_pool[i].getTag(); - if((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) - i++; - } - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantPool(this); - } - - /** - * Resolve constant to a string representation. - * - * @param constant Constant to be printed - * @return String representation - */ - public String constantToString(Constant c) - throws ClassFormatException - { - String str; - int i; - byte tag = c.getTag(); - - switch(tag) { - case Constants.CONSTANT_Class: - i = ((ConstantClass)c).getNameIndex(); - c = getConstant(i, Constants.CONSTANT_Utf8); - str = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false); - break; - - case Constants.CONSTANT_String: - i = ((ConstantString)c).getStringIndex(); - c = getConstant(i, Constants.CONSTANT_Utf8); - str = "\"" + escape(((ConstantUtf8)c).getBytes()) + "\""; - break; - - case Constants.CONSTANT_Utf8: str = ((ConstantUtf8)c).getBytes(); break; - case Constants.CONSTANT_Double: str = "" + ((ConstantDouble)c).getBytes(); break; - case Constants.CONSTANT_Float: str = "" + ((ConstantFloat)c).getBytes(); break; - case Constants.CONSTANT_Long: str = "" + ((ConstantLong)c).getBytes(); break; - case Constants.CONSTANT_Integer: str = "" + ((ConstantInteger)c).getBytes(); break; - - case Constants.CONSTANT_NameAndType: - str = (constantToString(((ConstantNameAndType)c).getNameIndex(), - Constants.CONSTANT_Utf8) + " " + - constantToString(((ConstantNameAndType)c).getSignatureIndex(), - Constants.CONSTANT_Utf8)); - break; - - case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref: - case Constants.CONSTANT_Fieldref: - str = (constantToString(((ConstantCP)c).getClassIndex(), - Constants.CONSTANT_Class) + "." + - constantToString(((ConstantCP)c).getNameAndTypeIndex(), - Constants.CONSTANT_NameAndType)); - break; - - default: // Never reached - throw new RuntimeException("Unknown constant type " + tag); - } - - return str; - } - - private static final String escape(String str) { - int len = str.length(); - StringBuffer buf = new StringBuffer(len + 5); - char[] ch = str.toCharArray(); - - for(int i=0; i < len; i++) { - switch(ch[i]) { - case '\n' : buf.append("\\n"); break; - case '\r' : buf.append("\\r"); break; - case '\t' : buf.append("\\t"); break; - case '\b' : buf.append("\\b"); break; - case '"' : buf.append("\\\""); break; - default: buf.append(ch[i]); - } - } - - return buf.toString(); - } - - - /** - * Retrieve constant at `index' from constant pool and resolve it to - * a string representation. - * - * @param index of constant in constant pool - * @param tag expected type - * @return String representation - */ - public String constantToString(int index, byte tag) - throws ClassFormatException - { - Constant c = getConstant(index, tag); - return constantToString(c); - } - - /** - * Dump constant pool to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public void dump(DataOutputStream file) throws IOException - { - file.writeShort(constant_pool_count); - - for(int i=1; i < constant_pool_count; i++) - if(constant_pool[i] != null) - constant_pool[i].dump(file); - } - - /** - * Get constant from constant pool. - * - * @param index Index in constant pool - * @return Constant value - * @see Constant - */ - public Constant getConstant(int index) { - if (index >= constant_pool.length || index < 0) - throw new ClassFormatException("Invalid constant pool reference: " + - index + ". Constant pool size is: " + - constant_pool.length); - return constant_pool[index]; - } - - /** - * Get constant from constant pool and check whether it has the - * expected type. - * - * @param index Index in constant pool - * @param tag Tag of expected constant, i.e., its type - * @return Constant value - * @see Constant - * @throws ClassFormatException - */ - public Constant getConstant(int index, byte tag) - throws ClassFormatException - { - Constant c; - - c = getConstant(index); - - if(c == null) - throw new ClassFormatException("Constant pool at index " + index + " is null."); - - if(c.getTag() == tag) - return c; - else - throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] + - "' at index " + index + " and got " + c); - } - - /** - * @return Array of constants. - * @see Constant - */ - public Constant[] getConstantPool() { return constant_pool; } - /** - * Get string from constant pool and bypass the indirection of - * `ConstantClass' and `ConstantString' objects. I.e. these classes have - * an index field that points to another entry of the constant pool of - * type `ConstantUtf8' which contains the real data. - * - * @param index Index in constant pool - * @param tag Tag of expected constant, either ConstantClass or ConstantString - * @return Contents of string reference - * @see ConstantClass - * @see ConstantString - * @throws ClassFormatException - */ - public String getConstantString(int index, byte tag) - throws ClassFormatException - { - Constant c; - int i; - - c = getConstant(index, tag); - - /* This switch() is not that elegant, since the two classes have the - * same contents, they just differ in the name of the index - * field variable. - * But we want to stick to the JVM naming conventions closely though - * we could have solved these more elegantly by using the same - * variable name or by subclassing. - */ - switch(tag) { - case Constants.CONSTANT_Class: i = ((ConstantClass)c).getNameIndex(); break; - case Constants.CONSTANT_String: i = ((ConstantString)c).getStringIndex(); break; - default: - throw new RuntimeException("getConstantString called with illegal tag " + tag); - } - - // Finally get the string from the constant pool - c = getConstant(i, Constants.CONSTANT_Utf8); - return ((ConstantUtf8)c).getBytes(); - } - /** - * @return Length of constant pool. - */ - public int getLength() - { - return constant_pool_count; - } - - /** - * @param constant Constant to set - */ - public void setConstant(int index, Constant constant) { - constant_pool[index] = constant; - } - - /** - * @param constant_pool - */ - public void setConstantPool(Constant[] constant_pool) { - this.constant_pool = constant_pool; - constant_pool_count = (constant_pool == null)? 0 : constant_pool.length; - } - /** - * @return String representation. - */ - public String toString() { - StringBuffer buf = new StringBuffer(); - - for(int i=1; i < constant_pool_count; i++) - buf.append(i + ")" + constant_pool[i] + "\n"); - - return buf.toString(); - } - - /** - * @return deep copy of this constant pool - */ - public ConstantPool copy() { - ConstantPool c = null; - - try { - c = (ConstantPool)clone(); - } catch(CloneNotSupportedException e) {} - - c.constant_pool = new Constant[constant_pool_count]; - - for(int i=1; i < constant_pool_count; i++) { - if(constant_pool[i] != null) - c.constant_pool[i] = constant_pool[i].copy(); - } - - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantString.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantString.java deleted file mode 100644 index be380e3..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantString.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a String object. - * - * @version $Id: ConstantString.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantString extends Constant implements ConstantObject { - private int string_index; // Identical to ConstantClass except for this name - - /** - * Initialize from another object. - */ - public ConstantString(ConstantString c) { - this(c.getStringIndex()); - } - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantString(DataInputStream file) throws IOException - { - this((int)file.readUnsignedShort()); - } - /** - * @param string_index Index of Constant_Utf8 in constant pool - */ - public ConstantString(int string_index) - { - super(Constants.CONSTANT_String); - this.string_index = string_index; - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantString(this); - } - /** - * Dump constant field reference to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeShort(string_index); - } - /** - * @return Index in constant pool of the string (ConstantUtf8). - */ - public final int getStringIndex() { return string_index; } - /** - * @param string_index. - */ - public final void setStringIndex(int string_index) { - this.string_index = string_index; - } - /** - * @return String representation. - */ - public final String toString() - { - return super.toString() + "(string_index = " + string_index + ")"; - } - - /** @return String object - */ - public Object getConstantValue(ConstantPool cp) { - Constant c = cp.getConstant(string_index, Constants.CONSTANT_Utf8); - return ((ConstantUtf8)c).getBytes(); - } - - /** @return dereferenced string - */ - public String getBytes(ConstantPool cp) { - return (String)getConstantValue(cp); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantUtf8.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantUtf8.java deleted file mode 100644 index 488dd63..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantUtf8.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a Utf8 encoded string. - * - * @version $Id: ConstantUtf8.java,v 1.3 2002/12/08 16:04:37 mdahm Exp $ - * @author M. Dahm - * @see Constant - */ -public final class ConstantUtf8 extends Constant { - private String bytes; - - /** - * Initialize from another object. - */ - public ConstantUtf8(ConstantUtf8 c) { - this(c.getBytes()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantUtf8(DataInputStream file) throws IOException - { - super(Constants.CONSTANT_Utf8); - - bytes = file.readUTF(); - } - - /** - * @param bytes Data - */ - public ConstantUtf8(String bytes) - { - super(Constants.CONSTANT_Utf8); - - if(bytes == null) - throw new IllegalArgumentException("bytes must not be null!"); - - this.bytes = bytes; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantUtf8(this); - } - - /** - * Dump String in Utf8 format to file stream. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeUTF(bytes); - } - - /** - * @return Data converted to string. - */ - public final String getBytes() { return bytes; } - - /** - * @param bytes. - */ - public final void setBytes(String bytes) { - this.bytes = bytes; - } - - /** - * @return String representation - */ - public final String toString() - { - return super.toString() + "(\"" + Utility.replace(bytes, "\n", "\\n") + "\")"; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantValue.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantValue.java deleted file mode 100644 index ce79c4b..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ConstantValue.java +++ /dev/null @@ -1,178 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and represents a constant - * value, i.e., a default value for initializing a class field. - * This class is instantiated by the Attribute.readAttribute() method. - * - * @version $Id: ConstantValue.java,v 1.5 2003/02/13 11:18:23 enver Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class ConstantValue extends Attribute { - private int constantvalue_index; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public ConstantValue(ConstantValue c) { - this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), - c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param name_index Name index in constant pool - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throw IOException - */ - ConstantValue(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (int)file.readUnsignedShort(), constant_pool); - } - - /** - * @param name_index Name index in constant pool - * @param length Content length in bytes - * @param constantvalue_index Index in constant pool - * @param constant_pool Array of constants - */ - public ConstantValue(int name_index, int length, - int constantvalue_index, - ConstantPool constant_pool) - { - super(Constants.ATTR_CONSTANT_VALUE, name_index, length, constant_pool); - this.constantvalue_index = constantvalue_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitConstantValue(this); - } - /** - * Dump constant value attribute to file stream on binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(constantvalue_index); - } - /** - * @return Index in constant pool of constant value. - */ - public final int getConstantValueIndex() { return constantvalue_index; } - - /** - * @param constantvalue_index. - */ - public final void setConstantValueIndex(int constantvalue_index) { - this.constantvalue_index = constantvalue_index; - } - - /** - * @return String representation of constant value. - */ - public final String toString() { - Constant c = constant_pool.getConstant(constantvalue_index); - - String buf; - int i; - - // Print constant to string depending on its type - switch(c.getTag()) { - case Constants.CONSTANT_Long: buf = "" + ((ConstantLong)c).getBytes(); break; - case Constants.CONSTANT_Float: buf = "" + ((ConstantFloat)c).getBytes(); break; - case Constants.CONSTANT_Double: buf = "" + ((ConstantDouble)c).getBytes(); break; - case Constants.CONSTANT_Integer: buf = "" + ((ConstantInteger)c).getBytes(); break; - case Constants.CONSTANT_String: - i = ((ConstantString)c).getStringIndex(); - c = constant_pool.getConstant(i, Constants.CONSTANT_Utf8); - buf = "\"" + Utility.convertString(((ConstantUtf8)c).getBytes()) + "\""; - break; - - default: - throw new IllegalStateException("Type of ConstValue invalid: " + c); - } - - return buf; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - ConstantValue c = (ConstantValue)clone(); - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Deprecated.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Deprecated.java deleted file mode 100644 index d8648a8..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Deprecated.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and denotes that this is a - * deprecated method. - * It is instantiated from the Attribute.readAttribute() method. - * - * @version $Id: Deprecated.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class Deprecated extends Attribute { - private byte[] bytes; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Deprecated(Deprecated c) { - this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param bytes Attribute contents - * @param constant_pool Array of constants - */ - public Deprecated(int name_index, int length, byte[] bytes, - ConstantPool constant_pool) - { - super(Constants.ATTR_DEPRECATED, name_index, length, constant_pool); - this.bytes = bytes; - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - Deprecated(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (byte [])null, constant_pool); - - if(length > 0) { - bytes = new byte[length]; - file.readFully(bytes); - System.err.println("Deprecated attribute with length > 0"); - } - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitDeprecated(this); - } - - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - - if(length > 0) - file.write(bytes, 0, length); - } - - /** - * @return data bytes. - */ - public final byte[] getBytes() { return bytes; } - - /** - * @param bytes. - */ - public final void setBytes(byte[] bytes) { - this.bytes = bytes; - } - - /** - * @return attribute name - */ - public final String toString() { - return Constants.ATTRIBUTE_NAMES[Constants.ATTR_DEPRECATED]; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - Deprecated c = (Deprecated)clone(); - - if(bytes != null) - c.bytes = (byte[])bytes.clone(); - - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/DescendingVisitor.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/DescendingVisitor.java deleted file mode 100644 index 563986e..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/DescendingVisitor.java +++ /dev/null @@ -1,357 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ -import java.util.Stack; - -/** - * Traverses a JavaClass with another Visitor object 'piggy-backed' - * that is applied to all components of a JavaClass object. I.e. this - * class supplies the traversal strategy, other classes can make use - * of it. - * - * @version $Id: DescendingVisitor.java,v 1.2 2002/02/04 13:07:30 enver Exp $ - * @author M. Dahm - */ -public class DescendingVisitor implements Visitor { - private JavaClass clazz; - private Visitor visitor; - private Stack stack = new Stack(); - - /** @return container of current entitity, i.e., predecessor during traversal - */ - public Object predecessor() { - return predecessor(0); - } - - /** - * @param level nesting level, i.e., 0 returns the direct predecessor - * @return container of current entitity, i.e., predecessor during traversal - */ - public Object predecessor(int level) { - int size = stack.size(); - - if((size < 2) || (level < 0)) - return null; - else - return stack.elementAt(size - (level + 2)); // size - 1 == current - } - - /** @return current object - */ - public Object current() { - return stack.peek(); - } - - /** - * @param clazz Class to traverse - * @param visitor visitor object to apply to all components - */ - public DescendingVisitor(JavaClass clazz, Visitor visitor) { - this.clazz = clazz; - this.visitor = visitor; - } - - /** - * Start traversal. - */ - public void visit() { clazz.accept(this); } - - public void visitJavaClass(JavaClass clazz) { - stack.push(clazz); - clazz.accept(visitor); - - Field[] fields = clazz.getFields(); - for(int i=0; i < fields.length; i++) - fields[i].accept(this); - - Method[] methods = clazz.getMethods(); - for(int i=0; i < methods.length; i++) - methods[i].accept(this); - - Attribute[] attributes = clazz.getAttributes(); - for(int i=0; i < attributes.length; i++) - attributes[i].accept(this); - - clazz.getConstantPool().accept(this); - stack.pop(); - } - - public void visitField(Field field) { - stack.push(field); - field.accept(visitor); - - Attribute[] attributes = field.getAttributes(); - for(int i=0; i < attributes.length; i++) - attributes[i].accept(this); - stack.pop(); - } - - public void visitConstantValue(ConstantValue cv) { - stack.push(cv); - cv.accept(visitor); - stack.pop(); - } - - public void visitMethod(Method method) { - stack.push(method); - method.accept(visitor); - - Attribute[] attributes = method.getAttributes(); - for(int i=0; i < attributes.length; i++) - attributes[i].accept(this); - - stack.pop(); - } - - public void visitExceptionTable(ExceptionTable table) { - stack.push(table); - table.accept(visitor); - stack.pop(); - } - - public void visitCode(Code code) { - stack.push(code); - code.accept(visitor); - - CodeException[] table = code.getExceptionTable(); - for(int i=0; i < table.length; i++) - table[i].accept(this); - - Attribute[] attributes = code.getAttributes(); - for(int i=0; i < attributes.length; i++) - attributes[i].accept(this); - stack.pop(); - } - - public void visitCodeException(CodeException ce) { - stack.push(ce); - ce.accept(visitor); - stack.pop(); - } - - public void visitLineNumberTable(LineNumberTable table) { - stack.push(table); - table.accept(visitor); - - LineNumber[] numbers = table.getLineNumberTable(); - for(int i=0; i < numbers.length; i++) - numbers[i].accept(this); - stack.pop(); - } - - public void visitLineNumber(LineNumber number) { - stack.push(number); - number.accept(visitor); - stack.pop(); - } - - public void visitLocalVariableTable(LocalVariableTable table) { - stack.push(table); - table.accept(visitor); - - LocalVariable[] vars = table.getLocalVariableTable(); - for(int i=0; i < vars.length; i++) - vars[i].accept(this); - stack.pop(); - } - - public void visitStackMap(StackMap table) { - stack.push(table); - table.accept(visitor); - - StackMapEntry[] vars = table.getStackMap(); - - for(int i=0; i < vars.length; i++) - vars[i].accept(this); - stack.pop(); - } - - public void visitStackMapEntry(StackMapEntry var) { - stack.push(var); - var.accept(visitor); - stack.pop(); - } - - public void visitLocalVariable(LocalVariable var) { - stack.push(var); - var.accept(visitor); - stack.pop(); - } - - public void visitConstantPool(ConstantPool cp) { - stack.push(cp); - cp.accept(visitor); - - Constant[] constants = cp.getConstantPool(); - for(int i=1; i < constants.length; i++) { - if(constants[i] != null) - constants[i].accept(this); - } - - stack.pop(); - } - - public void visitConstantClass(ConstantClass constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantDouble(ConstantDouble constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantFieldref(ConstantFieldref constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantFloat(ConstantFloat constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantInteger(ConstantInteger constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantLong(ConstantLong constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantMethodref(ConstantMethodref constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantNameAndType(ConstantNameAndType constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantString(ConstantString constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitConstantUtf8(ConstantUtf8 constant) { - stack.push(constant); - constant.accept(visitor); - stack.pop(); - } - - public void visitInnerClasses(InnerClasses ic) { - stack.push(ic); - ic.accept(visitor); - - InnerClass[] ics = ic.getInnerClasses(); - for(int i=0; i < ics.length; i++) - ics[i].accept(this); - stack.pop(); - } - - public void visitInnerClass(InnerClass inner) { - stack.push(inner); - inner.accept(visitor); - stack.pop(); - } - - public void visitDeprecated(Deprecated attribute) { - stack.push(attribute); - attribute.accept(visitor); - stack.pop(); - } - - public void visitSignature(Signature attribute) { - stack.push(attribute); - attribute.accept(visitor); - stack.pop(); - } - - public void visitSourceFile(SourceFile attribute) { - stack.push(attribute); - attribute.accept(visitor); - stack.pop(); - } - - public void visitSynthetic(Synthetic attribute) { - stack.push(attribute); - attribute.accept(visitor); - stack.pop(); - } - - public void visitUnknown(Unknown attribute) { - stack.push(attribute); - attribute.accept(visitor); - stack.pop(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/EmptyVisitor.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/EmptyVisitor.java deleted file mode 100644 index dc8ff8a..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/EmptyVisitor.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.classfile.*; -import org.apache.bcel.*; - -/** - * Visitor with empty method bodies, can be extended and used in conjunction with the - * DescendingVisitor class, e.g. - * - * By courtesy of David Spencer. - * - * @see DescendingVisitor - * @version $Id: EmptyVisitor.java,v 1.2 2002/02/04 13:07:30 enver Exp $ - * - */ -public class EmptyVisitor implements Visitor { - protected EmptyVisitor() { } - - public void visitCode(Code obj) {} - public void visitCodeException(CodeException obj) {} - public void visitConstantClass(ConstantClass obj) {} - public void visitConstantDouble(ConstantDouble obj) {} - public void visitConstantFieldref(ConstantFieldref obj) {} - public void visitConstantFloat(ConstantFloat obj) {} - public void visitConstantInteger(ConstantInteger obj) {} - public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj) {} - public void visitConstantLong(ConstantLong obj) {} - public void visitConstantMethodref(ConstantMethodref obj) {} - public void visitConstantNameAndType(ConstantNameAndType obj) {} - public void visitConstantPool(ConstantPool obj) {} - public void visitConstantString(ConstantString obj) {} - public void visitConstantUtf8(ConstantUtf8 obj) {} - public void visitConstantValue(ConstantValue obj) {} - public void visitDeprecated(Deprecated obj) {} - public void visitExceptionTable(ExceptionTable obj) {} - public void visitField(Field obj) {} - public void visitInnerClass(InnerClass obj) {} - public void visitInnerClasses(InnerClasses obj) {} - public void visitJavaClass(JavaClass obj) {} - public void visitLineNumber(LineNumber obj) {} - public void visitLineNumberTable(LineNumberTable obj) {} - public void visitLocalVariable(LocalVariable obj) {} - public void visitLocalVariableTable(LocalVariableTable obj) {} - public void visitMethod(Method obj) {} - public void visitSignature(Signature obj) {} - public void visitSourceFile(SourceFile obj) {} - public void visitSynthetic(Synthetic obj) {} - public void visitUnknown(Unknown obj) {} - public void visitStackMap(StackMap obj) {} - public void visitStackMapEntry(StackMapEntry obj) {} -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ExceptionTable.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/ExceptionTable.java deleted file mode 100644 index 4b70945..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/ExceptionTable.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents the table of exceptions that are thrown by a - * method. This attribute may be used once per method. The name of - * this class is ExceptionTable for historical reasons; The - * Java Virtual Machine Specification, Second Edition defines this - * attribute using the name Exceptions (which is inconsistent - * with the other classes). - * - * @version $Id: ExceptionTable.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Code - */ -public final class ExceptionTable extends Attribute { - private int number_of_exceptions; // Table of indices into - private int[] exception_index_table; // constant pool - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public ExceptionTable(ExceptionTable c) { - this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), - c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param exception_index_table Table of indices in constant pool - * @param constant_pool Array of constants - */ - public ExceptionTable(int name_index, int length, - int[] exception_index_table, - ConstantPool constant_pool) - { - super(Constants.ATTR_EXCEPTIONS, name_index, length, constant_pool); - setExceptionIndexTable(exception_index_table); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - ExceptionTable(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (int[])null, constant_pool); - - number_of_exceptions = file.readUnsignedShort(); - exception_index_table = new int[number_of_exceptions]; - - for(int i=0; i < number_of_exceptions; i++) - exception_index_table[i] = file.readUnsignedShort(); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitExceptionTable(this); - } - - /** - * Dump exceptions attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(number_of_exceptions); - for(int i=0; i < number_of_exceptions; i++) - file.writeShort(exception_index_table[i]); - } - - /** - * @return Array of indices into constant pool of thrown exceptions. - */ - public final int[] getExceptionIndexTable() {return exception_index_table;} - /** - * @return Length of exception table. - */ - public final int getNumberOfExceptions() { return number_of_exceptions; } - - /** - * @return class names of thrown exceptions - */ - public final String[] getExceptionNames() { - String[] names = new String[number_of_exceptions]; - for(int i=0; i < number_of_exceptions; i++) - names[i] = constant_pool.getConstantString(exception_index_table[i], - Constants.CONSTANT_Class). - replace('/', '.'); - return names; - } - - /** - * @param exception_index_table. - * Also redefines number_of_exceptions according to table length. - */ - public final void setExceptionIndexTable(int[] exception_index_table) { - this.exception_index_table = exception_index_table; - number_of_exceptions = (exception_index_table == null)? 0 : - exception_index_table.length; - } - /** - * @return String representation, i.e., a list of thrown exceptions. - */ - public final String toString() { - StringBuffer buf = new StringBuffer(""); - String str; - - for(int i=0; i < number_of_exceptions; i++) { - str = constant_pool.getConstantString(exception_index_table[i], - Constants.CONSTANT_Class); - buf.append(Utility.compactClassName(str, false)); - - if(i < number_of_exceptions - 1) - buf.append(", "); - } - - return buf.toString(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - ExceptionTable c = (ExceptionTable)clone(); - c.exception_index_table = (int[])exception_index_table.clone(); - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Field.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Field.java deleted file mode 100644 index aaae002..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Field.java +++ /dev/null @@ -1,165 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ -import org.apache.bcel.Constants; -import org.apache.bcel.generic.Type; -import java.io.*; - -/** - * This class represents the field info structure, i.e., the representation - * for a variable in the class. See JVM specification for details. - * - * @version $Id: Field.java,v 1.3 2002/12/08 16:04:37 mdahm Exp $ - * @author M. Dahm - */ -public final class Field extends FieldOrMethod { - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Field(Field c) { - super(c); - } - - /** - * Construct object from file stream. - * @param file Input stream - */ - Field(DataInputStream file, ConstantPool constant_pool) - throws IOException, ClassFormatException - { - super(file, constant_pool); - } - - /** - * @param access_flags Access rights of field - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature - * @param attributes Collection of attributes - * @param constant_pool Array of constants - */ - public Field(int access_flags, int name_index, int signature_index, - Attribute[] attributes, ConstantPool constant_pool) - { - super(access_flags, name_index, signature_index, attributes, constant_pool); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitField(this); - } - - /** - * @return constant value associated with this field (may be null) - */ - public final ConstantValue getConstantValue() { - for(int i=0; i < attributes_count; i++) - if(attributes[i].getTag() == Constants.ATTR_CONSTANT_VALUE) - return (ConstantValue)attributes[i]; - - return null; - } - - /** - * Return string representation close to declaration format, - * `public static final short MAX = 100', e.g.. - * - * @return String representation of field, including the signature. - */ - public final String toString() { - String name, signature, access; // Short cuts to constant pool - - // Get names from constant pool - access = Utility.accessToString(access_flags); - access = access.equals("")? "" : (access + " "); - signature = Utility.signatureToString(getSignature()); - name = getName(); - - StringBuffer buf = new StringBuffer(access + signature + " " + name); - ConstantValue cv = getConstantValue(); - - if(cv != null) - buf.append(" = " + cv); - - for(int i=0; i < attributes_count; i++) { - Attribute a = attributes[i]; - - if(!(a instanceof ConstantValue)) - buf.append(" [" + a.toString() + "]"); - } - - return buf.toString(); - } - - /** - * @return deep copy of this field - */ - public final Field copy(ConstantPool constant_pool) { - return (Field)copy_(constant_pool); - } - - /** - * @return type of field - */ - public Type getType() { - return Type.getReturnType(getSignature()); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/FieldOrMethod.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/FieldOrMethod.java deleted file mode 100644 index 6863e83..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/FieldOrMethod.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ -import org.apache.bcel.Constants; -import java.io.*; - -/** - * Abstract super class for fields and methods. - * - * @version $Id: FieldOrMethod.java,v 1.3 2002/04/24 11:01:30 mdahm Exp $ - * @author M. Dahm - */ -public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { - protected int name_index; // Points to field name in constant pool - protected int signature_index; // Points to encoded signature - protected int attributes_count;// No. of attributes - protected Attribute[] attributes; // Collection of attributes - protected ConstantPool constant_pool; - - FieldOrMethod() {} - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - protected FieldOrMethod(FieldOrMethod c) { - this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), - c.getAttributes(), c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - * @throws ClassFormatException - */ - protected FieldOrMethod(DataInputStream file, ConstantPool constant_pool) - throws IOException, ClassFormatException - { - this(file.readUnsignedShort(), file.readUnsignedShort(), - file.readUnsignedShort(), null, constant_pool); - - attributes_count = file.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - for(int i=0; i < attributes_count; i++) - attributes[i] = Attribute.readAttribute(file, constant_pool); - } - - /** - * @param access_flags Access rights of method - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature - * @param attributes Collection of attributes - * @param constant_pool Array of constants - */ - protected FieldOrMethod(int access_flags, int name_index, int signature_index, - Attribute[] attributes, ConstantPool constant_pool) - { - this.access_flags = access_flags; - this.name_index = name_index; - this.signature_index = signature_index; - this.constant_pool = constant_pool; - - setAttributes(attributes); - } - - /** - * Dump object to file stream on binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(access_flags); - file.writeShort(name_index); - file.writeShort(signature_index); - file.writeShort(attributes_count); - - for(int i=0; i < attributes_count; i++) - attributes[i].dump(file); - } - - /** - * @return Collection of object attributes. - */ - public final Attribute[] getAttributes() { return attributes; } - - /** - * @param attributes Collection of object attributes. - */ - public final void setAttributes(Attribute[] attributes) { - this.attributes = attributes; - attributes_count = (attributes == null)? 0 : attributes.length; - } - - /** - * @return Constant pool used by this object. - */ - public final ConstantPool getConstantPool() { return constant_pool; } - - /** - * @param constant_pool Constant pool to be used for this object. - */ - public final void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } - - /** - * @return Index in constant pool of object's name. - */ - public final int getNameIndex() { return name_index; } - - /** - * @param name_index Index in constant pool of object's name. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } - - /** - * @return Index in constant pool of field signature. - */ - public final int getSignatureIndex() { return signature_index; } - - /** - * @param signature_index Index in constant pool of field signature. - */ - public final void setSignatureIndex(int signature_index) { - this.signature_index = signature_index; - } - - /** - * @return Name of object, i.e., method name or field name - */ - public final String getName() { - ConstantUtf8 c; - c = (ConstantUtf8)constant_pool.getConstant(name_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return String representation of object's type signature (java style) - */ - public final String getSignature() { - ConstantUtf8 c; - c = (ConstantUtf8)constant_pool.getConstant(signature_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return deep copy of this field - */ - protected FieldOrMethod copy_(ConstantPool constant_pool) { - FieldOrMethod c = null; - - try { - c = (FieldOrMethod)clone(); - } catch(CloneNotSupportedException e) {} - - c.constant_pool = constant_pool; - c.attributes = new Attribute[attributes_count]; - - for(int i=0; i < attributes_count; i++) - c.attributes[i] = attributes[i].copy(constant_pool); - - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClass.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClass.java deleted file mode 100644 index eb43962..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClass.java +++ /dev/null @@ -1,221 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a inner class attribute, i.e., the class - * indices of the inner and outer classes, the name and the attributes - * of the inner class. - * - * @version $Id: InnerClass.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see InnerClasses - */ -public final class InnerClass implements Cloneable, Node { - private int inner_class_index; - private int outer_class_index; - private int inner_name_index; - private int inner_access_flags; - - /** - * Initialize from another object. - */ - public InnerClass(InnerClass c) { - this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), - c.getInnerAccessFlags()); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - InnerClass(DataInputStream file) throws IOException - { - this(file.readUnsignedShort(), file.readUnsignedShort(), - file.readUnsignedShort(), file.readUnsignedShort()); - } - - /** - * @param inner_class_index Class index in constant pool of inner class - * @param outer_class_index Class index in constant pool of outer class - * @param inner_name_index Name index in constant pool of inner class - * @param inner_access_flags Access flags of inner class - */ - public InnerClass(int inner_class_index, int outer_class_index, - int inner_name_index, int inner_access_flags) - { - this.inner_class_index = inner_class_index; - this.outer_class_index = outer_class_index; - this.inner_name_index = inner_name_index; - this.inner_access_flags = inner_access_flags; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitInnerClass(this); - } - /** - * Dump inner class attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(inner_class_index); - file.writeShort(outer_class_index); - file.writeShort(inner_name_index); - file.writeShort(inner_access_flags); - } - /** - * @return access flags of inner class. - */ - public final int getInnerAccessFlags() { return inner_access_flags; } - /** - * @return class index of inner class. - */ - public final int getInnerClassIndex() { return inner_class_index; } - /** - * @return name index of inner class. - */ - public final int getInnerNameIndex() { return inner_name_index; } - /** - * @return class index of outer class. - */ - public final int getOuterClassIndex() { return outer_class_index; } - /** - * @param inner_access_flags. - */ - public final void setInnerAccessFlags(int inner_access_flags) { - this.inner_access_flags = inner_access_flags; - } - /** - * @param inner_class_index. - */ - public final void setInnerClassIndex(int inner_class_index) { - this.inner_class_index = inner_class_index; - } - /** - * @param inner_name_index. - */ - public final void setInnerNameIndex(int inner_name_index) { - this.inner_name_index = inner_name_index; - } - /** - * @param outer_class_index. - */ - public final void setOuterClassIndex(int outer_class_index) { - this.outer_class_index = outer_class_index; - } - /** - * @return String representation. - */ - public final String toString() { - return "InnerClass(" + inner_class_index + ", " + outer_class_index + - ", " + inner_name_index + ", " + inner_access_flags + ")"; - } - - /** - * @return Resolved string representation - */ - public final String toString(ConstantPool constant_pool) { - String inner_class_name, outer_class_name, inner_name, access; - - inner_class_name = constant_pool.getConstantString(inner_class_index, - Constants.CONSTANT_Class); - inner_class_name = Utility.compactClassName(inner_class_name); - - if (outer_class_index != 0) { - outer_class_name = constant_pool.getConstantString(outer_class_index, - Constants.CONSTANT_Class); - outer_class_name = Utility.compactClassName(outer_class_name); - } - else - outer_class_name = ""; - - if(inner_name_index != 0) - inner_name = ((ConstantUtf8)constant_pool. - getConstant(inner_name_index, Constants.CONSTANT_Utf8)).getBytes(); - else - inner_name = ""; - - access = Utility.accessToString(inner_access_flags, true); - access = access.equals("")? "" : (access + " "); - - return "InnerClass:" + access + inner_class_name + - "(\"" + outer_class_name + "\", \"" + inner_name + "\")"; - } - - /** - * @return deep copy of this object - */ - public InnerClass copy() { - try { - return (InnerClass)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClasses.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClasses.java deleted file mode 100644 index 84b37b8..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/InnerClasses.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and denotes that this class - * is an Inner class of another. - * to the source file of this class. - * It is instantiated from the Attribute.readAttribute() method. - * - * @version $Id: InnerClasses.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class InnerClasses extends Attribute { - private InnerClass[] inner_classes; - private int number_of_classes; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public InnerClasses(InnerClasses c) { - this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), - c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param inner_classes array of inner classes attributes - * @param constant_pool Array of constants - * @param sourcefile_index Index in constant pool to CONSTANT_Utf8 - */ - public InnerClasses(int name_index, int length, - InnerClass[] inner_classes, - ConstantPool constant_pool) - { - super(Constants.ATTR_INNER_CLASSES, name_index, length, constant_pool); - setInnerClasses(inner_classes); - } - - /** - * Construct object from file stream. - * - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - InnerClasses(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (InnerClass[])null, constant_pool); - - number_of_classes = file.readUnsignedShort(); - inner_classes = new InnerClass[number_of_classes]; - - for(int i=0; i < number_of_classes; i++) - inner_classes[i] = new InnerClass(file); - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitInnerClasses(this); - } - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(number_of_classes); - - for(int i=0; i < number_of_classes; i++) - inner_classes[i].dump(file); - } - - /** - * @return array of inner class "records" - */ - public final InnerClass[] getInnerClasses() { return inner_classes; } - - /** - * @param inner_classes. - */ - public final void setInnerClasses(InnerClass[] inner_classes) { - this.inner_classes = inner_classes; - number_of_classes = (inner_classes == null)? 0 : inner_classes.length; - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer(); - - for(int i=0; i < number_of_classes; i++) - buf.append(inner_classes[i].toString(constant_pool) + "\n"); - - return buf.toString(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - InnerClasses c = (InnerClasses)clone(); - - c.inner_classes = new InnerClass[number_of_classes]; - for(int i=0; i < number_of_classes; i++) - c.inner_classes[i] = inner_classes[i].copy(); - - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/JavaClass.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/JavaClass.java deleted file mode 100644 index 3d110c1..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/JavaClass.java +++ /dev/null @@ -1,815 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import org.apache.bcel.util.SyntheticRepository; -import org.apache.bcel.util.ClassVector; -import org.apache.bcel.util.ClassQueue; -import org.apache.bcel.generic.Type; - -import java.io.*; -import java.util.StringTokenizer; - -/** - * Represents a Java class, i.e., the data structures, constant pool, - * fields, methods and commands contained in a Java .class file. - * See JVM - * specification for details. - - * The intent of this class is to represent a parsed or otherwise existing - * class file. Those interested in programatically generating classes - * should see the ClassGen class. - - * @version $Id: JavaClass.java,v 1.13 2002/07/11 19:39:04 mdahm Exp $ - * @see org.apache.bcel.generic.ClassGen - * @author M. Dahm - */ -public class JavaClass extends AccessFlags implements Cloneable, Node { - private String file_name; - private String package_name; - private String source_file_name = ""; - private int class_name_index; - private int superclass_name_index; - private String class_name; - private String superclass_name; - private int major, minor; // Compiler version - private ConstantPool constant_pool; // Constant pool - private int[] interfaces; // implemented interfaces - private String[] interface_names; - private Field[] fields; // Fields, i.e., variables of class - private Method[] methods; // methods defined in the class - private Attribute[] attributes; // attributes defined in the class - private byte source = HEAP; // Generated in memory - - public static final byte HEAP = 1; - public static final byte FILE = 2; - public static final byte ZIP = 3; - - static boolean debug = false; // Debugging on/off - static char sep = '/'; // directory separator - - /** - * In cases where we go ahead and create something, - * use the default SyntheticRepository, because we - * don't know any better. - */ - private transient org.apache.bcel.util.Repository repository = - SyntheticRepository.getInstance(); - - /** - * Constructor gets all contents as arguments. - * - * @param class_name_index Index into constant pool referencing a - * ConstantClass that represents this class. - * @param superclass_name_index Index into constant pool referencing a - * ConstantClass that represents this class's superclass. - * @param file_name File name - * @param major Major compiler version - * @param minor Minor compiler version - * @param access_flags Access rights defined by bit flags - * @param constant_pool Array of constants - * @param interfaces Implemented interfaces - * @param fields Class fields - * @param methods Class methods - * @param attributes Class attributes - * @param source Read from file or generated in memory? - */ - public JavaClass(int class_name_index, - int superclass_name_index, - String file_name, - int major, - int minor, - int access_flags, - ConstantPool constant_pool, - int[] interfaces, - Field[] fields, - Method[] methods, - Attribute[] attributes, - byte source) - { - if(interfaces == null) // Allowed for backward compatibility - interfaces = new int[0]; - if(attributes == null) - this.attributes = new Attribute[0]; - if(fields == null) - fields = new Field[0]; - if(methods == null) - methods = new Method[0]; - - this.class_name_index = class_name_index; - this.superclass_name_index = superclass_name_index; - this.file_name = file_name; - this.major = major; - this.minor = minor; - this.access_flags = access_flags; - this.constant_pool = constant_pool; - this.interfaces = interfaces; - this.fields = fields; - this.methods = methods; - this.attributes = attributes; - this.source = source; - - // Get source file name if available - for(int i=0; i < attributes.length; i++) { - if(attributes[i] instanceof SourceFile) { - source_file_name = ((SourceFile)attributes[i]).getSourceFileName(); - break; - } - } - - /* According to the specification the following entries must be of type - * `ConstantClass' but we check that anyway via the - * `ConstPool.getConstant' method. - */ - class_name = constant_pool.getConstantString(class_name_index, - Constants.CONSTANT_Class); - class_name = Utility.compactClassName(class_name, false); - - int index = class_name.lastIndexOf('.'); - if(index < 0) - package_name = ""; - else - package_name = class_name.substring(0, index); - - if(superclass_name_index > 0) { // May be zero -> class is java.lang.Object - superclass_name = constant_pool.getConstantString(superclass_name_index, - Constants.CONSTANT_Class); - superclass_name = Utility.compactClassName(superclass_name, false); - } - else - superclass_name = "java.lang.Object"; - - interface_names = new String[interfaces.length]; - for(int i=0; i < interfaces.length; i++) { - String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class); - interface_names[i] = Utility.compactClassName(str, false); - } - } - - /** - * Constructor gets all contents as arguments. - * - * @param class_name_index Class name - * @param superclass_name_index Superclass name - * @param file_name File name - * @param major Major compiler version - * @param minor Minor compiler version - * @param access_flags Access rights defined by bit flags - * @param constant_pool Array of constants - * @param interfaces Implemented interfaces - * @param fields Class fields - * @param methods Class methods - * @param attributes Class attributes - */ - public JavaClass(int class_name_index, - int superclass_name_index, - String file_name, - int major, - int minor, - int access_flags, - ConstantPool constant_pool, - int[] interfaces, - Field[] fields, - Method[] methods, - Attribute[] attributes) { - this(class_name_index, superclass_name_index, file_name, major, minor, access_flags, - constant_pool, interfaces, fields, methods, attributes, HEAP); - } - - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitJavaClass(this); - } - - /* Print debug information depending on `JavaClass.debug' - */ - static final void Debug(String str) { - if(debug) - System.out.println(str); - } - - /** - * Dump class to a file. - * - * @param file Output file - * @throws IOException - */ - public void dump(File file) throws IOException - { - String parent = file.getParent(); - - if(parent != null) { - File dir = new File(parent); - - if(dir != null) - dir.mkdirs(); - } - - dump(new DataOutputStream(new FileOutputStream(file))); - } - - /** - * Dump class to a file named file_name. - * - * @param file_name Output file name - * @exception IOException - */ - public void dump(String file_name) throws IOException - { - dump(new File(file_name)); - } - - /** - * @return class in binary format - */ - public byte[] getBytes() { - ByteArrayOutputStream s = new ByteArrayOutputStream(); - DataOutputStream ds = new DataOutputStream(s); - - try { - dump(ds); - } catch(IOException e) { - e.printStackTrace(); - } finally { - try { ds.close(); } catch(IOException e2) { e2.printStackTrace(); } - } - - return s.toByteArray(); - } - - /** - * Dump Java class to output stream in binary format. - * - * @param file Output stream - * @exception IOException - */ - public void dump(OutputStream file) throws IOException { - dump(new DataOutputStream(file)); - } - - /** - * Dump Java class to output stream in binary format. - * - * @param file Output stream - * @exception IOException - */ - public void dump(DataOutputStream file) throws IOException - { - file.writeInt(0xcafebabe); - file.writeShort(minor); - file.writeShort(major); - - constant_pool.dump(file); - - file.writeShort(access_flags); - file.writeShort(class_name_index); - file.writeShort(superclass_name_index); - - file.writeShort(interfaces.length); - for(int i=0; i < interfaces.length; i++) - file.writeShort(interfaces[i]); - - file.writeShort(fields.length); - for(int i=0; i < fields.length; i++) - fields[i].dump(file); - - file.writeShort(methods.length); - for(int i=0; i < methods.length; i++) - methods[i].dump(file); - - if(attributes != null) { - file.writeShort(attributes.length); - for(int i=0; i < attributes.length; i++) - attributes[i].dump(file); - } - else - file.writeShort(0); - - file.close(); - } - - /** - * @return Attributes of the class. - */ - public Attribute[] getAttributes() { return attributes; } - - /** - * @return Class name. - */ - public String getClassName() { return class_name; } - - /** - * @return Package name. - */ - public String getPackageName() { return package_name; } - - /** - * @return Class name index. - */ - public int getClassNameIndex() { return class_name_index; } - - /** - * @return Constant pool. - */ - public ConstantPool getConstantPool() { return constant_pool; } - - /** - * @return Fields, i.e., variables of the class. Like the JVM spec - * mandates for the classfile format, these fields are those specific to - * this class, and not those of the superclass or superinterfaces. - */ - public Field[] getFields() { return fields; } - - /** - * @return File name of class, aka SourceFile attribute value - */ - public String getFileName() { return file_name; } - - /** - * @return Names of implemented interfaces. - */ - public String[] getInterfaceNames() { return interface_names; } - - /** - * @return Indices in constant pool of implemented interfaces. - */ - public int[] getInterfaceIndices() { return interfaces; } - - /** - * @return Major number of class file version. - */ - public int getMajor() { return major; } - - /** - * @return Methods of the class. - */ - public Method[] getMethods() { return methods; } - - /** - * @return A org.apache.bcel.classfile.Method corresponding to - * java.lang.reflect.Method if any - */ - public Method getMethod(java.lang.reflect.Method m) { - for(int i = 0; i < methods.length; i++) { - Method method = methods[i]; - - if(m.getName().equals(method.getName()) && - (m.getModifiers() == method.getModifiers()) && - Type.getSignature(m).equals(method.getSignature())) { - return method; - } - } - - return null; - } - - /** - * @return Minor number of class file version. - */ - public int getMinor() { return minor; } - - /** - * @return sbsolute path to file where this class was read from - */ - public String getSourceFileName() { return source_file_name; } - - /** - * @return Superclass name. - */ - public String getSuperclassName() { return superclass_name; } - - /** - * @return Class name index. - */ - public int getSuperclassNameIndex() { return superclass_name_index; } - - static { - // Debugging ... on/off - String debug = System.getProperty("JavaClass.debug"); - - if(debug != null) - JavaClass.debug = new Boolean(debug).booleanValue(); - - // Get path separator either / or \ usually - String sep = System.getProperty("file.separator"); - - if(sep != null) - try { - JavaClass.sep = sep.charAt(0); - } catch(StringIndexOutOfBoundsException e) {} // Never reached - } - - /** - * @param attributes . - */ - public void setAttributes(Attribute[] attributes) { - this.attributes = attributes; - } - - /** - * @param class_name . - */ - public void setClassName(String class_name) { - this.class_name = class_name; - } - - /** - * @param class_name_index . - */ - public void setClassNameIndex(int class_name_index) { - this.class_name_index = class_name_index; - } - - /** - * @param constant_pool . - */ - public void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } - - /** - * @param fields . - */ - public void setFields(Field[] fields) { - this.fields = fields; - } - - /** - * Set File name of class, aka SourceFile attribute value - */ - public void setFileName(String file_name) { - this.file_name = file_name; - } - - /** - * @param interface_names . - */ - public void setInterfaceNames(String[] interface_names) { - this.interface_names = interface_names; - } - - /** - * @param interfaces . - */ - public void setInterfaces(int[] interfaces) { - this.interfaces = interfaces; - } - - /** - * @param major . - */ - public void setMajor(int major) { - this.major = major; - } - - /** - * @param methods . - */ - public void setMethods(Method[] methods) { - this.methods = methods; - } - - /** - * @param minor . - */ - public void setMinor(int minor) { - this.minor = minor; - } - - /** - * Set absolute path to file this class was read from. - */ - public void setSourceFileName(String source_file_name) { - this.source_file_name = source_file_name; - } - - /** - * @param superclass_name . - */ - public void setSuperclassName(String superclass_name) { - this.superclass_name = superclass_name; - } - - /** - * @param superclass_name_index . - */ - public void setSuperclassNameIndex(int superclass_name_index) { - this.superclass_name_index = superclass_name_index; - } - - /** - * @return String representing class contents. - */ - public String toString() { - String access = Utility.accessToString(access_flags, true); - access = access.equals("")? "" : (access + " "); - - StringBuffer buf = new StringBuffer(access + - Utility.classOrInterface(access_flags) + - " " + - class_name + " extends " + - Utility.compactClassName(superclass_name, - false) + '\n'); - int size = interfaces.length; - - if(size > 0) { - buf.append("implements\t\t"); - - for(int i=0; i < size; i++) { - buf.append(interface_names[i]); - if(i < size - 1) - buf.append(", "); - } - - buf.append('\n'); - } - - buf.append("filename\t\t" + file_name + '\n'); - buf.append("compiled from\t\t" + source_file_name + '\n'); - buf.append("compiler version\t" + major + "." + minor + '\n'); - buf.append("access flags\t\t" + access_flags + '\n'); - buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n"); - buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n"); - - if(attributes.length > 0) { - buf.append("\nAttribute(s):\n"); - for(int i=0; i < attributes.length; i++) - buf.append(indent(attributes[i])); - } - - if(fields.length > 0) { - buf.append("\n" + fields.length + " fields:\n"); - for(int i=0; i < fields.length; i++) - buf.append("\t" + fields[i] + '\n'); - } - - if(methods.length > 0) { - buf.append("\n" + methods.length + " methods:\n"); - for(int i=0; i < methods.length; i++) - buf.append("\t" + methods[i] + '\n'); - } - - return buf.toString(); - } - - private static final String indent(Object obj) { - StringTokenizer tok = new StringTokenizer(obj.toString(), "\n"); - StringBuffer buf = new StringBuffer(); - - while(tok.hasMoreTokens()) - buf.append("\t" + tok.nextToken() + "\n"); - - return buf.toString(); - } - - /** - * @return deep copy of this class - */ - public JavaClass copy() { - JavaClass c = null; - - try { - c = (JavaClass)clone(); - } catch(CloneNotSupportedException e) {} - - c.constant_pool = constant_pool.copy(); - c.interfaces = (int[])interfaces.clone(); - c.interface_names = (String[])interface_names.clone(); - - c.fields = new Field[fields.length]; - for(int i=0; i < fields.length; i++) - c.fields[i] = fields[i].copy(c.constant_pool); - - c.methods = new Method[methods.length]; - for(int i=0; i < methods.length; i++) - c.methods[i] = methods[i].copy(c.constant_pool); - - c.attributes = new Attribute[attributes.length]; - for(int i=0; i < attributes.length; i++) - c.attributes[i] = attributes[i].copy(c.constant_pool); - - return c; - } - - public final boolean isSuper() { - return (access_flags & Constants.ACC_SUPER) != 0; - } - - public final boolean isClass() { - return (access_flags & Constants.ACC_INTERFACE) == 0; - } - - /** @return returns either HEAP (generated), FILE, or ZIP - */ - public final byte getSource() { - return source; - } - - /********************* New repository functionality *********************/ - - /** - * Gets the ClassRepository which holds its definition. By default - * this is the same as SyntheticRepository.getInstance(); - */ - public org.apache.bcel.util.Repository getRepository() { - return repository; - } - - /** - * Sets the ClassRepository which loaded the JavaClass. - * Should be called immediately after parsing is done. - */ - public void setRepository(org.apache.bcel.util.Repository repository) { - this.repository = repository; - } - - /** Equivalent to runtime "instanceof" operator. - * - * @return true if this JavaClass is derived from teh super class - */ - public final boolean instanceOf(JavaClass super_class) { - if(this.equals(super_class)) - return true; - - JavaClass[] super_classes = getSuperClasses(); - - for(int i=0; i < super_classes.length; i++) { - if(super_classes[i].equals(super_class)) { - return true; - } - } - - if(super_class.isInterface()) { - return implementationOf(super_class); - } - - return false; - } - - /** - * @return true, if clazz is an implementation of interface inter - */ - public boolean implementationOf(JavaClass inter) { - if(!inter.isInterface()) { - throw new IllegalArgumentException(inter.getClassName() + " is no interface"); - } - - if(this.equals(inter)) { - return true; - } - - JavaClass[] super_interfaces = getAllInterfaces(); - - for(int i=0; i < super_interfaces.length; i++) { - if(super_interfaces[i].equals(inter)) { - return true; - } - } - - return false; - } - - /** - * @return the superclass for this JavaClass object, or null if this - * is java.lang.Object - */ - public JavaClass getSuperClass() { - if("java.lang.Object".equals(getClassName())) { - return null; - } - - try { - return repository.loadClass(getSuperclassName()); - } catch(ClassNotFoundException e) { - System.err.println(e); - return null; - } - } - - /** - * @return list of super classes of this class in ascending order, i.e., - * java.lang.Object is always the last element - */ - public JavaClass[] getSuperClasses() { - JavaClass clazz = this; - ClassVector vec = new ClassVector(); - - for(clazz = clazz.getSuperClass(); clazz != null; - clazz = clazz.getSuperClass()) - { - vec.addElement(clazz); - } - - return vec.toArray(); - } - - /** - * Get interfaces directly implemented by this JavaClass. - */ - public JavaClass[] getInterfaces() { - String[] interfaces = getInterfaceNames(); - JavaClass[] classes = new JavaClass[interfaces.length]; - - try { - for(int i = 0; i < interfaces.length; i++) { - classes[i] = repository.loadClass(interfaces[i]); - } - } catch(ClassNotFoundException e) { - System.err.println(e); - return null; - } - - return classes; - } - - /** - * Get all interfaces implemented by this JavaClass (transitively). - */ - public JavaClass[] getAllInterfaces() { - ClassQueue queue = new ClassQueue(); - ClassVector vec = new ClassVector(); - - queue.enqueue(this); - - while(!queue.empty()) { - JavaClass clazz = queue.dequeue(); - - JavaClass souper = clazz.getSuperClass(); - JavaClass[] interfaces = clazz.getInterfaces(); - - if(clazz.isInterface()) { - vec.addElement(clazz); - } else { - if(souper != null) { - queue.enqueue(souper); - } - } - - for(int i = 0; i < interfaces.length; i++) { - queue.enqueue(interfaces[i]); - } - } - - return vec.toArray(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumber.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumber.java deleted file mode 100644 index 23d51a9..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumber.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a (PC offset, line number) pair, i.e., a line number in - * the source that corresponds to a relative address in the byte code. This - * is used for debugging purposes. - * - * @version $Id: LineNumber.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - * @see LineNumberTable - */ -public final class LineNumber implements Cloneable, Node, Serializable { - private int start_pc; // Program Counter (PC) corresponds to line - private int line_number; // number in source file - - /** - * Initialize from another object. - */ - public LineNumber(LineNumber c) { - this(c.getStartPC(), c.getLineNumber()); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - LineNumber(DataInputStream file) throws IOException - { - this(file.readUnsignedShort(), file.readUnsignedShort()); - } - - /** - * @param start_pc Program Counter (PC) corresponds to - * @param line_number line number in source file - */ - public LineNumber(int start_pc, int line_number) - { - this.start_pc = start_pc; - this.line_number = line_number; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitLineNumber(this); - } - - /** - * Dump line number/pc pair to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(start_pc); - file.writeShort(line_number); - - } - /** - * @return Corresponding source line - */ - public final int getLineNumber() { return line_number; } - - /** - * @return PC in code - */ - public final int getStartPC() { return start_pc; } - - /** - * @param line_number. - */ - public final void setLineNumber(int line_number) { - this.line_number = line_number; - } - - /** - * @param start_pc. - */ - public final void setStartPC(int start_pc) { - this.start_pc = start_pc; - } - - /** - * @return String representation - */ - public final String toString() { - return "LineNumber(" + start_pc + ", " + line_number + ")"; - } - - /** - * @return deep copy of this object - */ - public LineNumber copy() { - try { - return (LineNumber)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumberTable.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumberTable.java deleted file mode 100644 index 541e476..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LineNumberTable.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a table of line numbers for debugging - * purposes. This attribute is used by the Code attribute. It - * contains pairs of PCs and line numbers. - * - * @version $Id: LineNumberTable.java,v 1.3 2002/12/08 16:04:37 mdahm Exp $ - * @author M. Dahm - * @see Code - * @see LineNumber - */ -public final class LineNumberTable extends Attribute { - private int line_number_table_length; - private LineNumber[] line_number_table; // Table of line/numbers pairs - - /* - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public LineNumberTable(LineNumberTable c) { - this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), - c.getConstantPool()); - } - - /* - * @param name_index Index of name - * @param length Content length in bytes - * @param line_number_table Table of line/numbers pairs - * @param constant_pool Array of constants - */ - public LineNumberTable(int name_index, int length, - LineNumber[] line_number_table, - ConstantPool constant_pool) - { - super(Constants.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool); - setLineNumberTable(line_number_table); - } - - /** - * Construct object from file stream. - * @param name_index Index of name - * @param length Content length in bytes - * @param file Input stream - * @throws IOException - * @param constant_pool Array of constants - */ - LineNumberTable(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (LineNumber[])null, constant_pool); - line_number_table_length = (file.readUnsignedShort()); - line_number_table = new LineNumber[line_number_table_length]; - - for(int i=0; i < line_number_table_length; i++) - line_number_table[i] = new LineNumber(file); - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitLineNumberTable(this); - } - /** - * Dump line number table attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(line_number_table_length); - for(int i=0; i < line_number_table_length; i++) - line_number_table[i].dump(file); - } - - /** - * @return Array of (pc offset, line number) pairs. - */ - public final LineNumber[] getLineNumberTable() { return line_number_table; } - - /** - * @param line_number_table. - */ - public final void setLineNumberTable(LineNumber[] line_number_table) { - this.line_number_table = line_number_table; - - line_number_table_length = (line_number_table == null)? 0 : - line_number_table.length; - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer(); - StringBuffer line = new StringBuffer(); - - for(int i=0; i < line_number_table_length; i++) { - line.append(line_number_table[i].toString()); - - if(i < line_number_table_length - 1) - line.append(", "); - - if(line.length() > 72) { - line.append('\n'); - buf.append(line); - line.setLength(0); - } - } - - buf.append(line); - - return buf.toString(); - } - - /** - * Map byte code positions to source code lines. - * - * @param pos byte code offset - * @return corresponding line in source code - */ - public int getSourceLine(int pos) { - int l = 0, r = line_number_table_length-1; - - if(r < 0) // array is empty - return -1; - - int min_index = -1, min=-1; - - /* Do a binary search since the array is ordered. - */ - do { - int i = (l + r) / 2; - int j = line_number_table[i].getStartPC(); - - if(j == pos) - return line_number_table[i].getLineNumber(); - else if(pos < j) // else constrain search area - r = i - 1; - else // pos > j - l = i + 1; - - /* If exact match can't be found (which is the most hardware case) - * return the line number that corresponds to the greatest index less - * than pos. - */ - if(j < pos && j > min) { - min = j; - min_index = i; - } - } while(l <= r); - - /* It's possible that we did not find any valid entry for the bytecode - * offset we were looking for. - */ - if (min_index < 0) - return -1; - - return line_number_table[min_index].getLineNumber(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - LineNumberTable c = (LineNumberTable)clone(); - - c.line_number_table = new LineNumber[line_number_table_length]; - for(int i=0; i < line_number_table_length; i++) - c.line_number_table[i] = line_number_table[i].copy(); - - c.constant_pool = constant_pool; - return c; - } - - public final int getTableLength() { return line_number_table_length; } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariable.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariable.java deleted file mode 100644 index 4c170a2..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariable.java +++ /dev/null @@ -1,259 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a local variable within a method. It contains its - * scope, name, signature and index on the method's frame. - * - * @version $Id: LocalVariable.java,v 1.3 2002/07/11 19:39:04 mdahm Exp $ - * @author M. Dahm - * @see LocalVariableTable - */ -public final class LocalVariable - implements Constants, Cloneable, Node, Serializable -{ - private int start_pc; // Range in which the variable is valid - private int length; - private int name_index; // Index in constant pool of variable name - private int signature_index; // Index of variable signature - private int index; /* Variable is `index'th local variable on - * this method's frame. - */ - - private ConstantPool constant_pool; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public LocalVariable(LocalVariable c) { - this(c.getStartPC(), c.getLength(), c.getNameIndex(), - c.getSignatureIndex(), c.getIndex(), c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - LocalVariable(DataInputStream file, ConstantPool constant_pool) - throws IOException - { - this(file.readUnsignedShort(), file.readUnsignedShort(), - file.readUnsignedShort(), file.readUnsignedShort(), - file.readUnsignedShort(), constant_pool); - } - - /** - * @param start_pc Range in which the variable - * @param length ... is valid - * @param name_index Index in constant pool of variable name - * @param signature_index Index of variable's signature - * @param index Variable is `index'th local variable on the method's frame - * @param constant_pool Array of constants - */ - public LocalVariable(int start_pc, int length, int name_index, - int signature_index, int index, - ConstantPool constant_pool) - { - this.start_pc = start_pc; - this.length = length; - this.name_index = name_index; - this.signature_index = signature_index; - this.index = index; - this.constant_pool = constant_pool; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitLocalVariable(this); - } - - /** - * Dump local variable to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(start_pc); - file.writeShort(length); - file.writeShort(name_index); - file.writeShort(signature_index); - file.writeShort(index); - } - - /** - * @return Constant pool used by this object. - */ - public final ConstantPool getConstantPool() { return constant_pool; } - - /** - * @return Variable is valid within getStartPC() .. getStartPC()+getLength() - */ - public final int getLength() { return length; } - - /** - * @return Variable name. - */ - public final String getName() { - ConstantUtf8 c; - - c = (ConstantUtf8)constant_pool.getConstant(name_index, CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return Index in constant pool of variable name. - */ - public final int getNameIndex() { return name_index; } - - /** - * @return Signature. - */ - public final String getSignature() { - ConstantUtf8 c; - c = (ConstantUtf8)constant_pool.getConstant(signature_index, - CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return Index in constant pool of variable signature. - */ - public final int getSignatureIndex() { return signature_index; } - - /** - * @return index of register where variable is stored - */ - public final int getIndex() { return index; } - - /** - * @return Start of range where he variable is valid - */ - public final int getStartPC() { return start_pc; } - - /** - * @param constant_pool Constant pool to be used for this object. - */ - public final void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } - - /** - * @param length. - */ - public final void setLength(int length) { - this.length = length; - } - - /** - * @param name_index. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } - - /** - * @param signature_index. - */ - public final void setSignatureIndex(int signature_index) { - this.signature_index = signature_index; - } - - /** - * @param index. - */ - public final void setIndex(int index) { this.index = index; } - - /** - * @param start_pc Specify range where the local variable is valid. - */ - public final void setStartPC(int start_pc) { - this.start_pc = start_pc; - } - - /** - * @return string representation. - */ - public final String toString() { - String name = getName(), signature = Utility.signatureToString(getSignature()); - - return "LocalVariable(start_pc = " + start_pc + ", length = " + length + - ", index = " + index + ":" + signature + " " + name + ")"; - } - - /** - * @return deep copy of this object - */ - public LocalVariable copy() { - try { - return (LocalVariable)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariableTable.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariableTable.java deleted file mode 100644 index 75a3180..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/LocalVariableTable.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents colection of local variables in a - * method. This attribute is contained in the Code attribute. - * - * @version $Id: LocalVariableTable.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Code - * @see LocalVariable - */ -public class LocalVariableTable extends Attribute { - private int local_variable_table_length; // Table of local - private LocalVariable[] local_variable_table; // variables - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public LocalVariableTable(LocalVariableTable c) { - this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), - c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool to `LocalVariableTable' - * @param length Content length in bytes - * @param local_variable_table Table of local variables - * @param constant_pool Array of constants - */ - public LocalVariableTable(int name_index, int length, - LocalVariable[] local_variable_table, - ConstantPool constant_pool) - { - super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool); - setLocalVariableTable(local_variable_table); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - LocalVariableTable(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (LocalVariable[])null, constant_pool); - - local_variable_table_length = (file.readUnsignedShort()); - local_variable_table = new LocalVariable[local_variable_table_length]; - - for(int i=0; i < local_variable_table_length; i++) - local_variable_table[i] = new LocalVariable(file, constant_pool); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitLocalVariableTable(this); - } - - /** - * Dump local variable table attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(local_variable_table_length); - for(int i=0; i < local_variable_table_length; i++) - local_variable_table[i].dump(file); - } - - /** - * @return Array of local variables of method. - */ - public final LocalVariable[] getLocalVariableTable() { - return local_variable_table; - } - - /** @return first matching variable using index - */ - public final LocalVariable getLocalVariable(int index) { - for(int i=0; i < local_variable_table_length; i++) - if(local_variable_table[i].getIndex() == index) - return local_variable_table[i]; - - return null; - } - - public final void setLocalVariableTable(LocalVariable[] local_variable_table) - { - this.local_variable_table = local_variable_table; - local_variable_table_length = (local_variable_table == null)? 0 : - local_variable_table.length; - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer(""); - - for(int i=0; i < local_variable_table_length; i++) { - buf.append(local_variable_table[i].toString()); - - if(i < local_variable_table_length - 1) - buf.append('\n'); - } - - return buf.toString(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - LocalVariableTable c = (LocalVariableTable)clone(); - - c.local_variable_table = new LocalVariable[local_variable_table_length]; - for(int i=0; i < local_variable_table_length; i++) - c.local_variable_table[i] = local_variable_table[i].copy(); - - c.constant_pool = constant_pool; - return c; - } - - public final int getTableLength() { return local_variable_table_length; } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Method.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Method.java deleted file mode 100644 index e608e7d..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Method.java +++ /dev/null @@ -1,228 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ -import org.apache.bcel.Constants; -import org.apache.bcel.generic.Type; -import java.io.*; - -/** - * This class represents the method info structure, i.e., the representation - * for a method in the class. See JVM specification for details. - * A method has access flags, a name, a signature and a number of attributes. - * - * @version $Id: Method.java,v 1.5 2002/12/08 16:04:37 mdahm Exp $ - * @author M. Dahm - */ -public final class Method extends FieldOrMethod { - /** - * Empty constructor, all attributes have to be defined via `setXXX' - * methods. Use at your own risk. - */ - public Method() {} - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Method(Method c) { - super(c); - } - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - * @throws ClassFormatException - */ - Method(DataInputStream file, ConstantPool constant_pool) - throws IOException, ClassFormatException - { - super(file, constant_pool); - } - - /** - * @param access_flags Access rights of method - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature - * @param attributes Collection of attributes - * @param constant_pool Array of constants - */ - public Method(int access_flags, int name_index, int signature_index, - Attribute[] attributes, ConstantPool constant_pool) - { - super(access_flags, name_index, signature_index, attributes, constant_pool); - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitMethod(this); - } - - /** - * @return Code attribute of method, if any - */ - public final Code getCode() { - for(int i=0; i < attributes_count; i++) - if(attributes[i] instanceof Code) - return (Code)attributes[i]; - - return null; - } - - /** - * @return ExceptionTable attribute of method, if any, i.e., list all - * exceptions the method may throw not exception handlers! - */ - public final ExceptionTable getExceptionTable() { - for(int i=0; i < attributes_count; i++) - if(attributes[i] instanceof ExceptionTable) - return (ExceptionTable)attributes[i]; - - return null; - } - - /** @return LocalVariableTable of code attribute if any, i.e. the call is forwarded - * to the Code atribute. - */ - public final LocalVariableTable getLocalVariableTable() { - Code code = getCode(); - - if(code != null) - return code.getLocalVariableTable(); - else - return null; - } - - /** @return LineNumberTable of code attribute if any, i.e. the call is forwarded - * to the Code atribute. - */ - public final LineNumberTable getLineNumberTable() { - Code code = getCode(); - - if(code != null) - return code.getLineNumberTable(); - else - return null; - } - - /** - * Return string representation close to declaration format, - * `public static void main(String[] args) throws IOException', e.g. - * - * @return String representation of the method. - */ - public final String toString() { - ConstantUtf8 c; - String name, signature, access; // Short cuts to constant pool - StringBuffer buf; - - access = Utility.accessToString(access_flags); - - // Get name and signature from constant pool - c = (ConstantUtf8)constant_pool.getConstant(signature_index, - Constants.CONSTANT_Utf8); - signature = c.getBytes(); - - c = (ConstantUtf8)constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8); - name = c.getBytes(); - - signature = Utility.methodSignatureToString(signature, name, access, true, - getLocalVariableTable()); - buf = new StringBuffer(signature); - - for(int i=0; i < attributes_count; i++) { - Attribute a = attributes[i]; - - if(!((a instanceof Code) || (a instanceof ExceptionTable))) - buf.append(" [" + a.toString() + "]"); - } - - ExceptionTable e = getExceptionTable(); - if(e != null) { - String str = e.toString(); - if(!str.equals("")) - buf.append("\n\t\tthrows " + str); - } - - return buf.toString(); - } - - /** - * @return deep copy of this method - */ - public final Method copy(ConstantPool constant_pool) { - return (Method)copy_(constant_pool); - } - - /** - * @return return type of method - */ - public Type getReturnType() { - return Type.getReturnType(getSignature()); - } - - /** - * @return array of method argument types - */ - public Type[] getArgumentTypes() { - return Type.getArgumentTypes(getSignature()); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Node.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Node.java deleted file mode 100644 index 2fd1a75..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Node.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -/** - * Denote class to have an accept method(); - * - * @version $Id: Node.java,v 1.1.1.1 2001/10/29 20:00:02 jvanzyl Exp $ - * @author M. Dahm - */ -public interface Node { - public void accept(Visitor obj); -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/PMGClass.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/PMGClass.java deleted file mode 100644 index db4fd63..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/PMGClass.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and represents a reference - * to a PMG - * attribute. - * - * @version $Id: PMGClass.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class PMGClass extends Attribute { - private int pmg_class_index, pmg_index; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public PMGClass(PMGClass c) { - this(c.getNameIndex(), c.getLength(), c.getPMGIndex(), c.getPMGClassIndex(), - c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - PMGClass(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), - constant_pool); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param constant_pool Array of constants - * @param PMGClass_index Index in constant pool to CONSTANT_Utf8 - */ - public PMGClass(int name_index, int length, int pmg_index, int pmg_class_index, - ConstantPool constant_pool) - { - super(Constants.ATTR_PMG, name_index, length, constant_pool); - this.pmg_index = pmg_index; - this.pmg_class_index = pmg_class_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - System.err.println("Visiting non-standard PMGClass object"); - } - - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(pmg_index); - file.writeShort(pmg_class_index); - } - - /** - * @return Index in constant pool of source file name. - */ - public final int getPMGClassIndex() { return pmg_class_index; } - - /** - * @param PMGClass_index. - */ - public final void setPMGClassIndex(int pmg_class_index) { - this.pmg_class_index = pmg_class_index; - } - - /** - * @return Index in constant pool of source file name. - */ - public final int getPMGIndex() { return pmg_index; } - - /** - * @param PMGClass_index. - */ - public final void setPMGIndex(int pmg_index) { - this.pmg_index = pmg_index; - } - - /** - * @return PMG name. - */ - public final String getPMGName() { - ConstantUtf8 c = (ConstantUtf8)constant_pool.getConstant(pmg_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return PMG class name. - */ - public final String getPMGClassName() { - ConstantUtf8 c = (ConstantUtf8)constant_pool.getConstant(pmg_class_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return String representation - */ - public final String toString() { - return "PMGClass(" + getPMGName() + ", " + getPMGClassName() + ")"; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - return (PMGClass)clone(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Signature.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Signature.java deleted file mode 100644 index 040d28f..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Signature.java +++ /dev/null @@ -1,296 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and represents a reference - * to a GJ attribute. - * - * @version $Id: Signature.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class Signature extends Attribute { - private int signature_index; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Signature(Signature c) { - this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - Signature(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, file.readUnsignedShort(), constant_pool); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param constant_pool Array of constants - * @param Signature_index Index in constant pool to CONSTANT_Utf8 - */ - public Signature(int name_index, int length, int signature_index, - ConstantPool constant_pool) - { - super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool); - this.signature_index = signature_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - System.err.println("Visiting non-standard Signature object"); - v.visitSignature(this); - } - - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(signature_index); - } - - /** - * @return Index in constant pool of source file name. - */ - public final int getSignatureIndex() { return signature_index; } - - /** - * @param Signature_index. - */ - public final void setSignatureIndex(int signature_index) { - this.signature_index = signature_index; - } - - /** - * @return GJ signature. - */ - public final String getSignature() { - ConstantUtf8 c = (ConstantUtf8)constant_pool.getConstant(signature_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * Extends ByteArrayInputStream to make 'unreading' chars possible. - */ - private static final class MyByteArrayInputStream extends ByteArrayInputStream { - MyByteArrayInputStream(String data) { super(data.getBytes()); } - final int mark() { return pos; } - final String getData() { return new String(buf); } - final void reset(int p) { pos = p; } - final void unread() { if(pos > 0) pos--; } - } - - private static boolean identStart(int ch) { - return ch == 'T' || ch == 'L'; - } - - private static boolean identPart(int ch) { - return ch == '/' || ch == ';'; - } - - private static final void matchIdent(MyByteArrayInputStream in, StringBuffer buf) { - int ch; - - if((ch = in.read()) == -1) - throw new RuntimeException("Illegal signature: " + in.getData() + - " no ident, reaching EOF"); - - //System.out.println("return from ident:" + (char)ch); - - if(!identStart(ch)) { - StringBuffer buf2 = new StringBuffer(); - - int count = 1; - while(Character.isJavaIdentifierPart((char)ch)) { - buf2.append((char)ch); - count++; - ch = in.read(); - } - - if(ch == ':') { // Ok, formal parameter - in.skip("Ljava/lang/Object".length()); - buf.append(buf2); - - ch = in.read(); - in.unread(); - //System.out.println("so far:" + buf2 + ":next:" +(char)ch); - } else { - for(int i=0; i < count; i++) - in.unread(); - } - - return; - } - - StringBuffer buf2 = new StringBuffer(); - ch = in.read(); - - do { - buf2.append((char)ch); - ch = in.read(); - //System.out.println("within ident:"+ (char)ch); - - } while((ch != -1) && (Character.isJavaIdentifierPart((char)ch) || (ch == '/'))); - - buf.append(buf2.toString().replace('/', '.')); - - //System.out.println("regular return ident:"+ (char)ch + ":" + buf2); - - if(ch != -1) - in.unread(); - } - - private static final void matchGJIdent(MyByteArrayInputStream in, - StringBuffer buf) - { - int ch; - - matchIdent(in, buf); - - ch = in.read(); - if((ch == '<') || ch == '(') { // Parameterized or method - //System.out.println("Enter <"); - buf.append((char)ch); - matchGJIdent(in, buf); - - while(((ch = in.read()) != '>') && (ch != ')')) { // List of parameters - if(ch == -1) - throw new RuntimeException("Illegal signature: " + in.getData() + - " reaching EOF"); - - //System.out.println("Still no >"); - buf.append(", "); - in.unread(); - matchGJIdent(in, buf); // Recursive call - } - - //System.out.println("Exit >"); - - buf.append((char)ch); - } else - in.unread(); - - ch = in.read(); - if(identStart(ch)) { - in.unread(); - matchGJIdent(in, buf); - } else if(ch == ')') { - in.unread(); - return; - } else if(ch != ';') - throw new RuntimeException("Illegal signature: " + in.getData() + " read " + - (char)ch); - } - - public static String translate(String s) { - //System.out.println("Sig:" + s); - StringBuffer buf = new StringBuffer(); - - matchGJIdent(new MyByteArrayInputStream(s), buf); - - return buf.toString(); - } - - public static final boolean isFormalParameterList(String s) { - return s.startsWith("<") && (s.indexOf(':') > 0); - } - - public static final boolean isActualParameterList(String s) { - return s.startsWith("L") && s.endsWith(">;"); - } - - /** - * @return String representation - */ - public final String toString() { - String s = getSignature(); - - return "Signature(" + s + ")"; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - return (Signature)clone(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/SourceFile.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/SourceFile.java deleted file mode 100644 index e70b854..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/SourceFile.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and represents a reference - * to the source file of this class. At most one SourceFile attribute - * should appear per classfile. The intention of this class is that it is - * instantiated from the Attribute.readAttribute() method. - * - * @version $Id: SourceFile.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class SourceFile extends Attribute { - private int sourcefile_index; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public SourceFile(SourceFile c) { - this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), - c.getConstantPool()); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - SourceFile(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, file.readUnsignedShort(), constant_pool); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8, which - * should represent the string "SourceFile". - * @param length Content length in bytes, the value should be 2. - * @param constant_pool The constant pool that this attribute is - * associated with. - * @param sourcefile_index Index in constant pool to CONSTANT_Utf8. This - * string will be interpreted as the name of the file from which this - * class was compiled. It will not be interpreted as indicating the name - * of the directory contqining the file or an absolute path; this - * information has to be supplied the consumer of this attribute - in - * many cases, the JVM. - */ - public SourceFile(int name_index, int length, int sourcefile_index, - ConstantPool constant_pool) - { - super(Constants.ATTR_SOURCE_FILE, name_index, length, constant_pool); - this.sourcefile_index = sourcefile_index; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitSourceFile(this); - } - - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(sourcefile_index); - } - - /** - * @return Index in constant pool of source file name. - */ - public final int getSourceFileIndex() { return sourcefile_index; } - - /** - * @param sourcefile_index. - */ - public final void setSourceFileIndex(int sourcefile_index) { - this.sourcefile_index = sourcefile_index; - } - - /** - * @return Source file name. - */ - public final String getSourceFileName() { - ConstantUtf8 c = (ConstantUtf8)constant_pool.getConstant(sourcefile_index, - Constants.CONSTANT_Utf8); - return c.getBytes(); - } - - /** - * @return String representation - */ - public final String toString() { - return "SourceFile(" + getSourceFileName() + ")"; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - return (SourceFile)clone(); - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMap.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMap.java deleted file mode 100644 index 1f48e11..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMap.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a stack map attribute used for - * preverification of Java classes for the Java 2 Micro Edition - * (J2ME). This attribute is used by the KVM and contained - * within the Code attribute of a method. See CLDC specification - * §5.3.1.2 - * - * @version $Id: StackMap.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Code - * @see StackMapEntry - * @see StackMapType - */ -public final class StackMap extends Attribute implements Node { - private int map_length; - private StackMapEntry[] map; // Table of stack map entries - - /* - * @param name_index Index of name - * @param length Content length in bytes - * @param map Table of stack map entries - * @param constant_pool Array of constants - */ - public StackMap(int name_index, int length, StackMapEntry[] map, - ConstantPool constant_pool) - { - super(Constants.ATTR_STACK_MAP, name_index, length, constant_pool); - - setStackMap(map); - } - - /** - * Construct object from file stream. - * @param name_index Index of name - * @param length Content length in bytes - * @param file Input stream - * @throws IOException - * @param constant_pool Array of constants - */ - StackMap(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (StackMapEntry[])null, constant_pool); - - map_length = file.readUnsignedShort(); - map = new StackMapEntry[map_length]; - - for(int i=0; i < map_length; i++) - map[i] = new StackMapEntry(file, constant_pool); - } - - /** - * Dump line number table attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - file.writeShort(map_length); - for(int i=0; i < map_length; i++) - map[i].dump(file); - } - - /** - * @return Array of stack map entries - */ - public final StackMapEntry[] getStackMap() { return map; } - - /** - * @param map Array of stack map entries - */ - public final void setStackMap(StackMapEntry[] map) { - this.map = map; - - map_length = (map == null)? 0 : map.length; - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer("StackMap("); - - for(int i=0; i < map_length; i++) { - buf.append(map[i].toString()); - - if(i < map_length - 1) - buf.append(", "); - } - - buf.append(')'); - - return buf.toString(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - StackMap c = (StackMap)clone(); - - c.map = new StackMapEntry[map_length]; - for(int i=0; i < map_length; i++) - c.map[i] = map[i].copy(); - - c.constant_pool = constant_pool; - return c; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitStackMap(this); - } - - public final int getMapLength() { return map_length; } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapEntry.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapEntry.java deleted file mode 100644 index 6d56e74..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapEntry.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents a stack map entry recording the types of - * local variables and the the of stack items at a given byte code offset. - * See CLDC specification §5.3.1.2 - * - * @version $Id: StackMapEntry.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see StackMap - * @see StackMapType - */ -public final class StackMapEntry implements Cloneable { - private int byte_code_offset; - private int number_of_locals; - private StackMapType[] types_of_locals; - private int number_of_stack_items; - private StackMapType[] types_of_stack_items; - private ConstantPool constant_pool; - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException - { - this(file.readShort(), file.readShort(), null, -1, null, constant_pool); - - types_of_locals = new StackMapType[number_of_locals]; - for(int i=0; i < number_of_locals; i++) - types_of_locals[i] = new StackMapType(file, constant_pool); - - number_of_stack_items = file.readShort(); - types_of_stack_items = new StackMapType[number_of_stack_items]; - for(int i=0; i < number_of_stack_items; i++) - types_of_stack_items[i] = new StackMapType(file, constant_pool); - } - - public StackMapEntry(int byte_code_offset, int number_of_locals, - StackMapType[] types_of_locals, - int number_of_stack_items, - StackMapType[] types_of_stack_items, - ConstantPool constant_pool) { - this.byte_code_offset = byte_code_offset; - this.number_of_locals = number_of_locals; - this.types_of_locals = types_of_locals; - this.number_of_stack_items = number_of_stack_items; - this.types_of_stack_items = types_of_stack_items; - this.constant_pool = constant_pool; - } - - /** - * Dump stack map entry - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeShort(byte_code_offset); - - file.writeShort(number_of_locals); - for(int i=0; i < number_of_locals; i++) - types_of_locals[i].dump(file); - - file.writeShort(number_of_stack_items); - for(int i=0; i < number_of_stack_items; i++) - types_of_stack_items[i].dump(file); - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer("(offset=" + byte_code_offset); - - if(number_of_locals > 0) { - buf.append(", locals={"); - - for(int i=0; i < number_of_locals; i++) { - buf.append(types_of_locals[i]); - if(i < number_of_locals - 1) - buf.append(", "); - } - - buf.append("}"); - } - - if(number_of_stack_items > 0) { - buf.append(", stack items={"); - - for(int i=0; i < number_of_stack_items; i++) { - buf.append(types_of_stack_items[i]); - if(i < number_of_stack_items - 1) - buf.append(", "); - } - - buf.append("}"); - } - - buf.append(")"); - - return buf.toString(); - } - - - public void setByteCodeOffset(int b) { byte_code_offset = b; } - public int getByteCodeOffset() { return byte_code_offset; } - public void setNumberOfLocals(int n) { number_of_locals = n; } - public int getNumberOfLocals() { return number_of_locals; } - public void setTypesOfLocals(StackMapType[] t) { types_of_locals = t; } - public StackMapType[] getTypesOfLocals() { return types_of_locals; } - public void setNumberOfStackItems(int n) { number_of_stack_items = n; } - public int getNumberOfStackItems() { return number_of_stack_items; } - public void setTypesOfStackItems(StackMapType[] t) { types_of_stack_items = t; } - public StackMapType[] getTypesOfStackItems() { return types_of_stack_items; } - - /** - * @return deep copy of this object - */ - public StackMapEntry copy() { - try { - return (StackMapEntry)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitStackMapEntry(this); - } - - /** - * @return Constant pool used by this object. - */ - public final ConstantPool getConstantPool() { return constant_pool; } - - /** - * @param constant_pool Constant pool to be used for this object. - */ - public final void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapType.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapType.java deleted file mode 100644 index 9cfcecc..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/StackMapType.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class represents the type of a local variable or item on stack - * used in the StackMap entries. - * - * @version $Id: StackMapType.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see StackMapEntry - * @see StackMap - * @see Constants - */ -public final class StackMapType implements Cloneable { - private byte type; - private int index = -1; // Index to CONSTANT_Class or offset - private ConstantPool constant_pool; - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - StackMapType(DataInputStream file, ConstantPool constant_pool) throws IOException - { - this(file.readByte(), -1, constant_pool); - - if(hasIndex()) - setIndex(file.readShort()); - - setConstantPool(constant_pool); - } - - /** - * @param type type tag as defined in the Constants interface - * @param index index to constant pool, or byte code offset - */ - public StackMapType(byte type, int index, ConstantPool constant_pool) { - setType(type); - setIndex(index); - setConstantPool(constant_pool); - } - - public void setType(byte t) { - if((t < Constants.ITEM_Bogus) || (t > Constants.ITEM_NewObject)) - throw new RuntimeException("Illegal type for StackMapType: " + t); - type = t; - } - - public byte getType() { return type; } - public void setIndex(int t) { index = t; } - - /** @return index to constant pool if type == ITEM_Object, or offset - * in byte code, if type == ITEM_NewObject, and -1 otherwise - */ - public int getIndex() { return index; } - - /** - * Dump type entries to file. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(type); - if(hasIndex()) - file.writeShort(getIndex()); - } - - /** @return true, if type is either ITEM_Object or ITEM_NewObject - */ - public final boolean hasIndex() { - return ((type == Constants.ITEM_Object) || - (type == Constants.ITEM_NewObject)); - } - - private String printIndex() { - if(type == Constants.ITEM_Object) - return ", class=" + constant_pool.constantToString(index, Constants.CONSTANT_Class); - else if(type == Constants.ITEM_NewObject) - return ", offset=" + index; - else - return ""; - } - - /** - * @return String representation - */ - public final String toString() { - return "(type=" + Constants.ITEM_NAMES[type] + printIndex() + ")"; - } - - /** - * @return deep copy of this object - */ - public StackMapType copy() { - try { - return (StackMapType)clone(); - } catch(CloneNotSupportedException e) {} - - return null; - } - - /** - * @return Constant pool used by this object. - */ - public final ConstantPool getConstantPool() { return constant_pool; } - - /** - * @param constant_pool Constant pool to be used for this object. - */ - public final void setConstantPool(ConstantPool constant_pool) { - this.constant_pool = constant_pool; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Synthetic.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Synthetic.java deleted file mode 100644 index e6ada23..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Synthetic.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; - -/** - * This class is derived from Attribute and declares this class as - * `synthetic', i.e., it needs special handling. The JVM specification - * states "A class member that does not appear in the source code must be - * marked using a Synthetic attribute." It may appear in the ClassFile - * attribute table, a field_info table or a method_info table. This class - * is intended to be instantiated from the - * Attribute.readAttribute() method. - * - * @version $Id: Synthetic.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @author M. Dahm - * @see Attribute - */ -public final class Synthetic extends Attribute { - private byte[] bytes; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public Synthetic(Synthetic c) { - this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8, which - * should represent the string "Synthetic". - * @param length Content length in bytes - should be zero. - * @param bytes Attribute contents - * @param constant_pool The constant pool this attribute is associated - * with. - */ - public Synthetic(int name_index, int length, byte[] bytes, - ConstantPool constant_pool) - { - super(Constants.ATTR_SYNTHETIC, name_index, length, constant_pool); - this.bytes = bytes; - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - Synthetic(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) throws IOException - { - this(name_index, length, (byte [])null, constant_pool); - - if(length > 0) { - bytes = new byte[length]; - file.readFully(bytes); - System.err.println("Synthetic attribute with length > 0"); - } - } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitSynthetic(this); - } - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - if(length > 0) - file.write(bytes, 0, length); - } - /** - * @return data bytes. - */ - public final byte[] getBytes() { return bytes; } - - /** - * @param bytes. - */ - public final void setBytes(byte[] bytes) { - this.bytes = bytes; - } - - /** - * @return String representation. - */ - public final String toString() { - StringBuffer buf = new StringBuffer("Synthetic"); - - if(length > 0) - buf.append(" " + Utility.toHexString(bytes)); - - return buf.toString(); - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - Synthetic c = (Synthetic)clone(); - - if(bytes != null) - c.bytes = (byte[])bytes.clone(); - - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Unknown.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Unknown.java deleted file mode 100644 index b3b31b8..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Unknown.java +++ /dev/null @@ -1,213 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import java.io.*; -import java.util.*; - -/** - * This class represents a reference to an unknown (i.e., - * application-specific) attribute of a class. It is instantiated from the - * Attribute.readAttribute() method. Applications that need to - * read in application-specific attributes should create an AttributeReader implementation and - * attach it via Attribute.addAttributeReader. - - * - * @version $Id: Unknown.java,v 1.3 2002/03/11 16:16:35 mdahm Exp $ - * @see org.apache.bcel.classfile.Attribute - * @see org.apache.bcel.classfile.AttributeReader - * @author M. Dahm - */ -public final class Unknown extends Attribute { - private byte[] bytes; - private String name; - - private static HashMap unknown_attributes = new HashMap(); - - /** @return array of unknown attributes, but just one for each kind. - */ - static Unknown[] getUnknownAttributes() { - Unknown[] unknowns = new Unknown[unknown_attributes.size()]; - Iterator entries = unknown_attributes.values().iterator(); - - for(int i=0; entries.hasNext(); i++) - unknowns[i] = (Unknown)entries.next(); - - unknown_attributes.clear(); - return unknowns; - } - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Unknown(Unknown c) { - this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); - } - - /** - * Create a non-standard attribute. - * - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param bytes Attribute contents - * @param constant_pool Array of constants - */ - public Unknown(int name_index, int length, byte[] bytes, - ConstantPool constant_pool) - { - super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool); - this.bytes = bytes; - - name = ((ConstantUtf8)constant_pool.getConstant(name_index, - Constants.CONSTANT_Utf8)).getBytes(); - unknown_attributes.put(name, this); - } - - /** - * Construct object from file stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param file Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - Unknown(int name_index, int length, DataInputStream file, - ConstantPool constant_pool) - throws IOException - { - this(name_index, length, (byte [])null, constant_pool); - - if(length > 0) { - bytes = new byte[length]; - file.readFully(bytes); - } - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(Visitor v) { - v.visitUnknown(this); - } - /** - * Dump unknown bytes to file stream. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - super.dump(file); - if(length > 0) - file.write(bytes, 0, length); - } - /** - * @return data bytes. - */ - public final byte[] getBytes() { return bytes; } - - /** - * @return name of attribute. - */ - public final String getName() { return name; } - - /** - * @param bytes. - */ - public final void setBytes(byte[] bytes) { - this.bytes = bytes; - } - - /** - * @return String representation. - */ - public final String toString() { - if(length == 0 || bytes == null) - return "(Unknown attribute " + name + ")"; - - String hex; - if(length > 10) { - byte[] tmp = new byte[10]; - System.arraycopy(bytes, 0, tmp, 0, 10); - hex = Utility.toHexString(tmp) + "... (truncated)"; - } - else - hex = Utility.toHexString(bytes); - - return "(Unknown attribute " + name + ": " + hex + ")"; - } - - /** - * @return deep copy of this attribute - */ - public Attribute copy(ConstantPool constant_pool) { - Unknown c = (Unknown)clone(); - - if(bytes != null) - c.bytes = (byte[])bytes.clone(); - - c.constant_pool = constant_pool; - return c; - } -} diff --git a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Utility.java b/external/bcel-5.1/src/java/org/apache/bcel/classfile/Utility.java deleted file mode 100644 index d1f186d..0000000 --- a/external/bcel-5.1/src/java/org/apache/bcel/classfile/Utility.java +++ /dev/null @@ -1,1416 +0,0 @@ -package org.apache.bcel.classfile; - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" and - * "Apache BCEL" must not be used to endorse or promote products - * derived from this software without prior written permission. For - * written permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * "Apache BCEL", nor may "Apache" appear in their name, without - * prior written permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -import org.apache.bcel.Constants; -import org.apache.bcel.util.ByteSequence; -import java.io.*; -import java.util.ArrayList; -import java.util.zip.*; - -/** - * Utility functions that do not really belong to any class in particular. - * - * @version $Id: Utility.java,v 1.6 2003/05/23 07:55:12 mdahm Exp $ - * @author M. Dahm - */ -public abstract class Utility { - - private static int unwrap(ThreadLocal tl) { - return ((Integer)tl.get()).intValue(); - } - - private static void wrap(ThreadLocal tl, int value) { - tl.set(new Integer(value)); - } - - private static ThreadLocal consumed_chars = new ThreadLocal() { - protected Object initialValue() { - return new Integer(0); - } - };/* How many chars have been consumed - * during parsing in signatureToString(). - * Read by methodSignatureToString(). - * Set by side effect,but only internally. - */ - - private static boolean wide=false; /* The `WIDE' instruction is used in the - * byte code to allow 16-bit wide indices - * for local variables. This opcode - * precedes an `ILOAD', e.g.. The opcode - * immediately following takes an extra - * byte which is combined with the - * following byte to form a - * 16-bit value. - */ - /** - * Convert bit field of flags into string such as `static final'. - * - * @param access_flags Access flags - * @return String representation of flags - */ - public static final String accessToString(int access_flags) { - return accessToString(access_flags, false); - } - - /** - * Convert bit field of flags into string such as `static final'. - * - * Special case: Classes compiled with new compilers and with the - * `ACC_SUPER' flag would be said to be "synchronized". This is - * because SUN used the same value for the flags `ACC_SUPER' and - * `ACC_SYNCHRONIZED'. - * - * @param access_flags Access flags - * @param for_class access flags are for class qualifiers ? - * @return String representation of flags - */ - public static final String accessToString(int access_flags, - boolean for_class) - { - StringBuffer buf = new StringBuffer(); - - int p = 0; - for(int i=0; p < Constants.MAX_ACC_FLAG; i++) { // Loop through known flags - p = pow2(i); - - if((access_flags & p) != 0) { - /* Special case: Classes compiled with new compilers and with the - * `ACC_SUPER' flag would be said to be "synchronized". This is - * because SUN used the same value for the flags `ACC_SUPER' and - * `ACC_SYNCHRONIZED'. - */ - if(for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE))) - continue; - - buf.append(Constants.ACCESS_NAMES[i] + " "); - } - } - - return buf.toString().trim(); - } - - /** - * @return "class" or "interface", depending on the ACC_INTERFACE flag - */ - public static final String classOrInterface(int access_flags) { - return ((access_flags & Constants.ACC_INTERFACE) != 0)? "interface" : "class"; - } - - /** - * Disassemble a byte array of JVM byte codes starting from code line - * `index' and return the disassembled string representation. Decode only - * `num' opcodes (including their operands), use -1 if you want to - * decompile everything. - * - * @param code byte code array - * @param constant_pool Array of constants - * @param index offset in `code' array - * (number of opcodes, not bytes!) - * @param length number of opcodes to decompile, -1 for all - * @param verbose be verbose, e.g. print constant pool index - * @return String representation of byte codes - */ - public static final String codeToString(byte[] code, - ConstantPool constant_pool, - int index, int length, boolean verbose) - { - StringBuffer buf = new StringBuffer(code.length * 20); // Should be sufficient - ByteSequence stream = new ByteSequence(code); - - try { - for(int i=0; i < index; i++) // Skip `index' lines of code - codeToString(stream, constant_pool, verbose); - - for(int i=0; stream.available() > 0; i++) { - if((length < 0) || (i < length)) { - String indices = fillup(stream.getIndex() + ":", 6, true, ' '); - buf.append(indices + codeToString(stream, constant_pool, verbose) + '\n'); - } - } - } catch(IOException e) { - System.out.println(buf.toString()); - e.printStackTrace(); - throw new ClassFormatException("Byte code error: " + e); - } - - return buf.toString(); - } - - public static final String codeToString(byte[] code, - ConstantPool constant_pool, - int index, int length) { - return codeToString(code, constant_pool, index, length, true); - } - - /** - * Disassemble a stream of byte codes and return the - * string representation. - * - * @param bytes stream of bytes - * @param constant_pool Array of constants - * @param verbose be verbose, e.g. print constant pool index - * @return String representation of byte code - */ - public static final String codeToString(ByteSequence bytes, - ConstantPool constant_pool, boolean verbose) - throws IOException - { - short opcode = (short)bytes.readUnsignedByte(); - int default_offset=0, low, high, npairs; - int index, vindex, constant; - int[] match, jump_table; - int no_pad_bytes=0, offset; - StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]); - - /* Special case: Skip (0-3) padding bytes, i.e., the - * following bytes are 4-byte-aligned - */ - if((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) { - int remainder = bytes.getIndex() % 4; - no_pad_bytes = (remainder == 0)? 0 : 4 - remainder; - - for(int i=0; i < no_pad_bytes; i++) { - byte b; - - if((b=bytes.readByte()) != 0) - System.err.println("Warning: Padding byte != 0 in " + - Constants.OPCODE_NAMES[opcode] + ":" + b); - } - - // Both cases have a field default_offset in hardware - default_offset = bytes.readInt(); - } - - switch(opcode) { - /* Table switch has variable length arguments. - */ - case Constants.TABLESWITCH: - low = bytes.readInt(); - high = bytes.readInt(); - - offset = bytes.getIndex() - 12 - no_pad_bytes - 1; - default_offset += offset; - - buf.append("\tdefault = " + default_offset + ", low = " + low + - ", high = " + high + "("); - - jump_table = new int[high - low + 1]; - for(int i=0; i < jump_table.length; i++) { - jump_table[i] = offset + bytes.readInt(); - buf.append(jump_table[i]); - - if(i < jump_table.length - 1) - buf.append(", "); - } - buf.append(")"); - - break; - - /* Lookup switch has variable length arguments. - */ - case Constants.LOOKUPSWITCH: { - - npairs = bytes.readInt(); - offset = bytes.getIndex() - 8 - no_pad_bytes - 1; - - match = new int[npairs]; - jump_table = new int[npairs]; - default_offset += offset; - - buf.append("\tdefault = " + default_offset + ", npairs = " + npairs + - " ("); - - for(int i=0; i < npairs; i++) { - match[i] = bytes.readInt(); - - jump_table[i] = offset + bytes.readInt(); - - buf.append("(" + match[i] + ", " + jump_table[i] + ")"); - - if(i < npairs - 1) - buf.append(", "); - } - buf.append(")"); - } - break; - - /* Two address bytes + offset from start of byte stream form the - * jump target - */ - case Constants.GOTO: case Constants.IFEQ: case Constants.IFGE: case Constants.IFGT: - case Constants.IFLE: case Constants.IFLT: case Constants.JSR: case Constants.IFNE: - case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IF_ACMPEQ: - case Constants.IF_ACMPNE: case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT: - case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE: - buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readShort())); - break; - - /* 32-bit wide jumps - */ - case Constants.GOTO_W: case Constants.JSR_W: - buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readInt())); - break; - - /* Index byte references local variable (register) - */ - case Constants.ALOAD: case Constants.ASTORE: case Constants.DLOAD: case Constants.DSTORE: case Constants.FLOAD: - case Constants.FSTORE: case Constants.ILOAD: case Constants.ISTORE: case Constants.LLOAD: case Constants.LSTORE: - case Constants.RET: - if(wide) { - vindex = bytes.readUnsignedShort(); - wide=false; // Clear flag - } - else - vindex = bytes.readUnsignedByte(); - - buf.append("\t\t%" + vindex); - break; - - /* - * Remember wide byte which is used to form a 16-bit address in the - * following instruction. Relies on that the method is called again with - * the following opcode. - */ - case Constants.WIDE: - wide = true; - buf.append("\t(wide)"); - break; - - /* Array of basic type. - */ - case Constants.NEWARRAY: - buf.append("\t\t<" + Constants.TYPE_NAMES[bytes.readByte()] + ">"); - break; - - /* Access object/class fields. - */ - case Constants.GETFIELD: case Constants.GETSTATIC: case Constants.PUTFIELD: case Constants.PUTSTATIC: - index = bytes.readUnsignedShort(); - buf.append("\t\t" + - constant_pool.constantToString(index, Constants.CONSTANT_Fieldref) + - (verbose? " (" + index + ")" : "")); - break; - - /* Operands are references to classes in constant pool - */ - case Constants.NEW: - case Constants.CHECKCAST: - buf.append("\t"); - case Constants.INSTANCEOF: - index = bytes.readUnsignedShort(); - buf.append("\t<" + constant_pool.constantToString(index, - Constants.CONSTANT_Class) + - ">" + (verbose? " (" + index + ")" : "")); - break; - - /* Operands are references to methods in constant pool - */ - case Constants.INVOKESPECIAL: case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL: - index = bytes.readUnsignedShort(); - buf.append("\t" + constant_pool.constantToString(index, - Constants.CONSTANT_Methodref) + - (verbose? " (" + index + ")" : "")); - break; - - case Constants.INVOKEINTERFACE: - index = bytes.readUnsignedShort(); - int nargs = bytes.readUnsignedByte(); // historical, redundant - buf.append("\t" + - constant_pool.constantToString(index, - Constants.CONSTANT_InterfaceMethodref) + - (verbose? " (" + index + ")\t" : "") + nargs + "\t" + - bytes.readUnsignedByte()); // Last byte is a reserved space - break; - - /* Operands are references to items in constant pool - */ - case Constants.LDC_W: case Constants.LDC2_W: - index = bytes.readUnsignedShort(); - - buf.append("\t\t" + constant_pool.constantToString - (index, constant_pool.getConstant(index).getTag()) + - (verbose? " (" + index + ")" : "")); - break; - - case Constants.LDC: - index = bytes.readUnsignedByte(); - - buf.append("\t\t" + - constant_pool.constantToString - (index, constant_pool.getConstant(index).getTag()) + - (verbose? " (" + index + ")" : "")); - break; - - /* Array of references. - */ - case Constants.ANEWARRAY: - index = bytes.readUnsignedShort(); - - buf.append("\t\t<" + compactClassName(constant_pool.getConstantString - (index, Constants.CONSTANT_Class), false) + - ">" + (verbose? " (" + index + ")": "")); - break; - - /* Multidimensional array of references. - */ - case Constants.MULTIANEWARRAY: { - index = bytes.readUnsignedShort(); - int dimensions = bytes.readUnsignedByte(); - - buf.append("\t<" + compactClassName(constant_pool.getConstantString - (index, Constants.CONSTANT_Class), false) + - ">\t" + dimensions + (verbose? " (" + index + ")" : "")); - } - break; - - /* Increment local variable. - */ - case Constants.IINC: - if(wide) { - vindex = bytes.readUnsignedShort(); - constant = bytes.readShort(); - wide = false; - } - else { - vindex = bytes.readUnsignedByte(); - constant = bytes.readByte(); - } - buf.append("\t\t%" + vindex + "\t" + constant); - break; - - default: - if(Constants.NO_OF_OPERANDS[opcode] > 0) { - for(int i=0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) { - buf.append("\t\t"); - switch(Constants.TYPE_OF_OPERANDS[opcode][i]) { - case Constants.T_BYTE: buf.append(bytes.readByte()); break; - case Constants.T_SHORT: buf.append(bytes.readShort()); break; - case Constants.T_INT: buf.append(bytes.readInt()); break; - - default: // Never reached - System.err.println("Unreachable default case reached!"); - System.exit(-1); - } - } - } - } - - return buf.toString(); - } - - public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool) - throws IOException - { - return codeToString(bytes, constant_pool, true); - } - - /** - * Shorten long class names, java/lang/String becomes - * String. - * - * @param str The long class name - * @return Compacted class name - */ - public static final String compactClassName(String str) { - return compactClassName(str, true); - } - - /** - * Shorten long class name str, i.e., chop off the prefix, - * if the - * class name starts with this string and the flag chopit is true. - * Slashes / are converted to dots .. - * - * @param str The long class name - * @param prefix The prefix the get rid off - * @param chopit Flag that determines whether chopping is executed or not - * @return Compacted class name - */ - public static final String compactClassName(String str, - String prefix, - boolean chopit) - { - int len = prefix.length(); - - str = str.replace('/', '.'); // Is `/' on all systems, even DOS - - if(chopit) { - // If string starts with `prefix' and contains no further dots - if(str.startsWith(prefix) && - (str.substring(len).indexOf('.') == -1)) - str = str.substring(len); - } - - return str; - } - - /** - * Shorten long class names, java/lang/String becomes - * java.lang.String, - * e.g.. If chopit is true the prefix java.lang - * is also removed. - * - * @param str The long class name - * @param chopit Flag that determines whether chopping is executed or not - * @return Compacted class name - */ - public static final String compactClassName(String str, boolean chopit) { - return compactClassName(str, "java.lang.", chopit); - } - - private static final boolean is_digit(char ch) { - return (ch >= '0') && (ch <= '9'); - } - - private static final boolean is_space(char ch) { - return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); - } - - /** - * @return `flag' with bit `i' set to 1 - */ - public static final int setBit(int flag, int i) { - return flag | pow2(i); - } - - /** - * @return `flag' with bit `i' set to 0 - */ - public static final int clearBit(int flag, int i) { - int bit = pow2(i); - return (flag & bit) == 0? flag : flag ^ bit; - } - - /** - * @return true, if bit `i' in `flag' is set - */ - public static final boolean isSet(int flag, int i) { - return (flag & pow2(i)) != 0; - } - - /** - * Converts string containing the method return and argument types - * to a byte code method signature. - * - * @param ret Return type of method - * @param argv Types of method arguments - * @return Byte code representation of method signature - */ - public final static String methodTypeToSignature(String ret, String[] argv) - throws ClassFormatException - { - StringBuffer buf = new StringBuffer("("); - String str; - - if(argv != null) - for(int i=0; i < argv.length; i++) { - str = getSignature(argv[i]); - - if(str.endsWith("V")) // void can't be a method argument - throw new ClassFormatException("Invalid type: " + argv[i]); - - buf.append(str); - } - - str = getSignature(ret); - - buf.append(")" + str); - - return buf.toString(); - } - - /** - * @param signature Method signature - * @return Array of argument types - * @throws ClassFormatException - */ - public static final String[] methodSignatureArgumentTypes(String signature) - throws ClassFormatException - { - return methodSignatureArgumentTypes(signature, true); - } - - /** - * @param signature Method signature - * @param chopit Shorten class names ? - * @return Array of argument types - * @throws ClassFormatException - */ - public static final String[] methodSignatureArgumentTypes(String signature, - boolean chopit) - throws ClassFormatException - { - ArrayList vec = new ArrayList(); - int index; - String[] types; - - try { // Read all declarations between for `(' and `)' - if(signature.charAt(0) != '(') - throw new ClassFormatException("Invalid method signature: " + signature); - - index = 1; // current string position - - while(signature.charAt(index) != ')') { - vec.add(signatureToString(signature.substring(index), chopit)); - //corrected concurrent private static field acess - index += unwrap(consumed_chars); // update position - } - } catch(StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature); - } - - types = new String[vec.size()]; - vec.toArray(types); - return types; - } - /** - * @param signature Method signature - * @return return type of method - * @throws ClassFormatException - */ - public static final String methodSignatureReturnType(String signature) - throws ClassFormatException - { - return methodSignatureReturnType(signature, true); - } - /** - * @param signature Method signature - * @param chopit Shorten class names ? - * @return return type of method - * @throws ClassFormatException - */ - public static final String methodSignatureReturnType(String signature, - boolean chopit) - throws ClassFormatException - { - int index; - String type; - - try { - // Read return type after `)' - index = signature.lastIndexOf(')') + 1; - type = signatureToString(signature.substring(index), chopit); - } catch(StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature); - } - - return type; - } - - /** - * Converts method signature to string with all class names compacted. - * - * @param signature to convert - * @param name of method - * @param access flags of method - * @return Human readable signature - */ - public static final String methodSignatureToString(String signature, - String name, - String access) { - return methodSignatureToString(signature, name, access, true); - } - - public static final String methodSignatureToString(String signature, - String name, - String access, - boolean chopit) { - return methodSignatureToString(signature, name, access, chopit, null); - } - - /** - * A return­type signature represents the return value from a method. - * It is a series of bytes in the following grammar: - * - * ::= | V - * - * The character V indicates that the method returns no value. Otherwise, the - * signature indicates the type of the return value. - * An argument signature represents an argument passed to a method: - * - * ::= - * - * A method signature represents the arguments that the method expects, and - * the value that it returns. - * ::= () - * ::= * - * - * This method converts such a string into a Java type declaration like - * `void main(String[])' and throws a `ClassFormatException' when the parsed - * type is invalid. - * - * @param signature Method signature - * @param name Method name - * @param access Method access rights - * @return Java type declaration - * @throws ClassFormatException - */ - public static final String methodSignatureToString(String signature, - String name, - String access, - boolean chopit, - LocalVariableTable vars) - throws ClassFormatException - { - StringBuffer buf = new StringBuffer("("); - String type; - int index; - int var_index = (access.indexOf("static") >= 0)? 0 : 1; - - try { // Read all declarations between for `(' and `)' - if(signature.charAt(0) != '(') - throw new ClassFormatException("Invalid method signature: " + signature); - - index = 1; // current string position - - while(signature.charAt(index) != ')') { - String param_type = signatureToString(signature.substring(index), chopit); - buf.append(param_type); - - if(vars != null) { - LocalVariable l = vars.getLocalVariable(var_index); - - if(l != null) - buf.append(" " + l.getName()); - } else - buf.append(" arg" + var_index); - - if("double".equals(param_type) || "long".equals(param_type)) - var_index += 2; - else - var_index++; - - buf.append(", "); - //corrected concurrent private static field acess - index += unwrap(consumed_chars); // update position - } - - index++; // update position - - // Read return type after `)' - type = signatureToString(signature.substring(index), chopit); - - } catch(StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature); - } - - if(buf.length() > 1) // Tack off the extra ", " - buf.setLength(buf.length() - 2); - - buf.append(")"); - - return access + ((access.length() > 0)? " " : "") + // May be an empty string - type + " " + name + buf.toString(); - } - - // Guess what this does - private static final int pow2(int n) { - return 1 << n; - } - - /** - * Replace all occurences of old in str with new. - * - * @param str String to permute - * @param old String to be replaced - * @param new Replacement string - * @return new String object - */ - public static final String replace(String str, String old, String new_) { - int index, old_index; - StringBuffer buf = new StringBuffer(); - - try { - if((index = str.indexOf(old)) != -1) { // `old' found in str - old_index = 0; // String start offset - - // While we have something to replace - while((index = str.indexOf(old, old_index)) != -1) { - buf.append(str.substring(old_index, index)); // append prefix - buf.append(new_); // append replacement - - old_index = index + old.length(); // Skip `old'.length chars - } - - buf.append(str.substring(old_index)); // append rest of string - str = buf.toString(); - } - } catch(StringIndexOutOfBoundsException e) { // Should not occur - System.err.println(e); - } - - return str; - } - - /** - * Converts signature to string with all class names compacted. - * - * @param signature to convert - * @return Human readable signature - */ - public static final String signatureToString(String signature) { - return signatureToString(signature, true); - } - - /** - * The field signature represents the value of an argument to a function or - * the value of a variable. It is a series of bytes generated by the - * following grammar: - * - *

-   *  ::= 
-   *       ::= ||
-   *        ::= B|C|D|F|I|J|S|Z
-   *      ::= L;
-   *       ::= [
-   *
-   * The meaning of the base types is as follows:
-   * B byte signed byte
-   * C char character
-   * D double double precision IEEE float
-   * F float single precision IEEE float
-   * I int integer
-   * J long long integer
-   * L; ... an object of the given class
-   * S short signed short
-   * Z boolean true or false
-   * [ ... array
-   * 
- * - * This method converts this string into a Java type declaration such as - * `String[]' and throws a `ClassFormatException' when the parsed type is - * invalid. - * - * @param signature Class signature - * @param chopit Flag that determines whether chopping is executed or not - * @return Java type declaration - * @throws ClassFormatException - */ - public static final String signatureToString(String signature, - boolean chopit) - { - //corrected concurrent private static field acess - wrap(consumed_chars, 1); // This is the default, read just one char like `B' - - try { - switch(signature.charAt(0)) { - case 'B' : return "byte"; - case 'C' : return "char"; - case 'D' : return "double"; - case 'F' : return "float"; - case 'I' : return "int"; - case 'J' : return "long"; - - case 'L' : { // Full class name - int index = signature.indexOf(';'); // Look for closing `;' - - if(index < 0) - throw new ClassFormatException("Invalid signature: " + signature); - - //corrected concurrent private static field acess - wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed - - return compactClassName(signature.substring(1, index), chopit); - } - - case 'S' : return "short"; - case 'Z' : return "boolean"; - - case '[' : { // Array declaration - int n; - StringBuffer buf, brackets; - String type; - char ch; - int consumed_chars; // Shadows global var - - brackets = new StringBuffer(); // Accumulate []'s - - // Count opening brackets and look for optional size argument - for(n=0; signature.charAt(n) == '['; n++) - brackets.append("[]"); - - consumed_chars = n; // Remember value - - // The rest of the string denotes a `' - type = signatureToString(signature.substring(n), chopit); - - //corrected concurrent private static field acess - //Utility.consumed_chars += consumed_chars; is replaced by: - int _temp = unwrap(Utility.consumed_chars)+consumed_chars; - wrap(Utility.consumed_chars, _temp); - - return type + brackets.toString(); - } - - case 'V' : return "void"; - - default : throw new ClassFormatException("Invalid signature: `" + - signature + "'"); - } - } catch(StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid signature: " + e + ":" + signature); - } - } - - /** Parse Java type such as "char", or "java.lang.String[]" and return the - * signature in byte code format, e.g. "C" or "[Ljava/lang/String;" respectively. - * - * @param type Java type - * @return byte code signature - */ - public static String getSignature(String type) { - StringBuffer buf = new StringBuffer(); - char[] chars = type.toCharArray(); - boolean char_found = false, delim = false; - int index = -1; - - loop: - for(int i=0; i < chars.length; i++) { - switch(chars[i]) { - case ' ': case '\t': case '\n': case '\r': case '\f': - if(char_found) - delim = true; - break; - - case '[': - if(!char_found) - throw new RuntimeException("Illegal type: " + type); - - index = i; - break loop; - - default: - char_found = true; - if(!delim) - buf.append(chars[i]); - } - } - - int brackets = 0; - - if(index > 0) - brackets = countBrackets(type.substring(index)); - - type = buf.toString(); - buf.setLength(0); - - for(int i=0; i < brackets; i++) - buf.append('['); - - boolean found = false; - - for(int i=Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) { - if(Constants.TYPE_NAMES[i].equals(type)) { - found = true; - buf.append(Constants.SHORT_TYPE_NAMES[i]); - } - } - - if(!found) // Class name - buf.append('L' + type.replace('.', '/') + ';'); - - return buf.toString(); - } - - private static int countBrackets(String brackets) { - char[] chars = brackets.toCharArray(); - int count = 0; - boolean open = false; - - for(int i=0; iConstants - * - * @param signature in format described above - * @return type of method signature - * @see Constants - */ - public static final byte typeOfMethodSignature(String signature) - throws ClassFormatException - { - int index; - - try { - if(signature.charAt(0) != '(') - throw new ClassFormatException("Invalid method signature: " + signature); - - index = signature.lastIndexOf(')') + 1; - return typeOfSignature(signature.substring(index)); - } catch(StringIndexOutOfBoundsException e) { - throw new ClassFormatException("Invalid method signature: " + signature); - } - } - - /** - * Return type of signature as a byte value as defined in Constants - * - * @param signature in format described above - * @return type of signature - * @see Constants - */ - public static final byte typeOfSignature(String signature) - throws ClassFormatException - { - try { - switch(signature.charAt(0)) { - case 'B' : return Constants.T_BYTE; - case 'C' : return Constants.T_CHAR; - case 'D' : return Constants.T_DOUBLE; - case 'F' : return Constants.T_FLOAT; - case 'I' : return Constants.T_INT; - case 'J' : return Constants.T_LONG; - case 'L' : return Constants.T_REFERENCE; - case '[' : return Constants.T_ARRAY; - case 'V' : return Constants.T_VOID; - case 'Z' : return Constants.T_BOOLEAN; - case 'S' : return Constants.T_SHORT; - default: - throw new ClassFormatException("Invalid method signature: " + signature); - } - } catch(StringIndexOutOfBoundsException e) { - throw new ClassFormatException("Invalid method signature: " + signature); - } - } - - /** Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload" - */ - public static short searchOpcode(String name) { - name = name.toLowerCase(); - - for(short i=0; i < Constants.OPCODE_NAMES.length; i++) - if(Constants.OPCODE_NAMES[i].equals(name)) - return i; - - return -1; - } - - /** - * Convert (signed) byte to (unsigned) short value, i.e., all negative - * values become positive. - */ - private static final short byteToShort(byte b) { - return (b < 0)? (short)(256 + b) : (short)b; - } - - /** Convert bytes into hexidecimal string - * - * @return bytes as hexidecimal string, e.g. 00 FA 12 ... - */ - public static final String toHexString(byte[] bytes) { - StringBuffer buf = new StringBuffer(); - - for(int i=0; i < bytes.length; i++) { - short b = byteToShort(bytes[i]); - String hex = Integer.toString(b, 0x10); - - if(b < 0x10) // just one digit, prepend '0' - buf.append('0'); - - buf.append(hex); - - if(i < bytes.length - 1) - buf.append(' '); - } - - return buf.toString(); - } - - /** - * Return a string for an integer justified left or right and filled up with - * `fill' characters if necessary. - * - * @param i integer to format - * @param length length of desired string - * @param left_justify format left or right - * @param fill fill character - * @return formatted int - */ - public static final String format(int i, int length, boolean left_justify, char fill) { - return fillup(Integer.toString(i), length, left_justify, fill); - } - - /** - * Fillup char with up to length characters with char `fill' and justify it left or right. - * - * @param str string to format - * @param length length of desired string - * @param left_justify format left or right - * @param fill fill character - * @return formatted string - */ - public static final String fillup(String str, int length, boolean left_justify, char fill) { - int len = length - str.length(); - char[] buf = new char[(len < 0)? 0 : len]; - - for(int j=0; j < buf.length; j++) - buf[j] = fill; - - if(left_justify) - return str + new String(buf); - else - return new String(buf) + str; - } - - static final boolean equals(byte[] a, byte[] b) { - int size; - - if((size=a.length) != b.length) - return false; - - for(int i=0; i < size; i++) - if(a[i] != b[i]) - return false; - - return true; - } - - public static final void printArray(PrintStream out, Object[] obj) { - out.println(printArray(obj, true)); - } - - public static final void printArray(PrintWriter out, Object[] obj) { - out.println(printArray(obj, true)); - } - - public static final String printArray(Object[] obj) { - return printArray(obj, true); - } - - public static final String printArray(Object[] obj, boolean braces) { - return printArray(obj, braces, false); - } - - public static final String printArray(Object[] obj, boolean braces, - boolean quote) { - if(obj == null) - return null; - - StringBuffer buf = new StringBuffer(); - if(braces) - buf.append('{'); - - for(int i=0; i < obj.length; i++) { - if(obj[i] != null) { - buf.append((quote? "\"" : "") + obj[i].toString() + (quote? "\"" : "")); - } else { - buf.append("null"); - } - - if(i < obj.length - 1) { - buf.append(", "); - } - } - - if(braces) - buf.append('}'); - - return buf.toString(); - } - - /** @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _) - */ - public static boolean isJavaIdentifierPart(char ch) { - return ((ch >= 'a') && (ch <= 'z')) || - ((ch >= 'A') && (ch <= 'Z')) || - ((ch >= '0') && (ch <= '9')) || - (ch == '_'); - } - - /** Encode byte array it into Java identifier string, i.e., a string - * that only contains the following characters: (a, ... z, A, ... Z, - * 0, ... 9, _, $). The encoding algorithm itself is not too - * clever: if the current byte's ASCII value already is a valid Java - * identifier part, leave it as it is. Otherwise it writes the - * escape character($) followed by