Package org.javatari.atari.console

Source Code of org.javatari.atari.console.Console$CartridgeSocketAdapter

// Copyright 2011-2012 Paulo Augusto Peccin. See licence.txt distributed with this file.

package org.javatari.atari.console;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.javatari.atari.board.BUS;
import org.javatari.atari.cartridge.Cartridge;
import org.javatari.atari.cartridge.CartridgeDatabase;
import org.javatari.atari.cartridge.CartridgeFormatOption;
import org.javatari.atari.cartridge.CartridgeInsertionListener;
import org.javatari.atari.cartridge.CartridgeSocket;
import org.javatari.atari.cartridge.ROMFormatUnsupportedException;
import org.javatari.atari.cartridge.formats.CartridgeSavestate;
import org.javatari.atari.console.savestate.ConsoleState;
import org.javatari.atari.console.savestate.SaveStateMedia;
import org.javatari.atari.console.savestate.SaveStateSocket;
import org.javatari.atari.controls.ConsoleControls;
import org.javatari.atari.controls.ConsoleControls.Control;
import org.javatari.atari.controls.ConsoleControlsInput;
import org.javatari.atari.controls.ConsoleControlsSocket;
import org.javatari.atari.pia.PIA;
import org.javatari.atari.pia.RAM;
import org.javatari.atari.tia.TIA;
import org.javatari.general.av.audio.AudioSignal;
import org.javatari.general.av.video.VideoSignal;
import org.javatari.general.av.video.VideoStandard;
import org.javatari.general.board.Clock;
import org.javatari.general.m6502.M6502;
import org.javatari.parameters.Parameters;


public class Console {

  public Console() {
    mainComponentsCreate();
    socketsCreate();
    mainClockCreate();
    videoStandardAuto();
  }

  public VideoSignal videoOutput() {
    return tia.videoOutput();
  }

  public AudioSignal audioOutput() {
    return tia.audioOutput();
  }

  public ConsoleControlsSocket controlsSocket() {
    return controlsSocket;
  }
 
  public CartridgeSocket cartridgeSocket() {
    return cartridgeSocket;
  }
 
  public SaveStateSocket saveStateSocket() {
    return saveStateSocket;
  }
 
  public void powerOn() {
    if (powerOn) powerOff();
    cpu.powerOn();
    bus.powerOn();
    powerOn = true;
    controlsSocket.controlsStatesRedefined();
    go();
    videoStandardAutoDetectionStart();
  }

  public void powerOff() {
    pause();
    bus.powerOff();
    cpu.powerOff();
    powerOn = false;
    controlsSocket.controlsStatesRedefined();
  }

  public void extendedPowerOff() {
    powerOff();
  }
 
  public void destroy() {
    extendedPowerOff();
    mainClockDestroy();
  }
 
  public void showOSD(String message, boolean overlap) {
    tia.videoOutput().showOSD(message, overlap);
  }
 
  public VideoStandard videoStandard() {
    return videoStandard;
  }
   
  public void videoStandard(VideoStandard videoStandard) {
    if (videoStandard != this.videoStandard) {
      this.videoStandard = videoStandard;
      tia.videoStandard(this.videoStandard);
      mainClockAdjustToNormal();
    }
    showOSD((videoStandardAuto ? "AUTO: " : "") + videoStandard.toString(), false);
  }

  public void go() {
    mainClock.go();
  }
 
  public void pause() {
    mainClock.pause();
  }
 
  // For debug purposes
  public Clock mainClock() {
    return mainClock;
  }

  protected Cartridge cartridge() {
    return bus.cartridge;
  }

  protected void cartridge(Cartridge cartridge) {
    controlsSocket.removeForwardedInput(cartridge());
    bus.cartridge(cartridge);
    cartridgeSocket.cartridgeInserted(cartridge);
    if (cartridge != null) {
      controlsSocket.addForwardedInput(cartridge);
      saveStateSocket.connectCartridge(cartridge);
    }
  }

  protected void videoStandardAuto() {
    videoStandardAuto = true;
    if (powerOn) videoStandardAutoDetectionStart();
    else videoStandard(VideoStandard.NTSC);
  }

  protected void videoStandardAutoDetectionStart() {
    if (!videoStandardAuto || videoStandardAutoDetectionInProgress) return;
    // If no Cartridge present, use NTSC
    if (bus.cartridge == null) {
      videoStandard(VideoStandard.NTSC);
      return;
    }
    // Otherwise use the VideoStandard detected by the monitor
    if (tia.videoOutput().monitor() == null) return;
    videoStandardAutoDetectionInProgress = true;
    tia.videoOutput().monitor().videoStandardDetectionStart();
    // TODO This thread is a source of indeterminism. Potential problem in multiplayer sync
    new Thread("Console VideoStd Detection") { public void run() {
      VideoStandard std;
      int tries = 0;
      do {
        try { Thread.sleep(20); } catch (InterruptedException e) {};
        std = tia.videoOutput().monitor().videoStandardDetected();
      } while (std == null && ++tries < 1500/20);
      if (std != null) videoStandard(std);
      else showOSD("AUTO: FAILED", false);
      videoStandardAutoDetectionInProgress = false;
    }}.start();
  }

  protected void videoStandardForced(VideoStandard forcedVideoStandard) {
    videoStandardAuto = false;
    videoStandard(forcedVideoStandard);
  }

  protected void mainComponentsCreate() {
    cpu = new M6502();
    tia = new TIA();
    pia = new PIA();
    ram = new RAM();
    bus = new BUS(cpu, tia, pia, ram);
  }

  protected void mainClockCreate() {
    mainClock = new Clock("Console(TIA)", tia, 0);
  }

  protected void mainClockAdjustToNormal() {
    double fps = tia.desiredClockForVideoStandard();
    mainClock.speed(fps);
    tia.audioOutput().fps(fps);
  }

  protected void mainClockAdjustToAlternate() {
    double fps = tia.desiredClockForVideoStandard() * ALTERNATE_CLOCK_FACTOR;
    mainClock.speed(fps);
    tia.audioOutput().fps(fps);
  }

  protected void mainClockDestroy() {
    mainClock.terminate();
  }
 
  protected void socketsCreate() {
    controlsSocket = new ConsoleControlsSocket();
    controlsSocket.addForwardedInput(new ConsoleControlsInputAdapter());
    controlsSocket.addForwardedInput(tia);
    controlsSocket.addForwardedInput(pia);
    cartridgeSocket = new CartridgeSocketAdapter();
    saveStateSocket = new SaveStateSocketAdapter();
  }

  protected void loadState(ConsoleState state) {
    tia.loadState(state.tiaState);
    pia.loadState(state.piaState);
    ram.loadState(state.ramState);
    cpu.loadState(state.cpuState);
    cartridge(state.cartridge);
    videoStandard(state.videoStandard);
    controlsSocket.controlsStatesRedefined();
  }

  protected ConsoleState saveState() {
    return new ConsoleState(
      tia.saveState(),
      pia.saveState(),
      ram.saveState(),
      cpu.saveState(),
      cartridge() != null ? cartridge().saveState() : null,
      videoStandard()
    );
  }

  protected void cycleCartridgeFormat() {
    if (cartridge() == null) {
      showOSD("NO CARTRIDGE INSERTED!", true);
      return;
    }
    ArrayList<CartridgeFormatOption> options;
    try {
      options = CartridgeDatabase.getFormatOptions(cartridge().rom());
    } catch (ROMFormatUnsupportedException e) {
      return;
    }
    CartridgeFormatOption currOption = null;
    for (CartridgeFormatOption option : options)
      if (option.format.equals(cartridge().format())) currOption = option;
    int pos = options.indexOf(currOption) + 1;    // cycle through options
    if (pos >= options.size()) pos = 0;
    CartridgeFormatOption newOption = options.get(pos);
    Cartridge newCart = newOption.format.createCartridge(cartridge().rom());
    cartridgeSocket().insert(newCart, true);
    showOSD(newOption.format.toString(), true);
  }
   
  protected void powerFry() {
    ram.powerFry();
  }

  private ConsoleState pauseAndSaveState() {
    pause();
    ConsoleState state = saveState();
    go();
    return state;
  }

  protected void pauseAndLoadState(ConsoleState state) {
    if (powerOn) {
      pause();
      loadState(state);
      go();
    } else {
      powerOn();
      pauseAndLoadState(state);
    }
  }


  public boolean powerOn = false;

  protected BUS bus;
  protected M6502 cpu;
  protected TIA tia;
  protected PIA pia;
  protected RAM ram;
  protected VideoStandard videoStandard;

  protected boolean videoStandardAuto = true;
  private boolean videoStandardAutoDetectionInProgress = false;
 
  protected ConsoleControlsSocket controlsSocket;
  protected CartridgeSocketAdapter cartridgeSocket;
  protected SaveStateSocketAdapter saveStateSocket;

  protected Clock mainClock;
 
