diff --git a/README.markdown b/README.markdown index 79d127b..c09d379 100644 --- a/README.markdown +++ b/README.markdown @@ -13,7 +13,6 @@ Boy is a Gamboy (dmg not 0) emulator written in Java. ### To-do * Pass all tests for dmg (not 0) * Implement sound -* Totally split ui from emulator * Make implementation of MBC1 clearer * Implement all other MBC's diff --git a/src/connectos/JoypadConnector.java b/src/connectos/JoypadConnector.java new file mode 100644 index 0000000..6058ac9 --- /dev/null +++ b/src/connectos/JoypadConnector.java @@ -0,0 +1,94 @@ +package connectos; + +public class JoypadConnector +{ + private boolean downIsPressed; + private boolean upIsPressed; + private boolean leftIsPressed; + private boolean rightIsPressed; + private boolean startIsPressed; + private boolean selectIsPressed; + private boolean aIsPressed; + private boolean bIsPressed; + + public boolean isDownPressed() + { + return downIsPressed; + } + + public void setDownPressed(boolean downIsPressed) + { + this.downIsPressed = downIsPressed; + } + + public boolean isUpPressed() + { + return upIsPressed; + } + + public void setUpPressed(boolean upIsPressed) + { + this.upIsPressed = upIsPressed; + } + + public boolean isLeftPressed() + { + return leftIsPressed; + } + + public void setLeftPressed(boolean leftIsPressed) + { + this.leftIsPressed = leftIsPressed; + } + + public boolean isRightPressed() + { + return rightIsPressed; + } + + public void setRightPressed(boolean rightIsPressed) + { + this.rightIsPressed = rightIsPressed; + } + + public boolean isStartPressed() + { + return startIsPressed; + } + + public void setStartPressed(boolean startIsPressed) + { + this.startIsPressed = startIsPressed; + } + + public boolean isSelectPressed() + { + return selectIsPressed; + } + + public void setSelectPressed(boolean selectIsPressed) + { + this.selectIsPressed = selectIsPressed; + } + + public boolean isaPressed() + { + return aIsPressed; + } + + public void setaPressed(boolean aIsPressed) + { + this.aIsPressed = aIsPressed; + } + + public boolean isbPressed() + { + return bIsPressed; + } + + public void setbPressed(boolean bIsPressed) + { + this.bIsPressed = bIsPressed; + } + +} diff --git a/src/connectos/LcdConnector.java b/src/connectos/LcdConnector.java new file mode 100644 index 0000000..03db560 --- /dev/null +++ b/src/connectos/LcdConnector.java @@ -0,0 +1,37 @@ +package connectos; + +import java.awt.image.BufferedImage; + +import ppu.LCD; + +public class LcdConnector +{ + private BufferedImage lcdOutput; + private boolean isLcdOn; + + public LcdConnector() + { + this.lcdOutput = new BufferedImage(LCD.LCD_WIDTH, LCD.LCD_HEIGHT, BufferedImage.TYPE_INT_RGB); + isLcdOn = false; + } + + public void setImage(BufferedImage lcdOutput) + { + this.lcdOutput = lcdOutput; + } + + public BufferedImage getImage() + { + return lcdOutput; + } + + public void setLcdOn(boolean isOn) + { + this.isLcdOn = isOn; + } + + public boolean isLcdOn() + { + return isLcdOn; + } +} diff --git a/src/gameboy/Gameboy.java b/src/gameboy/Gameboy.java index 84ed832..482fe0b 100644 --- a/src/gameboy/Gameboy.java +++ b/src/gameboy/Gameboy.java @@ -2,14 +2,11 @@ import java.awt.event.KeyListener; -import javax.swing.JPanel; - import cartridge.BootRomUnmapRegister; import cartridge.BootRom; import cartridge.Cartridge; -import cartridge.RomBank0; -import cartridge.SwitchableRamBank; -import cartridge.SwitchableRomBank; +import connectos.JoypadConnector; +import connectos.LcdConnector; import cpu.Accumulator; import cpu.CPU; import cpu.Flags; @@ -24,7 +21,6 @@ import ppu.DMAMecanism; import ppu.DirectMemoryAcessRegister; import ppu.LCD; -import ppu.LCD.Panel; import ppu.LCDControlStatusRegister; import ppu.LCDControllRegister; import ppu.LCDControllYCompare; @@ -83,7 +79,8 @@ public class Gameboy private Register8Bit l; private int baseClockHz; - public Gameboy(String RomPath, int baseClockHz) + public Gameboy(String RomPath, int baseClockHz, IPSMonitor ipsMonitor, LcdConnector lcdConnector, + JoypadConnector joypadConnector) { this.baseClockHz = baseClockHz; @@ -140,22 +137,22 @@ public Gameboy(String RomPath, int baseClockHz) this.cpu = new CPU(ram, accu, pc, sp, b, c, d, e, h, l, flags, interruptEnableRegister, interruptFlagRegister); + this.lcd = new LCD(lcdControll, lcdConnector); + this.ppu = new PPU(tilePatternTable, scrollX, scrollY, lcdControll, lcdControllYCompare, lcdControlStatusRegister, lcdYCoordinate, backgroundAndWindowColorPalette, obj0, obj1, - interruptFlagRegister, tileMap, objectAtributeMap, videoRam); + interruptFlagRegister, tileMap, objectAtributeMap, videoRam, lcd); this.timer = new Timer(timerControl, timerCounter, timerModulo, interruptFlagRegister, divider); - this.joypad = new JoyPad(joypadInformation, interruptFlagRegister); - - this.lcd = new LCD(ppu.getPixelFifo(), lcdControll); + this.joypad = new JoyPad(joypadInformation, interruptFlagRegister, joypadConnector); this.dma = new DMAMecanism(dmaRegister, ram, objectAtributeMap); this.cardridgeOverBootRomMapper = new CardridgeOverBootRomMapper(cartridge, unusableMemory1, ram, bootRomTurnOff); - this.ipsMonitor = new IPSMonitor(); + this.ipsMonitor = ipsMonitor; instructionCount = 0; elapsedTime = System.nanoTime(); @@ -163,10 +160,6 @@ public Gameboy(String RomPath, int baseClockHz) public void start() { - // CPUDataScreen cpuScreen = new CPUDataScreen(ram, accu, pc, sp, b, c, - // d, e, h, l, flags); - - // new Thread(cpuScreen).start(); while (true) { tick(); @@ -200,24 +193,8 @@ public Ram getRam() return ram; } - public Panel getPanel() - { - return lcd.getPanel(); - } - - public KeyListener getKeyListener() - { - return joypad; - } - public CPU getCpu() { return cpu; } - - public IPSMonitor getIPSMonitor() - { - return ipsMonitor; - } - } diff --git a/src/joypad/JoyPad.java b/src/joypad/JoyPad.java index 1289a33..bfcee12 100644 --- a/src/joypad/JoyPad.java +++ b/src/joypad/JoyPad.java @@ -3,97 +3,24 @@ import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import connectos.JoypadConnector; import cpu.InterruptFlagRegister; +import gameboy.MegiHertz; import gameboy.TickBasedComponend; -public class JoyPad extends TickBasedComponend implements KeyListener +public class JoyPad extends TickBasedComponend { private JoypadInformationRegister joypadInformation; private InterruptFlagRegister interruptFlag; + private JoypadConnector joypadConnector; - private boolean downIsPressed; - private boolean upIsPressed; - private boolean leftIsPressed; - private boolean rightIsPressed; - private boolean startIsPressed; - private boolean selectIsPressed; - private boolean aIsPressed; - private boolean bIsPressed; - - public JoyPad(JoypadInformationRegister joypadInformation, InterruptFlagRegister interruptFlag) + public JoyPad(JoypadInformationRegister joypadInformation, InterruptFlagRegister interruptFlag, + JoypadConnector joypadConnector) { - super(4194304); + super(MegiHertz.get(4)); this.joypadInformation = joypadInformation; this.interruptFlag = interruptFlag; - } - - @Override - public void keyPressed(KeyEvent event) - { - switch (event.getKeyCode()) - { - case KeyEvent.VK_DOWN: - downIsPressed = true; - break; - case KeyEvent.VK_UP: - upIsPressed = true; - break; - case KeyEvent.VK_LEFT: - leftIsPressed = true; - break; - case KeyEvent.VK_RIGHT: - rightIsPressed = true; - break; - case KeyEvent.VK_SPACE: - startIsPressed = true; - break; - case KeyEvent.VK_ENTER: - selectIsPressed = true; - break; - case KeyEvent.VK_B: - bIsPressed = true; - break; - case KeyEvent.VK_A: - aIsPressed = true; - break; - } - } - - @Override - public void keyReleased(KeyEvent event) - { - switch (event.getKeyCode()) - { - case KeyEvent.VK_DOWN: - downIsPressed = false; - break; - case KeyEvent.VK_UP: - upIsPressed = false; - break; - case KeyEvent.VK_LEFT: - leftIsPressed = false; - break; - case KeyEvent.VK_RIGHT: - rightIsPressed = false; - break; - case KeyEvent.VK_SPACE: - startIsPressed = false; - break; - case KeyEvent.VK_ENTER: - selectIsPressed = false; - break; - case KeyEvent.VK_B: - bIsPressed = false; - break; - case KeyEvent.VK_A: - aIsPressed = false; - break; - } - } - - @Override - public void keyTyped(KeyEvent event) - { + this.joypadConnector = joypadConnector; } @Override @@ -106,42 +33,42 @@ public boolean tick() boolean isAnyButtonPressed = joypadInformation.isButtonPressed(); - if (downIsPressed) + if (joypadConnector.isDownPressed()) { joypadInformation.setInputDown(true); } - if (upIsPressed) + if (joypadConnector.isUpPressed()) { joypadInformation.setInputUp(true); } - if (leftIsPressed) + if (joypadConnector.isLeftPressed()) { joypadInformation.setInputLeft(true); } - if (rightIsPressed) + if (joypadConnector.isRightPressed()) { joypadInformation.setInputRight(true); } - if (startIsPressed) + if (joypadConnector.isStartPressed()) { joypadInformation.setInputStart(true); } - if (selectIsPressed) + if (joypadConnector.isSelectPressed()) { joypadInformation.setInputSelect(true); } - if (aIsPressed) + if (joypadConnector.isaPressed()) { joypadInformation.setInputA(true); } - if (bIsPressed) + if (joypadConnector.isbPressed()) { joypadInformation.setInputB(true); } diff --git a/src/ppu/LCD.java b/src/ppu/LCD.java index 295eabf..41bee46 100644 --- a/src/ppu/LCD.java +++ b/src/ppu/LCD.java @@ -4,9 +4,11 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.image.BufferedImage; import javax.swing.JPanel; +import connectos.LcdConnector; import gameboy.MegiHertz; import gameboy.TickBasedComponend; @@ -15,42 +17,16 @@ public class LCD extends TickBasedComponend public static final int LCD_WIDTH = 160; public static final int LCD_HEIGHT = 144; - private PixelFifo fifo; private LCDControllRegister lcdControll; - private Panel panel; - private double scale; - private boolean isOn; + private BufferedImage lcdContent; + private LcdConnector lcdConnector; - public LCD(PixelFifo fifo, LCDControllRegister lcdControll) + public LCD(LCDControllRegister lcdControll, LcdConnector lcdConnector) { super(MegiHertz.get(4)); - this.fifo = fifo; this.lcdControll = lcdControll; - - panel = new Panel(); - isOn = lcdControll.isLcdOn(); - scale = 3.0; - panel.setPreferredSize(new Dimension((int) (LCD_WIDTH * scale), (int) (LCD_HEIGHT * scale))); - } - - public class Panel extends JPanel - { - - @Override - protected void paintComponent(Graphics g) - { - Graphics2D g2D = (Graphics2D) g; - g2D.scale(scale, scale); - if (true) - { - g2D.drawImage(fifo.getImage(), 0, 0, this); - } - else - { - g2D.setColor(new Color(170, 170, 170)); - g2D.fillRect(0, 0, LCD_WIDTH, LCD_HEIGHT); - } - } + this.lcdConnector = lcdConnector; + lcdContent = new BufferedImage(LCD_WIDTH, LCD_HEIGHT, BufferedImage.TYPE_INT_RGB); } @Override @@ -61,13 +37,14 @@ public boolean tick() return true; } - isOn = lcdControll.isLcdOn(); + lcdConnector.setLcdOn(lcdControll.isLcdOn()); return false; } - public Panel getPanel() + public void setPixel(int x, int y, int color) { - return panel; + lcdContent.setRGB(x, y, color); + lcdConnector.setImage(lcdContent); } } diff --git a/src/ppu/PPU.java b/src/ppu/PPU.java index ad4bab9..7a91db8 100644 --- a/src/ppu/PPU.java +++ b/src/ppu/PPU.java @@ -39,10 +39,10 @@ public PPU(TilePatternTable tilePatternTable, ScrollXRegister scrollX, ScrollYRe LCDControlStatusRegister lcdControlStatusRegister, LCDControllYCoordinateRegister lcdYCoordinate, BackgroundAndWindowColorPalette backgroundAndWindowColorPalette, ObjectColorPalette0 obj0, ObjectColorPalette1 obj1, InterruptFlagRegister interruptFlagRegister, TileMap tileMap, - ObjectsAttributeMap oaMap, VideoRam videoRam) + ObjectsAttributeMap oaMap, VideoRam videoRam, LCD lcd) { super(MegiHertz.get(4)); - this.fifo = new PixelFifo(scrollX, scrollY, backgroundAndWindowColorPalette, obj0, obj1); + this.fifo = new PixelFifo(scrollX, scrollY, backgroundAndWindowColorPalette, obj0, obj1, lcd); this.oamSearcher = new OAMSearcher(lcdControll, lcdYCoordinate, oaMap); this.lcdYCoordinate = lcdYCoordinate; this.fetcher = new Fetcher(tilePatternTable, fifo, lcdControll, oamSearcher, lcdYCoordinate, tileMap); @@ -107,14 +107,17 @@ public boolean tick() interruptFlagRegister.setLCDCPending(true); } } - if (count == 79) - { - System.out.println("79 " + internelMode); - System.out.println( - "LY: " + lcdYCoordinate.loadLcdYCoordinate() + ", Mode: " + lcdControlStatusRegister.getStatus() - + ", OAM read: " + oam.isReadAllowed() + ", OAM write: " + oam.isWriteAllowed() - + ", VRam read: " + vRam.isReadAllowed() + ", VRam write: " + vRam.isWriteAllowed()); - } + // if (count == 79) + // { + // System.out.println("79 " + internelMode); + // System.out.println( + // "LY: " + lcdYCoordinate.loadLcdYCoordinate() + ", Mode: " + + // lcdControlStatusRegister.getStatus() + // + ", OAM read: " + oam.isReadAllowed() + ", OAM write: " + + // oam.isWriteAllowed() + // + ", VRam read: " + vRam.isReadAllowed() + ", VRam write: " + + // vRam.isWriteAllowed()); + // } return false; } @@ -138,7 +141,6 @@ public void drawScreen() if (oamSearcher.getState() == OAMState.FINISHED) { internelMode = LCDStatus.PIXEL_TRANSFER; - System.out.println(internelMode); oam.allowRead(false); oam.allowWrite(true); vRam.allowRead(false); @@ -167,7 +169,6 @@ public void drawScreen() if (fifo.isLineFinished()) { internelMode = LCDStatus.H_BLANCK; - System.out.println(internelMode); } break; @@ -176,7 +177,6 @@ public void drawScreen() && lcdControlStatusRegister.isHBlankInterruptEnabled()) { interruptFlagRegister.setLCDCPending(true); - System.out.println("Interrupt"); } this.lcdControlStatusRegister.setModeHBlank(); tickCount++; @@ -189,7 +189,6 @@ public void drawScreen() if (veryFirstLine) { internelMode = LCDStatus.PIXEL_TRANSFER; - System.out.println(internelMode); tickCount = 0; pixelTransferTickCount = 0; veryFirstLine = false; @@ -200,7 +199,6 @@ public void drawScreen() vRam.allowRead(true); vRam.allowWrite(true); internelMode = LCDStatus.OAM_SEARCH; - System.out.println(internelMode); oamSearcher.reset(); tickCount = 0; @@ -247,7 +245,6 @@ public void drawScreen() if (lcdYCoordinate.loadLcdYCoordinate() - SCREEN_LINES == V_BLANCK_LINES) { internelMode = LCDStatus.OAM_SEARCH; - System.out.println(internelMode); lcdYCoordinate.writeLcdYCoordinate(0); fetcher.reset(); fifo.reset(); diff --git a/src/ppu/PixelFifo.java b/src/ppu/PixelFifo.java index 4a3c7ac..6b3e2de 100644 --- a/src/ppu/PixelFifo.java +++ b/src/ppu/PixelFifo.java @@ -12,11 +12,11 @@ public class PixelFifo extends TickBasedComponend private static final int MINIMUM_FIFO_SIZE = 8; private LinkedList fifo; - private BufferedImage image; private ScrollXRegister scrollX; private BackgroundAndWindowColorPalette backgroundAndWindowColorPalette; private ObjectColorPalette0 obj0; private ObjectColorPalette1 obj1; + private LCD lcd; private int lcdXDrawPosition; private int lcdYDrawPosition; @@ -25,20 +25,20 @@ public class PixelFifo extends TickBasedComponend public PixelFifo(ScrollXRegister scrollX, ScrollYRegister scrollY, BackgroundAndWindowColorPalette backgroundAndWindowColorPalette, ObjectColorPalette0 obj0, - ObjectColorPalette1 obj1) + ObjectColorPalette1 obj1, LCD lcd) { super(MegiHertz.get(4)); this.scrollX = scrollX; this.backgroundAndWindowColorPalette = backgroundAndWindowColorPalette; this.obj0 = obj0; this.obj1 = obj1; + this.lcd = lcd; lcdXDrawPosition = 0; lcdYDrawPosition = 0; xOffset = this.scrollX.getXScroll() % 8; fifo = new LinkedList<>(); - image = new BufferedImage(LCD.LCD_WIDTH, LCD.LCD_HEIGHT, BufferedImage.TYPE_INT_RGB); } @Override @@ -48,8 +48,9 @@ public boolean tick() { return true; } - - if(xOffset == -1) { + + if (xOffset == -1) + { xOffset = this.scrollX.getXScroll() % 8; } @@ -67,14 +68,14 @@ public boolean tick() switch (infos.source) { case BACKGROUND_AND_WINDOW: - image.setRGB(lcdXDrawPosition, lcdYDrawPosition, + lcd.setPixel(lcdXDrawPosition, lcdYDrawPosition, backgroundAndWindowColorPalette.getColorFor(infos.color)); break; case OBJECT_0: - image.setRGB(lcdXDrawPosition, lcdYDrawPosition, obj0.getColorFor(infos.color)); + lcd.setPixel(lcdXDrawPosition, lcdYDrawPosition, obj0.getColorFor(infos.color)); break; case OBJECT_1: - image.setRGB(lcdXDrawPosition, lcdYDrawPosition, obj1.getColorFor(infos.color)); + lcd.setPixel(lcdXDrawPosition, lcdYDrawPosition, obj1.getColorFor(infos.color)); break; } @@ -129,11 +130,6 @@ public boolean isEmpty() return fifo.isEmpty(); } - public BufferedImage getImage() - { - return image; - } - public void reset() { fifo.clear(); diff --git a/src/ppu/ScrollXRegister.java b/src/ppu/ScrollXRegister.java index 14174a3..b8f75a3 100644 --- a/src/ppu/ScrollXRegister.java +++ b/src/ppu/ScrollXRegister.java @@ -16,11 +16,4 @@ public int getXScroll() { return getValue(); } - - @Override - public void put(int adress, byte input) - { - System.out.println("SCX: " + Byte.toUnsignedInt(input)); - super.put(adress, input); - } } diff --git a/src/tools/CPUDataScreen.java b/src/tools/CPUDataScreen.java deleted file mode 100644 index aedc402..0000000 --- a/src/tools/CPUDataScreen.java +++ /dev/null @@ -1,306 +0,0 @@ -package tools; - -import java.awt.GridLayout; - -import javax.swing.JFrame; -import javax.swing.JLabel; - -import cpu.Accumulator; -import cpu.Flags; -import cpu.ProgrammCounter; -import cpu.Register16bit; -import cpu.Register8Bit; -import ram.Ram; - -public class CPUDataScreen extends JFrame implements Runnable -{ - - private Ram ram; - private Accumulator accu; - private Flags flags; - private Register16bit sp; - private ProgrammCounter pc; - private Register8Bit b; - private Register8Bit c; - private Register8Bit d; - private Register8Bit e; - private Register8Bit h; - private Register8Bit l; - - JLabel register = new JLabel("Register"); - JLabel biner = new JLabel("Binär"); - JLabel decimal = new JLabel("Dezimal"); - JLabel octal = new JLabel("Octal"); - JLabel hex = new JLabel("Hex"); - - JLabel aLabel = new JLabel("A"); - JLabel aValueB = new JLabel(); - JLabel aValueO = new JLabel(); - JLabel aValueD = new JLabel(); - JLabel aValueH = new JLabel(); - - JLabel flagsLabel = new JLabel("Flags Z N H C"); - JLabel flagsValueB = new JLabel(); - JLabel flagsValueO = new JLabel(); - JLabel flagsValueD = new JLabel(); - JLabel flagsValueH = new JLabel(); - - JLabel bLabel = new JLabel("B"); - JLabel bValueB = new JLabel(); - JLabel bValueO = new JLabel(); - JLabel bValueD = new JLabel(); - JLabel bValueH = new JLabel(); - - JLabel cLabel = new JLabel("C"); - JLabel cValueB = new JLabel(); - JLabel cValueO = new JLabel(); - JLabel cValueD = new JLabel(); - JLabel cValueH = new JLabel(); - - JLabel dLabel = new JLabel("D"); - JLabel dValueB = new JLabel(); - JLabel dValueO = new JLabel(); - JLabel dValueD = new JLabel(); - JLabel dValueH = new JLabel(); - - JLabel eLabel = new JLabel("E"); - JLabel eValueB = new JLabel(); - JLabel eValueO = new JLabel(); - JLabel eValueD = new JLabel(); - JLabel eValueH = new JLabel(); - - JLabel hLabel = new JLabel("H"); - JLabel hValueB = new JLabel(); - JLabel hValueO = new JLabel(); - JLabel hValueD = new JLabel(); - JLabel hValueH = new JLabel(); - - JLabel lLabel = new JLabel("L"); - JLabel lValueB = new JLabel(); - JLabel lValueO = new JLabel(); - JLabel lValueD = new JLabel(); - JLabel lValueH = new JLabel(); - - JLabel spLabel = new JLabel("SP"); - JLabel spValueB = new JLabel(); - JLabel spValueO = new JLabel(); - JLabel spValueD = new JLabel(); - JLabel spValueH = new JLabel(); - - JLabel pcLabel = new JLabel("PC"); - JLabel pcValueB = new JLabel(); - JLabel pcValueO = new JLabel(); - JLabel pcValueD = new JLabel(); - JLabel pcValueH = new JLabel(); - - JLabel pcInstruction = new JLabel("Instruction"); - JLabel pcInstructionValueB = new JLabel(); - JLabel pcInstructionValueO = new JLabel(); - JLabel pcInstructionValueD = new JLabel(); - JLabel pcInstructionValueH = new JLabel(); - - public CPUDataScreen(Ram ram, Accumulator accu, ProgrammCounter pc, Register16bit sp, Register8Bit b, - Register8Bit c, Register8Bit d, Register8Bit e, Register8Bit h, Register8Bit l, Flags flags) - { - super("My Frame"); - - this.ram = ram; - this.flags = flags; - this.accu = accu; - this.pc = pc; - this.sp = sp; - this.b = b; - this.c = c; - this.d = d; - this.e = e; - this.h = h; - this.l = l; - - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - GridLayout experimentLayout = new GridLayout(0, 5); - - this.getContentPane().setLayout(experimentLayout); - - this.getContentPane().add(register); - this.getContentPane().add(biner); - this.getContentPane().add(octal); - this.getContentPane().add(decimal); - this.getContentPane().add(hex); - - this.getContentPane().add(aLabel); - this.getContentPane().add(aValueB); - this.getContentPane().add(aValueO); - this.getContentPane().add(aValueD); - this.getContentPane().add(aValueH); - - this.getContentPane().add(flagsLabel); - this.getContentPane().add(flagsValueB); - this.getContentPane().add(flagsValueO); - this.getContentPane().add(flagsValueD); - this.getContentPane().add(flagsValueH); - - this.getContentPane().add(bLabel); - this.getContentPane().add(bValueB); - this.getContentPane().add(bValueO); - this.getContentPane().add(bValueD); - this.getContentPane().add(bValueH); - - this.getContentPane().add(cLabel); - this.getContentPane().add(cValueB); - this.getContentPane().add(cValueO); - this.getContentPane().add(cValueD); - this.getContentPane().add(cValueH); - - this.getContentPane().add(dLabel); - this.getContentPane().add(dValueB); - this.getContentPane().add(dValueO); - this.getContentPane().add(dValueD); - this.getContentPane().add(dValueH); - - this.getContentPane().add(eLabel); - this.getContentPane().add(eValueB); - this.getContentPane().add(eValueO); - this.getContentPane().add(eValueD); - this.getContentPane().add(eValueH); - - this.getContentPane().add(hLabel); - this.getContentPane().add(hValueB); - this.getContentPane().add(hValueO); - this.getContentPane().add(hValueD); - this.getContentPane().add(hValueH); - - this.getContentPane().add(lLabel); - this.getContentPane().add(lValueB); - this.getContentPane().add(lValueO); - this.getContentPane().add(lValueD); - this.getContentPane().add(lValueH); - - this.getContentPane().add(spLabel); - this.getContentPane().add(spValueB); - this.getContentPane().add(spValueO); - this.getContentPane().add(spValueD); - this.getContentPane().add(spValueH); - - this.getContentPane().add(pcLabel); - this.getContentPane().add(pcValueB); - this.getContentPane().add(pcValueO); - this.getContentPane().add(pcValueD); - this.getContentPane().add(pcValueH); - - this.getContentPane().add(pcInstruction); - this.getContentPane().add(pcInstructionValueB); - this.getContentPane().add(pcInstructionValueO); - this.getContentPane().add(pcInstructionValueD); - this.getContentPane().add(pcInstructionValueH); - - update(); - - setSize(500, 500); - setVisible(true); - } - - private String ByteToString(byte value) - { - return Integer.toString(Byte.toUnsignedInt(value)); - } - - private String ByteToHexString(byte value) - { - return Integer.toHexString(Byte.toUnsignedInt(value)); - } - - private String ShortToString(short value) - { - return Integer.toString(Short.toUnsignedInt(value)); - } - - private String ShortToHexString(short value) - { - return Integer.toHexString(Short.toUnsignedInt(value)); - } - - private String ByteToOctalString(byte value) - { - StringBuilder octalNumber = new StringBuilder(Integer.toOctalString(Byte.toUnsignedInt(value))); - octalNumber.reverse(); - while (octalNumber.length() < 3) - { - octalNumber.append("0"); - } - return octalNumber.reverse().toString(); - } - - private String ByteToBinaryString(byte value) - { - StringBuilder octalNumber = new StringBuilder(Integer.toBinaryString(Byte.toUnsignedInt(value))); - octalNumber.reverse(); - while (octalNumber.length() < 8) - { - octalNumber.append("0"); - } - return octalNumber.reverse().toString(); - } - - private void update() - { - aValueB.setText(ByteToBinaryString(accu.load())); - aValueO.setText(ByteToOctalString(accu.load())); - aValueD.setText(ByteToString(accu.load())); - aValueH.setText(ByteToHexString(accu.load())); - - flagsValueB.setText(ByteToBinaryString(flags.load())); - flagsValueO.setText(ByteToOctalString(flags.load())); - flagsValueD.setText(ByteToString(flags.load())); - flagsValueH.setText(ByteToHexString(flags.load())); - - bValueB.setText(ByteToBinaryString(b.load())); - bValueO.setText(ByteToOctalString(b.load())); - bValueD.setText(ByteToString(b.load())); - bValueH.setText(ByteToHexString(b.load())); - - cValueB.setText(ByteToBinaryString(c.load())); - cValueO.setText(ByteToOctalString(c.load())); - cValueD.setText(ByteToString(c.load())); - cValueH.setText(ByteToHexString(c.load())); - - dValueB.setText(ByteToBinaryString(d.load())); - dValueO.setText(ByteToOctalString(d.load())); - dValueD.setText(ByteToString(d.load())); - dValueH.setText(ByteToHexString(d.load())); - - eValueB.setText(ByteToBinaryString(e.load())); - eValueO.setText(ByteToOctalString(e.load())); - eValueD.setText(ByteToString(e.load())); - eValueH.setText(ByteToHexString(e.load())); - - hValueB.setText(ByteToBinaryString(h.load())); - hValueO.setText(ByteToOctalString(h.load())); - hValueD.setText(ByteToString(h.load())); - hValueH.setText(ByteToHexString(h.load())); - - lValueB.setText(ByteToBinaryString(l.load())); - lValueO.setText(ByteToOctalString(l.load())); - lValueD.setText(ByteToString(l.load())); - lValueH.setText(ByteToHexString(l.load())); - - spValueD.setText(ShortToString(sp.load())); - spValueH.setText(ShortToHexString(sp.load())); - - pcValueD.setText(ShortToString(pc.loadWithoutInc())); - pcValueH.setText(ShortToHexString(pc.loadWithoutInc())); - - pcInstructionValueO.setText(ByteToOctalString(ram.load(pc.loadWithoutInc()))); - pcInstructionValueH.setText(ByteToHexString(ram.load(pc.loadWithoutInc()))); - } - - @Override - public void run() - { - while (true) - { - update(); - } - - } -} diff --git a/src/ui/BoyPanel.java b/src/ui/BoyPanel.java new file mode 100644 index 0000000..c14ae32 --- /dev/null +++ b/src/ui/BoyPanel.java @@ -0,0 +1,41 @@ +package ui; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; + +import javax.swing.JPanel; + +import connectos.LcdConnector; +import ppu.LCD; + +public class BoyPanel extends JPanel +{ + private LcdConnector lcdConnector; + private int scale; + + public BoyPanel(LcdConnector lcdConnector, int scale) + { + this.lcdConnector = lcdConnector; + this.setPreferredSize(new Dimension(LCD.LCD_WIDTH * scale, LCD.LCD_HEIGHT * scale)); + this.scale = scale; + } + + @Override + protected void paintComponent(Graphics g) + { + Graphics2D g2D = (Graphics2D) g; + g2D.scale(scale, scale); + + if (lcdConnector.isLcdOn()) + { + g2D.drawImage(lcdConnector.getImage(), 0, 0, this); + } + else + { + g2D.setColor(new Color(170, 170, 170)); + g2D.fillRect(0, 0, LCD.LCD_WIDTH, LCD.LCD_HEIGHT); + } + } +} diff --git a/src/ui/GbKeyListener.java b/src/ui/GbKeyListener.java new file mode 100644 index 0000000..2f29b43 --- /dev/null +++ b/src/ui/GbKeyListener.java @@ -0,0 +1,86 @@ +package ui; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import connectos.JoypadConnector; + +public class GbKeyListener implements KeyListener +{ + private JoypadConnector joypadConnector; + + public GbKeyListener(JoypadConnector joypadConnector) + { + this.joypadConnector = joypadConnector; + } + + @Override + public void keyPressed(KeyEvent event) + { + switch (event.getKeyCode()) + { + case KeyEvent.VK_DOWN: + joypadConnector.setDownPressed(true); + break; + case KeyEvent.VK_UP: + joypadConnector.setUpPressed(true); + break; + case KeyEvent.VK_LEFT: + joypadConnector.setLeftPressed(true); + break; + case KeyEvent.VK_RIGHT: + joypadConnector.setRightPressed(true); + break; + case KeyEvent.VK_SPACE: + joypadConnector.setStartPressed(true); + break; + case KeyEvent.VK_ENTER: + joypadConnector.setSelectPressed(true); + break; + case KeyEvent.VK_B: + joypadConnector.setbPressed(true); + break; + case KeyEvent.VK_A: + joypadConnector.setaPressed(true); + break; + } + } + + @Override + public void keyReleased(KeyEvent event) + { + switch (event.getKeyCode()) + { + case KeyEvent.VK_DOWN: + joypadConnector.setDownPressed(false); + break; + case KeyEvent.VK_UP: + joypadConnector.setUpPressed(false); + break; + case KeyEvent.VK_LEFT: + joypadConnector.setLeftPressed(false); + break; + case KeyEvent.VK_RIGHT: + joypadConnector.setRightPressed(false); + break; + case KeyEvent.VK_SPACE: + joypadConnector.setStartPressed(false); + break; + case KeyEvent.VK_ENTER: + joypadConnector.setSelectPressed(false); + break; + case KeyEvent.VK_B: + joypadConnector.setbPressed(false); + break; + case KeyEvent.VK_A: + joypadConnector.setaPressed(false); + break; + } + } + + @Override + public void keyTyped(KeyEvent event) + { + } + +} diff --git a/src/ui/Main.java b/src/ui/Main.java index ff01c63..fbfc36f 100644 --- a/src/ui/Main.java +++ b/src/ui/Main.java @@ -1,15 +1,24 @@ package ui; +import connectos.JoypadConnector; +import connectos.LcdConnector; import gameboy.Gameboy; import gameboy.MegiHertz; +import joypad.JoyPad; +import ppu.LCD; +import tools.IPSMonitor; public class Main { public static void main(String[] args) { - Gameboy gb = new Gameboy("resources/Roms/SuperMarioLand.gb", MegiHertz.get(4)); - Window window = new Window(gb.getIPSMonitor(), gb.getPanel(), gb.getKeyListener()); + LcdConnector lcdConnector = new LcdConnector(); + JoypadConnector joypadConnector = new JoypadConnector(); + IPSMonitor ipsMonitor = new IPSMonitor(); + Gameboy gb = new Gameboy("resources/Roms/SuperMarioLand.gb", MegiHertz.get(4), ipsMonitor, lcdConnector, + joypadConnector); + Window window = new Window(ipsMonitor, lcdConnector, joypadConnector); Sound sound = new Sound(); // new Thread(sound).start(); diff --git a/src/ui/Window.java b/src/ui/Window.java index be14804..0fbbd8c 100644 --- a/src/ui/Window.java +++ b/src/ui/Window.java @@ -1,43 +1,46 @@ package ui; import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.event.KeyListener; -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.SourceDataLine; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; -import gameboy.Gameboy; -import ppu.LCD.Panel; +import connectos.JoypadConnector; +import connectos.LcdConnector; +import ppu.LCD; import tools.IPSMonitor; public class Window extends JFrame implements Runnable { - private Panel gamePane; + private BoyPanel gamePane; private JPanel contendPane; private JLabel ips; private IPSMonitor ipsMonitor; - public Window(IPSMonitor ipsMonitor, Panel panel, KeyListener listener) + public Window(IPSMonitor ipsMonitor, LcdConnector lcdConnector, JoypadConnector joypadConnector) { super("Gameboy"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.gamePane = panel; + setResizable(false); + + this.gamePane = new BoyPanel(lcdConnector, 3); this.ipsMonitor = ipsMonitor; contendPane = new JPanel(new BorderLayout()); this.setContentPane(contendPane); - ips = new JLabel(); + ips = new JLabel(""); contendPane.add(gamePane, BorderLayout.CENTER); contendPane.add(ips, BorderLayout.PAGE_START); - this.addKeyListener(listener); + this.addKeyListener(new GbKeyListener(joypadConnector)); pack(); } @@ -50,6 +53,5 @@ public void run() gamePane.repaint(); ips.setText(Long.toString(ipsMonitor.getInstructionsPerSecond())); } - } } diff --git a/tests/general/BlarggsRomsTest.java b/tests/general/BlarggsRomsTest.java index d83defc..49800db 100644 --- a/tests/general/BlarggsRomsTest.java +++ b/tests/general/BlarggsRomsTest.java @@ -11,22 +11,26 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import connectos.JoypadConnector; +import connectos.LcdConnector; import gameboy.Gameboy; +import tools.IPSMonitor; @RunWith(Parameterized.class) public class BlarggsRomsTest extends NoOutputTest { - @Parameters( name = "{1}" ) + @Parameters(name = "{1}") public static List data() { List files = new ArrayList<>(); - + File folder = new File("resources/TestData/blarggs"); File[] listOfFolders = folder.listFiles(); - + for (int i = 0; i < listOfFolders.length; i++) { - if(listOfFolders[i].isFile()) { + if (listOfFolders[i].isFile()) + { continue; } File[] listOfFiles = new File(listOfFolders[i].getPath() + "/individual").listFiles(); @@ -51,7 +55,7 @@ public BlarggsRomsTest(String input, String name) @Test public void test() { - Gameboy gameboy = new Gameboy(fInput, 0); + Gameboy gameboy = new Gameboy(fInput, 0, new IPSMonitor(), new LcdConnector(), new JoypadConnector()); StringBuilder result = new StringBuilder(); while (result.indexOf("Failed") == -1 && result.indexOf("Passed") == -1) { @@ -63,7 +67,7 @@ public void test() gameboy.getRam().put(0xFF01, 0); } } - + assertTrue(result.toString() + "\n" + fInput, result.indexOf("Passed") != -1); } diff --git a/tests/general/MoonEyeTest.java b/tests/general/MoonEyeTest.java index 794ba09..0e7ee3e 100644 --- a/tests/general/MoonEyeTest.java +++ b/tests/general/MoonEyeTest.java @@ -15,7 +15,10 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import connectos.JoypadConnector; +import connectos.LcdConnector; import gameboy.Gameboy; +import tools.IPSMonitor; @RunWith(Parameterized.class) public class MoonEyeTest extends NoOutputTest @@ -85,7 +88,7 @@ public MoonEyeTest(String input, String name) @Test public void test() { - Gameboy gameboy = new Gameboy(fInput, 0); + Gameboy gameboy = new Gameboy(fInput, 0, new IPSMonitor(), new LcdConnector(), new JoypadConnector()); while (!gameboy.getCpu().getCurrentOpCode().equals("100")) { gameboy.tick(); diff --git a/tests/general/SingleBlarggsTest.java b/tests/general/SingleBlarggsTest.java index 7c05ba2..72c0fb2 100644 --- a/tests/general/SingleBlarggsTest.java +++ b/tests/general/SingleBlarggsTest.java @@ -10,7 +10,10 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import connectos.JoypadConnector; +import connectos.LcdConnector; import gameboy.Gameboy; +import tools.IPSMonitor; @RunWith(Parameterized.class) public class SingleBlarggsTest @@ -38,7 +41,7 @@ public SingleBlarggsTest(String input, String name) @Test public void test() { - Gameboy gameboy = new Gameboy(fInput, 0); + Gameboy gameboy = new Gameboy(fInput, 0, new IPSMonitor(), new LcdConnector(), new JoypadConnector()); StringBuilder result = new StringBuilder(); while (result.indexOf("Failed") == -1 && result.indexOf("Passed") == -1) { diff --git a/tests/general/SingleMoonEyeTest.java b/tests/general/SingleMoonEyeTest.java index fa7783e..e38ef8f 100644 --- a/tests/general/SingleMoonEyeTest.java +++ b/tests/general/SingleMoonEyeTest.java @@ -11,7 +11,11 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import connectos.JoypadConnector; +import connectos.LcdConnector; import gameboy.Gameboy; +import gameboy.MegiHertz; +import tools.IPSMonitor; import ui.Window; @RunWith(Parameterized.class) @@ -40,8 +44,12 @@ public SingleMoonEyeTest(String input, String name) @Test public void test() { - Gameboy gameboy = new Gameboy(fInput, 0); - Window window = new Window(gameboy.getIPSMonitor(), gameboy.getPanel(), gameboy.getKeyListener()); + LcdConnector lcdConnector = new LcdConnector(); + JoypadConnector joypadConnector = new JoypadConnector(); + IPSMonitor ipsMonitor = new IPSMonitor(); + Gameboy gameboy = new Gameboy("resources/Roms/SuperMarioLand.gb", MegiHertz.get(4), ipsMonitor, lcdConnector, + joypadConnector); + Window window = new Window(ipsMonitor, lcdConnector, joypadConnector); new Thread(window).start(); window.setVisible(true);