⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgbvideo.java

📁 一个用java写成的gb模拟器的源代码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * this source file released under the GNU Public Licence.
 * see the accompanying copyright.txt for more information.
 * Copyright (C) 2000-2001 Ben Mazur
 * modified by retroK 2004 http://aep-emu.de/
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * PgbVideo is responsible for the GameBoy video hardware.
 * 
 * Additionally, some SGB memory and functions are contained 
 * here.
 * 
 * It is abstract because it only makes sure that the VRAM,
 * etc., contain the proper values.  PgbVideoOutput classes
 * depend on the getScreenPixels, etc methods
 */
public abstract class PgbVideo {
	static final int	VBLANK_CYCLES	= 109;
	static final int	HBLANK_CYCLES	= 49;
	static final int	OAM_CYCLES		= 20;
	static final int	TRANSFER_CYCLES	= 40;
	
	static final byte	STAT_HBLANK		= 0;
	static final byte	STAT_VBLANK		= 1;
	static final byte	STAT_OAM		= 2;
	static final byte	STAT_TRANSFER	= 3;
	
	static final byte	INT_LYC			= 0x40;
	static final byte	INT_OAM			= 0x20;
	static final byte	INT_HBLANK		= 0x10;
	static final byte	INT_VBLANK		= 0x08;
	static final byte	INT_LYCMODE		= 0x04;
	
	// output
	PgbVideoOutput		vidout;

	// registers
	public int			scx;
	public int			scy;
	public int			ly;
	public int			lyc;
	public int			wx;
	public int			wy;
	
	// lcdc
	public boolean		lcd_on;
	public boolean		win_on;
	public boolean		win_mode;
	public boolean		chr_mode;
	public boolean		bg_mode;
	public boolean		obj_mode;
	public boolean		obj_on;
	public boolean		bg_on;
	public int			win_src;
	public int			bg_src;
	public int			obj_siz;
	public int			chr_src;
	
	// stat
	public boolean		int_lyc;
	public boolean		int_oam;
	public boolean		int_hblank;
	public boolean		int_vblank;
	public byte			stat_mode;
	
	// counters
	int					cycles;
	int					curframe;
	public long			framecount;
	
	// memory
	byte[]				vram;
	byte[]				oam;
	
	// regular gb palettes
	public int			bgpal;
	public int			objpal0;
	public int			objpal1;
	
	// SGB memory
	boolean				sgbvramon;
	byte				sgbPicture[];
	byte				sgbCharset[];
	byte				sgbPalette[];
	byte				sgbSystemPalette[];
	byte				sgbAtfData[];
	byte				sgbPaletteOverlay[];
	
	// color gb
	byte[]				gbcPalette;
	byte				gbcVram;
	int					vramOffset;
	byte				bgpi;
	byte				obpi;
	
	public PgbVideo() {
		// setup ram
		vram = new byte[0x4000];
		oam = new byte[0xA0];
		// sgb
		sgbPicture = new byte[0x1000];
		sgbCharset = new byte[0x4000];
		sgbPalette = new byte[0x20];
		sgbSystemPalette = new byte[0x1000];
		sgbAtfData = new byte[0x1800];
		sgbPaletteOverlay = new byte[90];
		// gbc
		gbcPalette = new byte[0x80];
	}
	
	public void reset() {
		int i;
		
		// blank ram
		for(i = 0; i < 0x4000; i++) {
			vram[i] = 0;
		}
		for(i = 0; i < 0xA0; i++) {
			oam[i] = 0;
		}
		
		// registers
		setLcdc((byte)0x91);
		setStat((byte)0x80);
		scy = 0;
		scx = 0;
		wx = 0;
		wy = 0;
		ly = 0;
		lyc = 0;		
		
		cycles = 0;
		curframe = 0;
		framecount = 0;
		
		// bgpal
		setBgPal(0xFC);
		setObjPal0(0xFF);
		setObjPal1(0xFF);
		
		// super GB
		sgbvramon = false;
		
		// gbc
		vramOffset = 0x8000;
		gbcVram = (byte)0x00;
		
		bgpi = (byte)0x00;
		obpi = (byte)0x00;
	}
	
	public byte read(int address) {
		// VRAM
		if(address >= 0x8000 && address < 0xA000) {
			return vram[address - vramOffset];
		}
		// OAM
		if(address >= 0xFE00 && address < 0xFEA0) {
			return oam[address - 0xFE00];
		}
		System.out.println("Read from unmapped video memory:" + Integer.toHexString(address));
		return 0;
	}
	