  public static final float ALTERNATE_CLOCK_FACTOR = Parameters.CONSOLE_ALTERNATE_CLOCK_FACTOR;

 
  protected class ConsoleControlsInputAdapter implements ConsoleControlsInput {
    public ConsoleControlsInputAdapter() {
    }
    @Override
    public void controlStateChanged(Control control, boolean state) {
      // Normal state controls
      if (control == Control.FAST_SPEED) {
        if (state) {
          showOSD("FAST FORWARD", true);
          mainClockAdjustToAlternate();
        } else {
          showOSD(null, true);
          mainClockAdjustToNormal();
        }
        return;
      }
      // Toggles
      if (!state) return;
      switch (control) {
        case POWER:
          if (powerOn) powerOff();
          else powerOn();
          break;
        case POWER_FRY:
          powerFry();
          break;
        case SAVE_STATE_0: case SAVE_STATE_1: case SAVE_STATE_2: case SAVE_STATE_3: case SAVE_STATE_4: case SAVE_STATE_5:
        case SAVE_STATE_6: case SAVE_STATE_7: case SAVE_STATE_8: case SAVE_STATE_9: case SAVE_STATE_10: case SAVE_STATE_11: case SAVE_STATE_12:
          saveStateSocket.saveState(control.slot);
          break;
        case LOAD_STATE_0: case LOAD_STATE_1: case LOAD_STATE_2: case LOAD_STATE_3: case LOAD_STATE_4: case LOAD_STATE_5:
        case LOAD_STATE_6: case LOAD_STATE_7: case LOAD_STATE_8: case LOAD_STATE_9: case LOAD_STATE_10: case LOAD_STATE_11: case LOAD_STATE_12:
          saveStateSocket.loadState(control.slot);
          break;
        case VIDEO_STANDARD:
          showOSD(null, true)// Prepares for the upcoming "AUTO" OSD to always show
          if (videoStandardAuto) videoStandardForced(VideoStandard.NTSC);
          else if (videoStandard() == VideoStandard.NTSC) videoStandardForced(VideoStandard.PAL);
            else videoStandardAuto();
          break;
        case CARTRIDGE_FORMAT:
          cycleCartridgeFormat();
      }
    }
    @Override
    public void controlStateChanged(ConsoleControls.Control control, int position) {
      // No positional controls here
    }
    @Override
    public void controlsStateReport(Map<ConsoleControls.Control, Boolean> report) {
      //  Only Power Control is visible from outside
      report.put(Control.POWER, powerOn);
    }
  } 
 
  protected class CartridgeSocketAdapter implements CartridgeSocket {
    @Override
    public void insert(Cartridge cartridge, boolean autoPower) {
      // Special case for Savestates
      if (cartridge != null && cartridge instanceof CartridgeSavestate) {
        insertSavestateCartridge((CartridgeSavestate) cartridge);
        return;
      }
      // Normal case
      if (autoPower && powerOn) powerOff();
      cartridge(cartridge);
      if (autoPower && !powerOn) powerOn();
    }
    @Override
    public Cartridge inserted() {
      return cartridge();
    }
    @Override
    public void cartridgeInserted(Cartridge cartridge) {
      for (CartridgeInsertionListener listener : insertionListeners)
        listener.cartridgeInserted(cartridge);
    }
    @Override
    public void addInsertionListener(CartridgeInsertionListener listener) {
      if (!insertionListeners.contains(listener)) {
        insertionListeners.add(listener);
        listener.cartridgeInserted(inserted());    // Fire a insertion event
      }
    }
    @Override
    public void removeInsertionListener(CartridgeInsertionListener listener) {
      insertionListeners.remove(listener);
    }
    protected void insertSavestateCartridge(CartridgeSavestate cartridge) {
      ConsoleState state = cartridge.getConsoleState();
      if (state != null) {
        pauseAndLoadState(state);
        showOSD("Savestate Cartridge loaded", true);
      }
    }
    private List<CartridgeInsertionListener> insertionListeners = new ArrayList<CartridgeInsertionListener>();
 
 
  protected class SaveStateSocketAdapter implements SaveStateSocket {
    @Override
    public void connectMedia(SaveStateMedia media) {
      this.media = media; 
    }
    @Override
    public SaveStateMedia media() {
      return media;
    }
    @Override
    public void externalStateChange() {
      // Nothing
    }
    public void connectCartridge(Cartridge cartridge) {
      cartridge.connectSaveStateSocket(this);
    }
    @Override
    public void saveStateFile() {
      if (!powerOn || media == null) return;
      ConsoleState state = pauseAndSaveState();
      if (media.saveStateFile(state))
        showOSD("State file saved", true);
      else
        showOSD("State file save failed", true);
    }
    public void saveState(int slot) {
      if (!powerOn || media == null) return;
      ConsoleState state = pauseAndSaveState();
      if (media.saveState(slot, state))
        showOSD("State " + slot + " saved", true);
      else
        showOSD("State " + slot + " save failed", true);
    }
    public void loadState(int slot) {
      if (media == null) return;
      ConsoleState state = media.loadState(slot);
      if (state == null) {
        showOSD("State " + slot + " load failed", true);
        return;
      }
      pauseAndLoadState(state);
      showOSD("State " + slot + " loaded", true);
    }
    private SaveStateMedia media;
 

}
TOP

Related Classes of org.javatari.atari.console.Console$CartridgeSocketAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.