	public void write(int address, byte towrite) {
		/*
		// SGB
		if(sgbvramon) {
			System.out.print(Integer.toHexString(address & 0xFFFF) + ":" + Integer.toHexString(towrite & 0xFF) + " ");
		}
		*/
		// VRAM
		if(address >= 0x8000 && address < 0xA000) {
			vram[address - vramOffset] = towrite;
			return;
		}
		// OAM
		if(address >= 0xFE00 && address < 0xFEA0) {
			oam[address - 0xFE00] = towrite;
			return;
		}
		System.out.println("Write to unmapped video memory:" + Integer.toHexString(address) + ", " + Integer.toHexString(towrite));
	}
	
	/**
	 * how many cycles until the next possible interrupt?
	 */
	public int cyclesLeft() {
		return cycles;
	}
	
	/**
	 * this is called to update the LCD cycles
	 */
	public int cycle(int cy, PgbMemory pgbmemory) {
		byte interrupt = 0;
		cycles -= cy;
		if(cycles <= 0) {
			if(stat_mode == STAT_HBLANK || stat_mode == STAT_VBLANK) {
				if(++ly > 0x100) {
					ly = 0;	
				}
				if(ly < 0x90) {
					hblank();
					stat_mode = STAT_OAM;
					cycles = (int)(OAM_CYCLES * PgbSettings.clockspeed);
					interrupt |= int_hblank ? PgbMemory.INT_LCD : 0;
				} else {
					stat_mode = STAT_VBLANK;
					cycles = (int)(VBLANK_CYCLES * PgbSettings.clockspeed);
					if(ly == 0x90) {
						vblank();
						// by retroK:
						pgbmemory.soundPlay();
						interrupt |= int_vblank ? (PgbMemory.INT_LCD | PgbMemory.INT_VBLANK) : PgbMemory.INT_VBLANK;
					}
				}
				// coincidence interrupt
				if(ly == lyc) {
					interrupt |= int_lyc ? PgbMemory.INT_LCD : 0;
				}
				return interrupt;
			}
			if(stat_mode == STAT_OAM) {
				stat_mode = STAT_TRANSFER;
				cycles = (int)(TRANSFER_CYCLES * PgbSettings.clockspeed);
				interrupt |= int_oam ? PgbMemory.INT_LCD : 0;
				return interrupt;
			}
			if(stat_mode == STAT_TRANSFER) {
				stat_mode = STAT_HBLANK;
				cycles = (int)(HBLANK_CYCLES * PgbSettings.clockspeed);
				return interrupt;
			}
		}
		return 0;
	}
	
	public void hblank() {
		//if(lcd_on && curframe == 0 && (ly & 1) == (framecount & 1)) {
		if(lcd_on && curframe == 0) {
			vidout.hblank(ly);
		}
	}
	
	public void vblank() {
		framecount++;
		curframe--;
		if(curframe < 0) {
			curframe = PgbSettings.frameskip;
			vidout.vblank();
		}
	}
	
	public void setVideoOutput(PgbVideoOutput vidout) {
		this.vidout = vidout;
	}
	
	public abstract byte[]	getScreenMemory();
	public abstract byte	getScreenMemory(int index);
	public abstract byte	getScreenRed(byte index);
	public abstract byte	getScreenGreen(byte index);
	public abstract byte	getScreenBlue(byte index);
	public abstract int		getScreenColor(byte index);
	
	public void setBgPal(int pval) {
		//System.out.println("Change background palette: " + Integer.toHexString(pval));
		bgpal = pval;
	}
	public void setObjPal0(int pval) {
		//System.out.println("Change obj 0 palette: " + Integer.toHexString(pval));
		objpal0 = pval;
	}
	public void setObjPal1(int pval) {
		//System.out.println("Change obj 1 palette: " + Integer.toHexString(pval));
		objpal1 = pval;
	}
	
	public void setLcdc(byte lval) {
		boolean old_lcd = lcd_on;
		lcd_on		= (lval & 0x80) == 0x80;
		win_mode	= (lval & 0x40) == 0x40;
		win_on		= (lval & 0x20) == 0x20;
		chr_mode	= (lval & 0x10) == 0x10;
		bg_mode		= (lval & 0x08) == 0x08;
		obj_mode	= (lval & 0x04) == 0x04;
		obj_on		= (lval & 0x02) == 0x02;
		bg_on		= (lval & 0x01) == 0x01;

		win_src		= win_mode ? 0x9C00 : 0x9800;
		chr_src		= chr_mode ? 0x8000 : 0x8800;
		bg_src		= bg_mode ? 0x9C00 : 0x9800;
		obj_siz		= obj_mode ? 16 : 8;
		
		// reset ly when LCD goes off to on?

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -