May 30, 2008 version by emu_kidid

This commit is contained in:
dborth 2008-09-14 20:40:26 +00:00
commit 64546f8550
96 changed files with 54140 additions and 0 deletions

183
Makefile Normal file
View File

@ -0,0 +1,183 @@
#---------------------------------------------------------------------------------
# Generic makefile for Gamecube projects
#
# Tab stops set to 4
# | | | |
# 0 1 2 3
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
HAVEDIST := $(wildcard w)
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := vba172
BUILD := build
SOURCES := src/gb src src/fileio src/ngc
INCLUDES = -I$(DEVKITPRO)/libogc/include -I$(DEVKITPRO)/libfat/libogc/include src/gb src src/fileio src/ngc
LIBPATHS = -L$(DEVKITPRO)/libogc/lib/wii -L$(DEVKITPRO)/libfat/libogc/lib/wii
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
MACHDEP = -DGEKKO -mcpu=750 -meabi -mhard-float
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -meabi \
-DWORDS_BIGENDIAN -DPACKAGE=\"VisualBoyAdvance\" \
-DVERSION=\"1.7.2\" -DC_CORE -DHAVE_ZUTIL_H \
-DCHANFFS -DSDL -DWII_BUILD
LDFLAGS = $(MACHDEP) -mrvl -Wl,-Map,$(notdir $@).map -Wl,--cref
PREFIX := powerpc-gekko-
#export PATH:=/c/devkitPPC_r11/bin:/bin
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with
#---------------------------------------------------------------------------------
LIBS := -lm -lz -lfat -ldb -lwiiuse -lbte -logc
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) *.elf
#---------------------------------------------------------------------------------
run:
psoload $(TARGET).dol
#---------------------------------------------------------------------------------
reload:
psoload -r $(TARGET).dol
#---------------------------------------------------------------------------------
dist:
@echo Files : $(HAVEDIST)
ifeq ($(strip $(HAVEDIST)),)
rule:
@echo "No file"
else
rule2: A
@echo "Have File"
endif
bindist:
@[ -f $(TARGET).7z ] || rm $(TARGET).7z 2>/dev/null
@7z a -mx=9 -m0=lzma $(TARGET).7z $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
@echo "Output ... "$(notdir $@)
@$(OBJCOPY) -O binary $< $@
#---------------------------------------------------------------------------------
$(OUTPUT).elf: $(OFILES)
@echo "Linking ... "$(notdir $@)
@$(LD) $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
# Compile Targets for C/C++
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
%.o : %.cpp
@echo Compiling ... $(notdir $<)
@$(CXX) -MMD $(CFLAGS) -o $@ -c $<
#---------------------------------------------------------------------------------
%.o : %.c
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -o $@ -c $<
#---------------------------------------------------------------------------------
%.o : %.S
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
#---------------------------------------------------------------------------------
%.o : %.s
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
define bin2o
cp $(<) $(*).tmp
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc \
--rename-section .data=.rodata,readonly,data,contents,alloc \
--redefine-sym _binary_$*_tmp_start=$*\
--redefine-sym _binary_$*_tmp_end=$*_end\
--redefine-sym _binary_$*_tmp_size=$*_size\
$(*).tmp $(@)
echo "extern const u8" $(*)"[];" > $(*).h
echo "extern const u32" $(*)_size[]";" >> $(*).h
rm $(*).tmp
endef
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

183
Makefile.gc Normal file
View File

@ -0,0 +1,183 @@
#---------------------------------------------------------------------------------
# Generic makefile for Gamecube projects
#
# Tab stops set to 4
# | | | |
# 0 1 2 3
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
HAVEDIST := $(wildcard w)
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := vba172
BUILD := build
SOURCES := src/gb src src/fileio src/ngc
INCLUDES = -I$(DEVKITPRO)/libogc/include -I$(DEVKITPRO)/libfat/libogc/include src/gb src src/fileio src/ngc
LIBPATHS = -L$(DEVKITPRO)/libogc/lib/cube -L$(DEVKITPRO)/libfat/libogc/lib/cube
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
MACHDEP = -DGEKKO -mcpu=750 -meabi -mhard-float
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -meabi \
-DWORDS_BIGENDIAN -DPACKAGE=\"VisualBoyAdvance\" \
-DVERSION=\"1.7.2\" -DC_CORE -DHAVE_ZUTIL_H \
-DCHANFFS -DSDL -DGC_BUILD
LDFLAGS = $(MACHDEP) -mogc -Wl,-Map,$(notdir $@).map -Wl,--cref
PREFIX := powerpc-gekko-
#export PATH:=/c/devkitPPC_r11/bin:/bin
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with
#---------------------------------------------------------------------------------
LIBS := -logc -lz -lm -lfat -logc -lz -lm
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) *.elf
#---------------------------------------------------------------------------------
run:
psoload $(TARGET).dol
#---------------------------------------------------------------------------------
reload:
psoload -r $(TARGET).dol
#---------------------------------------------------------------------------------
dist:
@echo Files : $(HAVEDIST)
ifeq ($(strip $(HAVEDIST)),)
rule:
@echo "No file"
else
rule2: A
@echo "Have File"
endif
bindist:
@[ -f $(TARGET).7z ] || rm $(TARGET).7z 2>/dev/null
@7z a -mx=9 -m0=lzma $(TARGET).7z $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
@echo "Output ... "$(notdir $@)
@$(OBJCOPY) -O binary $< $@
#---------------------------------------------------------------------------------
$(OUTPUT).elf: $(OFILES)
@echo "Linking ... "$(notdir $@)
@$(LD) $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
# Compile Targets for C/C++
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
%.o : %.cpp
@echo Compiling ... $(notdir $<)
@$(CXX) -MMD $(CFLAGS) -o $@ -c $<
#---------------------------------------------------------------------------------
%.o : %.c
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -o $@ -c $<
#---------------------------------------------------------------------------------
%.o : %.S
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
#---------------------------------------------------------------------------------
%.o : %.s
@echo Compiling ... $(notdir $<)
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
define bin2o
cp $(<) $(*).tmp
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc \
--rename-section .data=.rodata,readonly,data,contents,alloc \
--redefine-sym _binary_$*_tmp_start=$*\
--redefine-sym _binary_$*_tmp_end=$*_end\
--redefine-sym _binary_$*_tmp_size=$*_size\
$(*).tmp $(@)
echo "extern const u8" $(*)"[];" > $(*).h
echo "extern const u32" $(*)_size[]";" >> $(*).h
rm $(*).tmp
endef
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

362
src/CheatSearch.cpp Normal file
View File

@ -0,0 +1,362 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdlib.h>
#include <string.h>
#include "CheatSearch.h"
CheatSearchBlock cheatSearchBlocks[4];
CheatSearchData cheatSearchData = {
0,
cheatSearchBlocks
};
static bool cheatSearchEQ(u32 a, u32 b)
{
return a == b;
}
static bool cheatSearchNE(u32 a, u32 b)
{
return a != b;
}
static bool cheatSearchLT(u32 a, u32 b)
{
return a < b;
}
static bool cheatSearchLE(u32 a, u32 b)
{
return a <= b;
}
static bool cheatSearchGT(u32 a, u32 b)
{
return a > b;
}
static bool cheatSearchGE(u32 a, u32 b)
{
return a >= b;
}
static bool cheatSearchSignedEQ(s32 a, s32 b)
{
return a == b;
}
static bool cheatSearchSignedNE(s32 a, s32 b)
{
return a != b;
}
static bool cheatSearchSignedLT(s32 a, s32 b)
{
return a < b;
}
static bool cheatSearchSignedLE(s32 a, s32 b)
{
return a <= b;
}
static bool cheatSearchSignedGT(s32 a, s32 b)
{
return a > b;
}
static bool cheatSearchSignedGE(s32 a, s32 b)
{
return a >= b;
}
static bool (*cheatSearchFunc[])(u32,u32) = {
cheatSearchEQ,
cheatSearchNE,
cheatSearchLT,
cheatSearchLE,
cheatSearchGT,
cheatSearchGE
};
static bool (*cheatSearchSignedFunc[])(s32,s32) = {
cheatSearchSignedEQ,
cheatSearchSignedNE,
cheatSearchSignedLT,
cheatSearchSignedLE,
cheatSearchSignedGT,
cheatSearchSignedGE
};
void cheatSearchCleanup(CheatSearchData *cs)
{
int count = cs->count;
for(int i = 0; i < count; i++)
{
free(cs->blocks[i].saved);
free(cs->blocks[i].bits);
}
cs->count = 0;
}
void cheatSearchStart(const CheatSearchData *cs)
{
int count = cs->count;
for(int i = 0; i < count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
memset(block->bits, 0xff, block->size >> 3);
memcpy(block->saved, block->data, block->size);
}
}
s32 cheatSearchSignedRead(u8 *data, int off, int size)
{
u32 res = data[off++];
switch(size)
{
case BITS_8:
res <<= 24;
return ((s32)res) >> 24;
case BITS_16:
res |= ((u32)data[off++])<<8;
res <<= 16;
return ((s32)res) >> 16;
case BITS_32:
res |= ((u32)data[off++])<<8;
res |= ((u32)data[off++])<<16;
res |= ((u32)data[off++])<<24;
return (s32)res;
}
return (s32)res;
}
u32 cheatSearchRead(u8 *data, int off, int size)
{
u32 res = data[off++];
if(size == BITS_16)
res |= ((u32)data[off++])<<8;
else if(size == BITS_32)
{
res |= ((u32)data[off++])<<8;
res |= ((u32)data[off++])<<16;
res |= ((u32)data[off++])<<24;
}
return res;
}
void cheatSearch(const CheatSearchData *cs, int compare, int size,
bool isSigned)
{
if(compare < 0 || compare > SEARCH_GE)
return;
int inc = 1;
if(size == BITS_16)
inc = 2;
else if(size == BITS_32)
inc = 4;
if(isSigned)
{
bool (*func)(s32,s32) = cheatSearchSignedFunc[compare];
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
u8 *saved = block->saved;
for(int j = 0; j < size2; j += inc)
{
if(IS_BIT_SET(bits, j))
{
s32 a = cheatSearchSignedRead(data, j, size);
s32 b = cheatSearchSignedRead(saved,j, size);
if(!func(a, b))
{
CLEAR_BIT(bits, j);
if(size == BITS_16)
CLEAR_BIT(bits, j+1);
if(size == BITS_32)
{
CLEAR_BIT(bits, j+2);
CLEAR_BIT(bits, j+3);
}
}
}
}
}
}
else
{
bool (*func)(u32,u32) = cheatSearchFunc[compare];
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
u8 *saved = block->saved;
for(int j = 0; j < size2; j += inc)
{
if(IS_BIT_SET(bits, j))
{
u32 a = cheatSearchRead(data, j, size);
u32 b = cheatSearchRead(saved,j, size);
if(!func(a, b))
{
CLEAR_BIT(bits, j);
if(size == BITS_16)
CLEAR_BIT(bits, j+1);
if(size == BITS_32)
{
CLEAR_BIT(bits, j+2);
CLEAR_BIT(bits, j+3);
}
}
}
}
}
}
}
void cheatSearchValue(const CheatSearchData *cs, int compare, int size,
bool isSigned, u32 value)
{
if(compare < 0 || compare > SEARCH_GE)
return;
int inc = 1;
if(size == BITS_16)
inc = 2;
else if(size == BITS_32)
inc = 4;
if(isSigned)
{
bool (*func)(s32,s32) = cheatSearchSignedFunc[compare];
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
for(int j = 0; j < size2; j += inc)
{
if(IS_BIT_SET(bits, j))
{
s32 a = cheatSearchSignedRead(data, j, size);
s32 b = (s32)value;
if(!func(a, b))
{
CLEAR_BIT(bits, j);
if(size == BITS_16)
CLEAR_BIT(bits, j+1);
if(size == BITS_32)
{
CLEAR_BIT(bits, j+2);
CLEAR_BIT(bits, j+3);
}
}
}
}
}
}
else
{
bool (*func)(u32,u32) = cheatSearchFunc[compare];
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
for(int j = 0; j < size2; j += inc)
{
if(IS_BIT_SET(bits, j))
{
u32 a = cheatSearchRead(data, j, size);
if(!func(a, value))
{
CLEAR_BIT(bits, j);
if(size == BITS_16)
CLEAR_BIT(bits, j+1);
if(size == BITS_32)
{
CLEAR_BIT(bits, j+2);
CLEAR_BIT(bits, j+3);
}
}
}
}
}
}
}
int cheatSearchGetCount(const CheatSearchData *cs, int size)
{
int res = 0;
int inc = 1;
if(size == BITS_16)
inc = 2;
else if(size == BITS_32)
inc = 4;
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
for(int j = 0; j < size2; j += inc)
{
if(IS_BIT_SET(bits, j))
res++;
}
}
return res;
}
void cheatSearchUpdateValues(const CheatSearchData *cs)
{
for(int i = 0; i < cs->count; i++)
{
CheatSearchBlock *block = &cs->blocks[i];
memcpy(block->saved, block->data, block->size);
}
}

75
src/CheatSearch.h Normal file
View File

@ -0,0 +1,75 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_CHEATSEARCH_H
#define VBA_CHEATSEARCH_H
#include "System.h"
struct CheatSearchBlock
{
int size;
u32 offset;
u8 *bits;
u8 *data;
u8 *saved;
};
struct CheatSearchData
{
int count;
CheatSearchBlock *blocks;
};
enum {
SEARCH_EQ,
SEARCH_NE,
SEARCH_LT,
SEARCH_LE,
SEARCH_GT,
SEARCH_GE
};
enum {
BITS_8,
BITS_16,
BITS_32
};
#define SET_BIT(bits,off) \
(bits)[(off) >> 3] |= (1 << ((off) & 7))
#define CLEAR_BIT(bits, off) \
(bits)[(off) >> 3] &= ~(1 << ((off) & 7))
#define IS_BIT_SET(bits, off) \
(bits)[(off) >> 3] & (1 << ((off) & 7))
extern CheatSearchData cheatSearchData;
extern void cheatSearchCleanup(CheatSearchData *cs);
extern void cheatSearchStart(const CheatSearchData *cs);
extern void cheatSearch(const CheatSearchData *cs, int compare, int size,
bool isSigned);
extern void cheatSearchValue(const CheatSearchData *cs, int compare, int size,
bool isSigned, u32 value);
extern int cheatSearchGetCount(const CheatSearchData *cs, int size);
extern void cheatSearchUpdateValues(const CheatSearchData *cs);
extern s32 cheatSearchSignedRead(u8 *data, int off, int size);
extern u32 cheatSearchRead(u8 *data, int off, int size);
#endif

1836
src/Cheats.cpp Normal file

File diff suppressed because it is too large Load Diff

55
src/Cheats.h Normal file
View File

@ -0,0 +1,55 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef GBA_CHEATS_H
#define GBA_CHEATS_H
struct CheatsData
{
int code;
int size;
int status;
bool enabled;
u32 address;
u32 value;
u32 oldValue;
char codestring[20];
char desc[32];
};
extern void cheatsAdd(const char *,const char *,u32,u32,int,int);
extern void cheatsAddCheatCode(const char *code, const char *desc);
extern void cheatsAddGSACode(const char *code, const char *desc, bool v3);
extern void cheatsAddCBACode(const char *code, const char *desc);
extern bool cheatsImportGSACodeFile(const char *name, int game, bool v3);
extern void cheatsDelete(int number, bool restore);
extern void cheatsDeleteAll(bool restore);
extern void cheatsEnable(int number);
extern void cheatsDisable(int number);
extern void cheatsSaveGame(gzFile file);
extern void cheatsReadGame(gzFile file);
extern void cheatsSaveCheatList(const char *file);
extern bool cheatsLoadCheatList(const char *file);
extern void cheatsWriteMemory(u32 *, u32, u32);
extern void cheatsWriteHalfWord(u16 *, u16, u16);
extern void cheatsWriteByte(u8 *, u8);
extern int cheatsCheckKeys(u32,u32);
extern int cheatsNumber;
extern CheatsData cheatsList[100];
#endif // GBA_CHEATS_H

214
src/EEprom.cpp Normal file
View File

@ -0,0 +1,214 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "EEprom.h"
#include "Util.h"
extern int cpuDmaCount;
int eepromMode = EEPROM_IDLE;
int eepromByte = 0;
int eepromBits = 0;
int eepromAddress = 0;
u8 eepromData[0x2000];
u8 eepromBuffer[16];
bool eepromInUse = false;
int eepromSize = 512;
variable_desc eepromSaveData[] = {
{ &eepromMode, sizeof(int) },
{ &eepromByte, sizeof(int) },
{ &eepromBits , sizeof(int) },
{ &eepromAddress , sizeof(int) },
{ &eepromInUse, sizeof(bool) },
{ &eepromData[0], 512 },
{ &eepromBuffer[0], 16 },
{ NULL, 0 }
};
void eepromReset()
{
eepromMode = EEPROM_IDLE;
eepromByte = 0;
eepromBits = 0;
eepromAddress = 0;
eepromInUse = false;
eepromSize = 512;
}
void eepromSaveGame(gzFile gzFile)
{
utilWriteData(gzFile, eepromSaveData);
utilWriteInt(gzFile, eepromSize);
utilGzWrite(gzFile, eepromData, 0x2000);
}
void eepromReadGame(gzFile gzFile, int version)
{
utilReadData(gzFile, eepromSaveData);
if(version >= SAVE_GAME_VERSION_3)
{
eepromSize = utilReadInt(gzFile);
utilGzRead(gzFile, eepromData, 0x2000);
}
else
{
// prior to 0.7.1, only 4K EEPROM was supported
eepromSize = 512;
}
}
int eepromRead(u32 /* address */)
{
switch(eepromMode)
{
case EEPROM_IDLE:
case EEPROM_READADDRESS:
case EEPROM_WRITEDATA:
return 1;
case EEPROM_READDATA:
{
eepromBits++;
if(eepromBits == 4)
{
eepromMode = EEPROM_READDATA2;
eepromBits = 0;
eepromByte = 0;
}
return 0;
}
case EEPROM_READDATA2:
{
int data = 0;
int address = eepromAddress << 3;
int mask = 1 << (7 - (eepromBits & 7));
data = (eepromData[address+eepromByte] & mask) ? 1 : 0;
eepromBits++;
if((eepromBits & 7) == 0)
eepromByte++;
if(eepromBits == 0x40)
eepromMode = EEPROM_IDLE;
return data;
}
default:
return 0;
}
return 1;
}
void eepromWrite(u32 /* address */, u8 value)
{
if(cpuDmaCount == 0)
return;
int bit = value & 1;
switch(eepromMode)
{
case EEPROM_IDLE:
eepromByte = 0;
eepromBits = 1;
eepromBuffer[eepromByte] = bit;
eepromMode = EEPROM_READADDRESS;
break;
case EEPROM_READADDRESS:
eepromBuffer[eepromByte] <<= 1;
eepromBuffer[eepromByte] |= bit;
eepromBits++;
if((eepromBits & 7) == 0)
{
eepromByte++;
}
if(cpuDmaCount == 0x11 || cpuDmaCount == 0x51)
{
if(eepromBits == 0x11)
{
eepromInUse = true;
eepromSize = 0x2000;
eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) |
((eepromBuffer[1] & 0xFF));
if(!(eepromBuffer[0] & 0x40))
{
eepromBuffer[0] = bit;
eepromBits = 1;
eepromByte = 0;
eepromMode = EEPROM_WRITEDATA;
}
else
{
eepromMode = EEPROM_READDATA;
eepromByte = 0;
eepromBits = 0;
}
}
}
else
{
if(eepromBits == 9)
{
eepromInUse = true;
eepromAddress = (eepromBuffer[0] & 0x3F);
if(!(eepromBuffer[0] & 0x40))
{
eepromBuffer[0] = bit;
eepromBits = 1;
eepromByte = 0;
eepromMode = EEPROM_WRITEDATA;
}
else
{
eepromMode = EEPROM_READDATA;
eepromByte = 0;
eepromBits = 0;
}
}
}
break;
case EEPROM_READDATA:
case EEPROM_READDATA2:
// should we reset here?
eepromMode = EEPROM_IDLE;
break;
case EEPROM_WRITEDATA:
eepromBuffer[eepromByte] <<= 1;
eepromBuffer[eepromByte] |= bit;
eepromBits++;
if((eepromBits & 7) == 0)
{
eepromByte++;
}
if(eepromBits == 0x40)
{
eepromInUse = true;
// write data;
for(int i = 0; i < 8; i++)
{
eepromData[(eepromAddress << 3) + i] = eepromBuffer[i];
}
systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
}
else if(eepromBits == 0x41)
{
eepromMode = EEPROM_IDLE;
eepromByte = 0;
eepromBits = 0;
}
break;
}
}

38
src/EEprom.h Normal file
View File

@ -0,0 +1,38 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_EEPROM_H
#define VBA_EEPROM_H
extern void eepromSaveGame(gzFile gzFile);
extern void eepromReadGame(gzFile gzFile, int version);
extern int eepromRead(u32 address);
extern void eepromWrite(u32 address, u8 value);
extern void eepromReset();
extern u8 eepromData[0x2000];
extern bool eepromInUse;
extern int eepromSize;
#define EEPROM_IDLE 0
#define EEPROM_READADDRESS 1
#define EEPROM_READDATA 2
#define EEPROM_READDATA2 3
#define EEPROM_WRITEDATA 4
#endif // VBA_EEPROM_H

288
src/Flash.cpp Normal file
View File

@ -0,0 +1,288 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <string.h>
#include "GBA.h"
#include "Globals.h"
#include "Flash.h"
#include "Sram.h"
#include "Util.h"
#define FLASH_READ_ARRAY 0
#define FLASH_CMD_1 1
#define FLASH_CMD_2 2
#define FLASH_AUTOSELECT 3
#define FLASH_CMD_3 4
#define FLASH_CMD_4 5
#define FLASH_CMD_5 6
#define FLASH_ERASE_COMPLETE 7
#define FLASH_PROGRAM 8
#define FLASH_SETBANK 9
u8 flashSaveMemory[0x20000];
int flashState = FLASH_READ_ARRAY;
int flashReadState = FLASH_READ_ARRAY;
int flashSize = 0x10000;
int flashDeviceID = 0x1b;
int flashManufacturerID = 0x32;
int flashBank = 0;
static variable_desc flashSaveData[] = {
{ &flashState, sizeof(int) },
{ &flashReadState, sizeof(int) },
{ &flashSaveMemory[0], 0x10000 },
{ NULL, 0 }
};
static variable_desc flashSaveData2[] = {
{ &flashState, sizeof(int) },
{ &flashReadState, sizeof(int) },
{ &flashSize, sizeof(int) },
{ &flashSaveMemory[0], 0x20000 },
{ NULL, 0 }
};
static variable_desc flashSaveData3[] = {
{ &flashState, sizeof(int) },
{ &flashReadState, sizeof(int) },
{ &flashSize, sizeof(int) },
{ &flashBank, sizeof(int) },
{ &flashSaveMemory[0], 0x20000 },
{ NULL, 0 }
};
void flashReset()
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
flashBank = 0;
}
void flashSaveGame(gzFile gzFile)
{
utilWriteData(gzFile, flashSaveData3);
}
void flashReadGame(gzFile gzFile, int version)
{
if(version < SAVE_GAME_VERSION_5)
utilReadData(gzFile, flashSaveData);
else if(version < SAVE_GAME_VERSION_7)
{
utilReadData(gzFile, flashSaveData2);
flashBank = 0;
flashSetSize(flashSize);
}
else
{
utilReadData(gzFile, flashSaveData3);
}
}
void flashSetSize(int size)
{
// log("Setting flash size to %d\n", size);
flashSize = size;
if(size == 0x10000)
{
flashDeviceID = 0x1b;
flashManufacturerID = 0x32;
}
else
{
flashDeviceID = 0x13; //0x09;
flashManufacturerID = 0x62; //0xc2;
}
}
u8 flashRead(u32 address)
{
// log("Reading %08x from %08x\n", address, reg[15].I);
// log("Current read state is %d\n", flashReadState);
address &= 0xFFFF;
switch(flashReadState)
{
case FLASH_READ_ARRAY:
return flashSaveMemory[(flashBank << 16) + address];
case FLASH_AUTOSELECT:
switch(address & 0xFF)
{
case 0:
// manufacturer ID
return flashManufacturerID;
case 1:
// device ID
return flashDeviceID;
}
break;
case FLASH_ERASE_COMPLETE:
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
return 0xFF;
};
return 0;
}
void flashSaveDecide(u32 address, u8 byte)
{
// log("Deciding save type %08x\n", address);
if(address == 0x0e005555)
{
saveType = 2;
cpuSaveGameFunc = flashWrite;
}
else
{
saveType = 1;
cpuSaveGameFunc = sramWrite;
}
(*cpuSaveGameFunc)(address, byte);
}
void flashWrite(u32 address, u8 byte)
{
// log("Writing %02x at %08x\n", byte, address);
// log("Current state is %d\n", flashState);
address &= 0xFFFF;
switch(flashState)
{
case FLASH_READ_ARRAY:
if(address == 0x5555 && byte == 0xAA)
flashState = FLASH_CMD_1;
break;
case FLASH_CMD_1:
if(address == 0x2AAA && byte == 0x55)
flashState = FLASH_CMD_2;
else
flashState = FLASH_READ_ARRAY;
break;
case FLASH_CMD_2:
if(address == 0x5555)
{
if(byte == 0x90)
{
flashState = FLASH_AUTOSELECT;
flashReadState = FLASH_AUTOSELECT;
}
else if(byte == 0x80)
{
flashState = FLASH_CMD_3;
}
else if(byte == 0xF0)
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
else if(byte == 0xA0)
{
flashState = FLASH_PROGRAM;
}
else if(byte == 0xB0 && flashSize == 0x20000)
{
flashState = FLASH_SETBANK;
}
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
}
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
break;
case FLASH_CMD_3:
if(address == 0x5555 && byte == 0xAA)
{
flashState = FLASH_CMD_4;
}
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
break;
case FLASH_CMD_4:
if(address == 0x2AAA && byte == 0x55)
{
flashState = FLASH_CMD_5;
}
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
break;
case FLASH_CMD_5:
if(byte == 0x30)
{
// SECTOR ERASE
memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)],
0,
0x1000);
systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
flashReadState = FLASH_ERASE_COMPLETE;
}
else if(byte == 0x10)
{
// CHIP ERASE
memset(flashSaveMemory, 0, flashSize);
systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
flashReadState = FLASH_ERASE_COMPLETE;
}
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
break;
case FLASH_AUTOSELECT:
if(byte == 0xF0)
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
else if(address == 0x5555 && byte == 0xAA)
flashState = FLASH_CMD_1;
else
{
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
}
break;
case FLASH_PROGRAM:
flashSaveMemory[(flashBank<<16)+address] = byte;
systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
break;
case FLASH_SETBANK:
if(address == 0)
{
flashBank = (byte & 1);
}
flashState = FLASH_READ_ARRAY;
flashReadState = FLASH_READ_ARRAY;
break;
}
}

33
src/Flash.h Normal file
View File

@ -0,0 +1,33 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_FLASH_H
#define VBA_FLASH_H
extern void flashSaveGame(gzFile gzFile);
extern void flashReadGame(gzFile gzFile, int version);
extern u8 flashRead(u32 address);
extern void flashWrite(u32 address, u8 byte);
extern u8 flashSaveMemory[0x20000];
extern void flashSaveDecide(u32 address, u8 byte);
extern void flashReset();
extern void flashSetSize(int size);
extern int flashSize;
#endif // VBA_FLASH_H

4360
src/GBA.cpp Normal file

File diff suppressed because it is too large Load Diff

153
src/GBA.h Normal file
View File

@ -0,0 +1,153 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_GBA_H
#define VBA_GBA_H
#include "System.h"
#define SAVE_GAME_VERSION_1 1
#define SAVE_GAME_VERSION_2 2
#define SAVE_GAME_VERSION_3 3
#define SAVE_GAME_VERSION_4 4
#define SAVE_GAME_VERSION_5 5
#define SAVE_GAME_VERSION_6 6
#define SAVE_GAME_VERSION_7 7
#define SAVE_GAME_VERSION_8 8
#define SAVE_GAME_VERSION SAVE_GAME_VERSION_8
typedef struct
{
u8 *address;
u32 mask;
}
memoryMap;
typedef union {
struct
{
#ifdef WORDS_BIGENDIAN
u8 B3;
u8 B2;
u8 B1;
u8 B0;
#else
u8 B0;
u8 B1;
u8 B2;
u8 B3;
#endif
}
B;
struct
{
#ifdef WORDS_BIGENDIAN
u16 W1;
u16 W0;
#else
u16 W0;
u16 W1;
#endif
}
W;
#ifdef WORDS_BIGENDIAN
volatile u32 I;
#else
u32 I;
#endif
} reg_pair;
#ifndef NO_GBA_MAP
extern memoryMap map[256];
#endif
extern reg_pair reg[45];
extern u8 biosProtected[4];
extern bool N_FLAG;
extern bool Z_FLAG;
extern bool C_FLAG;
extern bool V_FLAG;
extern bool armIrqEnable;
extern bool armState;
extern int armMode;
extern void (*cpuSaveGameFunc)(u32,u8);
extern bool freezeWorkRAM[0x40000];
extern bool freezeInternalRAM[0x8000];
extern bool CPUReadGSASnapshot(const char *);
extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
extern bool CPUWriteBatteryFile(const char *);
extern bool CPUReadBatteryFile(const char *);
extern bool CPUExportEepromFile(const char *);
extern bool CPUImportEepromFile(const char *);
extern bool CPUWritePNGFile(const char *);
extern bool CPUWriteBMPFile(const char *);
extern void CPUCleanUp();
extern void CPUUpdateRender();
extern bool CPUReadMemState(char *, int);
extern bool CPUReadState(const char *);
extern bool CPUWriteMemState(char *, int);
extern bool CPUWriteState(const char *);
extern int CPULoadRom(const char *);
extern void CPUUpdateRegister(u32, u16);
extern void CPUWriteHalfWord(u32, u16);
extern void CPUWriteByte(u32, u8);
extern void CPUInit(const char *,bool);
extern void CPUReset();
extern void CPULoop(int);
extern void CPUCheckDMA(int,int);
extern bool CPUIsGBAImage(const char *);
extern bool CPUIsZipFile(const char *);
#ifdef PROFILING
extern void cpuProfil(char *buffer, int, u32, int);
extern void cpuEnableProfiling(int hz);
#endif
extern struct EmulatedSystem GBASystem;
#define R13_IRQ 18
#define R14_IRQ 19
#define SPSR_IRQ 20
#define R13_USR 26
#define R14_USR 27
#define R13_SVC 28
#define R14_SVC 29
#define SPSR_SVC 30
#define R13_ABT 31
#define R14_ABT 32
#define SPSR_ABT 33
#define R13_UND 34
#define R14_UND 35
#define SPSR_UND 36
#define R8_FIQ 37
#define R9_FIQ 38
#define R10_FIQ 39
#define R11_FIQ 40
#define R12_FIQ 41
#define R13_FIQ 42
#define R14_FIQ 43
#define SPSR_FIQ 44
#include "Cheats.h"
#include "Globals.h"
#include "EEprom.h"
#include "Flash.h"
#endif //VBA_GBA_H

556
src/GBAinline.h Normal file
View File

@ -0,0 +1,556 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_GBAinline_H
#define VBA_GBAinline_H
#include "System.h"
#include "Port.h"
#include "RTC.h"
#include "vmmem.h"
extern bool cpuSramEnabled;
extern bool cpuFlashEnabled;
extern bool cpuEEPROMEnabled;
extern bool cpuEEPROMSensorEnabled;
#define VM_USED 1
#define CPUReadByteQuickDef(addr) \
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
#define CPUReadHalfWordQuickDef(addr) \
READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
#define CPUReadMemoryQuickDef(addr) \
READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
u8 inline CPUReadByteQuick( u32 addr )
{
switch(addr >> 24 )
{
case 8:
case 9:
case 10:
case 12:
return VMRead8( addr & 0x1FFFFFF );
default:
return CPUReadByteQuickDef(addr);
}
return 0;
}
u16 inline CPUReadHalfWordQuick( u32 addr )
{
switch(addr >> 24)
{
case 8:
case 9:
case 10:
case 12:
return VMRead16( addr & 0x1FFFFFF );
default:
return CPUReadHalfWordQuickDef(addr);
}
return 0;
}
u32 inline CPUReadMemoryQuick( u32 addr )
{
switch(addr >> 24)
{
case 8:
case 9:
case 10:
case 12:
return VMRead32( addr & 0x1FFFFFF );
default:
return CPUReadMemoryQuickDef(addr);
}
return 0;
}
inline u32 CPUReadMemory(u32 address)
{
#ifdef DEV_VERSION
if(address & 3)
{
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY)
{
log("Unaligned word read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
}
#endif
u32 value;
switch(address >> 24)
{
case 0:
if(reg[15].I >> 24)
{
if(address < 0x4000)
{
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal word read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
value = READ32LE(((u32 *)&biosProtected));
}
else goto unreadable;
}
else
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
break;
case 2:
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
break;
case 3:
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
break;
case 4:
if((address < 0x4000400) && ioReadable[address & 0x3fc])
{
if(ioReadable[(address & 0x3fc) + 2])
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
else
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
}
else goto unreadable;
break;
case 5:
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
break;
case 6:
value = READ32LE(((u32 *)&vram[address & 0x1fffc]));
break;
case 7:
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
break;
case 8:
case 9:
case 10:
case 11:
case 12:
/** Need NGC VM here **/
//value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
value = VMRead32( address & 0x1FFFFFC );
break;
case 13:
if(cpuEEPROMEnabled)
// no need to swap this
return eepromRead(address);
goto unreadable;
case 14:
if(cpuFlashEnabled | cpuSramEnabled)
// no need to swap this
return flashRead(address);
// default
default:
unreadable:
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal word read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
// if(ioMem[0x205] & 0x40) {
if(armState)
{
#if VM_USED
value = CPUReadMemoryQuick(reg[15].I);
#else
value = CPUReadMemoryQuickDef(reg[15].I);
#endif
//value = VMRead32(reg[15].I);
}
else
{
#if VM_USED
value = CPUReadHalfWordQuick(reg[15].I) |
CPUReadHalfWordQuick(reg[15].I) << 16;
#else
value = CPUReadHalfWordQuickDef(reg[15].I) |
CPUReadHalfWordQuickDef(reg[15].I) << 16;
#endif
//value = VMRead16(reg[15].I) | VMRead16(reg[15].I) << 16;
}
// } else {
// value = *((u32 *)&bios[address & 0x3ffc]);
// }
// return 0xFFFFFFFF;
}
if(address & 3)
{
#ifdef C_CORE
int shift = (address & 3) << 3;
value = (value >> shift) | (value << (32 - shift));
#else
#ifdef __GNUC__
asm("and $3, %%ecx;"
"shl $3 ,%%ecx;"
"ror %%cl, %0"
: "=r" (value)
: "r" (value), "c" (address));
#else
__asm {
mov ecx, address;
and ecx, 3;
shl ecx, 3;
ror [dword ptr value], cl;
}
#endif
#endif
}
return value;
}
extern u32 myROM[];
inline u32 CPUReadHalfWord(u32 address)
{
#ifdef DEV_VERSION
if(address & 1)
{
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY)
{
log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
}
#endif
u32 value;
switch(address >> 24)
{
case 0:
if (reg[15].I >> 24)
{
if(address < 0x4000)
{
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
value = READ16LE(((u16 *)&biosProtected[address&2]));
}
else goto unreadable;
}
else
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
break;
case 2:
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
break;
case 3:
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
break;
case 4:
if((address < 0x4000400) && ioReadable[address & 0x3fe])
value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
else goto unreadable;
break;
case 5:
value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
break;
case 6:
value = READ16LE(((u16 *)&vram[address & 0x1fffe]));
break;
case 7:
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
break;
case 8:
case 9:
case 10:
case 11:
case 12:
if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
value = rtcRead(address);
else
/** Need NGC VM Here **/
//value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
value = VMRead16( address & 0x1FFFFFE );
break;
case 13:
if(cpuEEPROMEnabled)
// no need to swap this
return eepromRead(address);
goto unreadable;
case 14:
if(cpuFlashEnabled | cpuSramEnabled)
// no need to swap this
return flashRead(address);
// default
default:
unreadable:
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
extern bool cpuDmaHack;
extern u32 cpuDmaLast;
extern int cpuDmaCount;
if(cpuDmaHack && cpuDmaCount)
{
value = (u16)cpuDmaLast;
}
else
{
if(armState)
{
#if VM_USED
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
#else
value = CPUReadHalfWordQuickDef(reg[15].I + (address & 2));
#endif
//value = VMRead16(reg[15].I + (address & 2));
}
else
{
#if VM_USED
value = CPUReadHalfWordQuick(reg[15].I);
#else
value = CPUReadHalfWordQuickDef(reg[15].I);
#endif
//value = VMRead16(reg[15].I);
}
}
// return value;
// if(address & 1)
// value = (value >> 8) | ((value & 0xFF) << 24);
// return 0xFFFF;
break;
}
if(address & 1)
{
value = (value >> 8) | (value << 24);
}
return value;
}
inline u16 CPUReadHalfWordSigned(u32 address)
{
u16 value = CPUReadHalfWord(address);
if((address & 1))
value = (s8)value;
return value;
}
inline u8 CPUReadByte(u32 address)
{
switch(address >> 24)
{
case 0:
if (reg[15].I >> 24)
{
if(address < 0x4000)
{
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal byte read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
return biosProtected[address & 3];
}
else goto unreadable;
}
return bios[address & 0x3FFF];
case 2:
return workRAM[address & 0x3FFFF];
case 3:
return internalRAM[address & 0x7fff];
case 4:
if((address < 0x4000400) && ioReadable[address & 0x3ff])
return ioMem[address & 0x3ff];
else goto unreadable;
case 5:
return paletteRAM[address & 0x3ff];
case 6:
return vram[address & 0x1ffff];
case 7:
return oam[address & 0x3ff];
case 8:
case 9:
case 10:
case 11:
case 12:
/** Need NGC VM Here **/
//return rom[address & 0x1FFFFFF];
return VMRead8( address & 0x1FFFFFF );
case 13:
if(cpuEEPROMEnabled)
return eepromRead(address);
goto unreadable;
case 14:
if(cpuSramEnabled | cpuFlashEnabled)
return flashRead(address);
if(cpuEEPROMSensorEnabled)
{
switch(address & 0x00008f00)
{
case 0x8200:
return systemGetSensorX() & 255;
case 0x8300:
return (systemGetSensorX() >> 8)|0x80;
case 0x8400:
return systemGetSensorY() & 255;
case 0x8500:
return systemGetSensorY() >> 8;
}
}
// default
default:
unreadable:
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_READ)
{
log("Illegal byte read: %08x at %08x\n", address, armMode ?
armNextPC - 4 : armNextPC - 2);
}
#endif
if(armState)
{
#if VM_USED
return CPUReadByteQuick(reg[15].I+(address & 3));
#else
return CPUReadByteQuickDef(reg[15].I+(address & 3));
#endif
//return VMRead8(reg[15].I+(address & 3));
}
else
{
#if VM_USED
return CPUReadByteQuick(reg[15].I+(address & 1));
#else
return CPUReadByteQuickDef(reg[15].I+(address & 1));
#endif
//return VMRead8(reg[15].I+(address & 1));
}
// return 0xFF;
break;
}
}
inline void CPUWriteMemory(u32 address, u32 value)
{
#ifdef DEV_VERSION
if(address & 3)
{
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY)
{
log("Unaliagned word write: %08x to %08x from %08x\n",
value,
address,
armMode ? armNextPC - 4 : armNextPC - 2);
}
}
#endif
switch(address >> 24)
{
case 0x02:
#ifdef SDL
if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC],
value,
*((u32 *)&freezeWorkRAM[address & 0x3FFFC]));
else
#endif
WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
break;
case 0x03:
#ifdef SDL
if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC],
value,
*((u32 *)&freezeInternalRAM[address & 0x7ffc]));
else
#endif
WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
break;
case 0x04:
CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
break;
case 0x05:
WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
break;
case 0x06:
if(address & 0x10000)
WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value);
else
WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value);
break;
case 0x07:
WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
break;
case 0x0D:
if(cpuEEPROMEnabled)
{
eepromWrite(address, value);
break;
}
goto unwritable;
case 0x0E:
if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled)
{
(*cpuSaveGameFunc)(address, (u8)value);
break;
}
// default
default:
unwritable:
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_ILLEGAL_WRITE)
{
log("Illegal word write: %08x to %08x from %08x\n",
value,
address,
armMode ? armNextPC - 4 : armNextPC - 2);
}
#endif
break;
}
}
#endif //VBA_GBAinline_H

47
src/Gfx.cpp Normal file
View File

@ -0,0 +1,47 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
int coeff[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
u32 line0[240];
u32 line1[240];
u32 line2[240];
u32 line3[240];
u32 lineOBJ[240];
u32 lineOBJWin[240];
u32 lineMix[240];
bool gfxInWin0[240];
bool gfxInWin1[240];
int gfxBG2Changed = 0;
int gfxBG3Changed = 0;
int gfxBG2X = 0;
int gfxBG2Y = 0;
int gfxBG2LastX = 0;
int gfxBG2LastY = 0;
int gfxBG3X = 0;
int gfxBG3Y = 0;
int gfxBG3LastX = 0;
int gfxBG3LastY = 0;
int gfxLastVCOUNT = 0;

1809
src/Gfx.h Normal file

File diff suppressed because it is too large Load Diff

135
src/Globals.cpp Normal file
View File

@ -0,0 +1,135 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
reg_pair reg[45];
memoryMap map[256];
bool ioReadable[0x400];
bool N_FLAG = 0;
bool C_FLAG = 0;
bool Z_FLAG = 0;
bool V_FLAG = 0;
bool armState = true;
bool armIrqEnable = true;
u32 armNextPC = 0x00000000;
int armMode = 0x1f;
u32 stop = 0x08000568;
int saveType = 0;
bool useBios = false;
bool skipBios = false;
int frameSkip = 1;
bool speedup = false;
bool synchronize = true;
bool cpuDisableSfx = false;
bool cpuIsMultiBoot = false;
bool parseDebug = true;
int layerSettings = 0xff00;
int layerEnable = 0xff00;
bool speedHack = false;
int cpuSaveType = 0;
bool cpuEnhancedDetection = true;
bool cheatsEnabled = true;
u8 *bios = NULL;
u8 *rom = NULL;
u8 *internalRAM = NULL;
u8 *workRAM = NULL;
u8 *paletteRAM = NULL;
u8 *vram = NULL;
u8 *pix = NULL;
u8 *oam = NULL;
u8 *ioMem = NULL;
u16 DISPCNT = 0x0080;
u16 DISPSTAT = 0x0000;
u16 VCOUNT = 0x0000;
u16 BG0CNT = 0x0000;
u16 BG1CNT = 0x0000;
u16 BG2CNT = 0x0000;
u16 BG3CNT = 0x0000;
u16 BG0HOFS = 0x0000;
u16 BG0VOFS = 0x0000;
u16 BG1HOFS = 0x0000;
u16 BG1VOFS = 0x0000;
u16 BG2HOFS = 0x0000;
u16 BG2VOFS = 0x0000;
u16 BG3HOFS = 0x0000;
u16 BG3VOFS = 0x0000;
u16 BG2PA = 0x0100;
u16 BG2PB = 0x0000;
u16 BG2PC = 0x0000;
u16 BG2PD = 0x0100;
u16 BG2X_L = 0x0000;
u16 BG2X_H = 0x0000;
u16 BG2Y_L = 0x0000;
u16 BG2Y_H = 0x0000;
u16 BG3PA = 0x0100;
u16 BG3PB = 0x0000;
u16 BG3PC = 0x0000;
u16 BG3PD = 0x0100;
u16 BG3X_L = 0x0000;
u16 BG3X_H = 0x0000;
u16 BG3Y_L = 0x0000;
u16 BG3Y_H = 0x0000;
u16 WIN0H = 0x0000;
u16 WIN1H = 0x0000;
u16 WIN0V = 0x0000;
u16 WIN1V = 0x0000;
u16 WININ = 0x0000;
u16 WINOUT = 0x0000;
u16 MOSAIC = 0x0000;
u16 BLDMOD = 0x0000;
u16 COLEV = 0x0000;
u16 COLY = 0x0000;
u16 DM0SAD_L = 0x0000;
u16 DM0SAD_H = 0x0000;
u16 DM0DAD_L = 0x0000;
u16 DM0DAD_H = 0x0000;
u16 DM0CNT_L = 0x0000;
u16 DM0CNT_H = 0x0000;
u16 DM1SAD_L = 0x0000;
u16 DM1SAD_H = 0x0000;
u16 DM1DAD_L = 0x0000;
u16 DM1DAD_H = 0x0000;
u16 DM1CNT_L = 0x0000;
u16 DM1CNT_H = 0x0000;
u16 DM2SAD_L = 0x0000;
u16 DM2SAD_H = 0x0000;
u16 DM2DAD_L = 0x0000;
u16 DM2DAD_H = 0x0000;
u16 DM2CNT_L = 0x0000;
u16 DM2CNT_H = 0x0000;
u16 DM3SAD_L = 0x0000;
u16 DM3SAD_H = 0x0000;
u16 DM3DAD_L = 0x0000;
u16 DM3DAD_H = 0x0000;
u16 DM3CNT_L = 0x0000;
u16 DM3CNT_H = 0x0000;
u16 TM0D = 0x0000;
u16 TM0CNT = 0x0000;
u16 TM1D = 0x0000;
u16 TM1CNT = 0x0000;
u16 TM2D = 0x0000;
u16 TM2CNT = 0x0000;
u16 TM3D = 0x0000;
u16 TM3CNT = 0x0000;
u16 P1 = 0xFFFF;
u16 IE = 0x0000;
u16 IF = 0x0000;
u16 IME = 0x0000;

149
src/Globals.h Normal file
View File

@ -0,0 +1,149 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_GLOBALS_H
#define VBA_GLOBALS_H
#define VERBOSE_SWI 1
#define VERBOSE_UNALIGNED_MEMORY 2
#define VERBOSE_ILLEGAL_WRITE 4
#define VERBOSE_ILLEGAL_READ 8
#define VERBOSE_DMA0 16
#define VERBOSE_DMA1 32
#define VERBOSE_DMA2 64
#define VERBOSE_DMA3 128
#define VERBOSE_UNDEFINED 256
#define VERBOSE_AGBPRINT 512
extern reg_pair reg[45];
extern bool ioReadable[0x400];
extern bool N_FLAG;
extern bool C_FLAG;
extern bool Z_FLAG;
extern bool V_FLAG;
extern bool armState;
extern bool armIrqEnable;
extern u32 armNextPC;
extern int armMode;
extern u32 stop;
extern int saveType;
extern bool useBios;
extern bool skipBios;
extern int frameSkip;
extern bool speedup;
extern bool synchronize;
extern bool cpuDisableSfx;
extern bool cpuIsMultiBoot;
extern bool parseDebug;
extern int layerSettings;
extern int layerEnable;
extern bool speedHack;
extern int cpuSaveType;
extern bool cpuEnhancedDetection;
extern bool cheatsEnabled;
extern u8 *bios;
extern u8 *rom;
extern u8 *internalRAM;
extern u8 *workRAM;
extern u8 *paletteRAM;
extern u8 *vram;
extern u8 *pix;
extern u8 *oam;
extern u8 *ioMem;
extern u16 DISPCNT;
extern u16 DISPSTAT;
extern u16 VCOUNT;
extern u16 BG0CNT;
extern u16 BG1CNT;
extern u16 BG2CNT;
extern u16 BG3CNT;
extern u16 BG0HOFS;
extern u16 BG0VOFS;
extern u16 BG1HOFS;
extern u16 BG1VOFS;
extern u16 BG2HOFS;
extern u16 BG2VOFS;
extern u16 BG3HOFS;
extern u16 BG3VOFS;
extern u16 BG2PA;
extern u16 BG2PB;
extern u16 BG2PC;
extern u16 BG2PD;
extern u16 BG2X_L;
extern u16 BG2X_H;
extern u16 BG2Y_L;
extern u16 BG2Y_H;
extern u16 BG3PA;
extern u16 BG3PB;
extern u16 BG3PC;
extern u16 BG3PD;
extern u16 BG3X_L;
extern u16 BG3X_H;
extern u16 BG3Y_L;
extern u16 BG3Y_H;
extern u16 WIN0H;
extern u16 WIN1H;
extern u16 WIN0V;
extern u16 WIN1V;
extern u16 WININ;
extern u16 WINOUT;
extern u16 MOSAIC;
extern u16 BLDMOD;
extern u16 COLEV;
extern u16 COLY;
extern u16 DM0SAD_L;
extern u16 DM0SAD_H;
extern u16 DM0DAD_L;
extern u16 DM0DAD_H;
extern u16 DM0CNT_L;
extern u16 DM0CNT_H;
extern u16 DM1SAD_L;
extern u16 DM1SAD_H;
extern u16 DM1DAD_L;
extern u16 DM1DAD_H;
extern u16 DM1CNT_L;
extern u16 DM1CNT_H;
extern u16 DM2SAD_L;
extern u16 DM2SAD_H;
extern u16 DM2DAD_L;
extern u16 DM2DAD_H;
extern u16 DM2CNT_L;
extern u16 DM2CNT_H;
extern u16 DM3SAD_L;
extern u16 DM3SAD_H;
extern u16 DM3DAD_L;
extern u16 DM3DAD_H;
extern u16 DM3CNT_L;
extern u16 DM3CNT_H;
extern u16 TM0D;
extern u16 TM0CNT;
extern u16 TM1D;
extern u16 TM1CNT;
extern u16 TM2D;
extern u16 TM2CNT;
extern u16 TM3D;
extern u16 TM3CNT;
extern u16 P1;
extern u16 IE;
extern u16 IF;
extern u16 IME;
#endif // VBA_GLOBALS_H

652
src/Mode0.cpp Normal file
View File

@ -0,0 +1,652 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Globals.h"
#include "Gfx.h"
void mode0RenderLine()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
return;
}
if(layerEnable & 0x0100)
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if(layerEnable & 0x0200)
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if(layerEnable & 0x0400)
{
gfxDrawTextScreen(BG2CNT, BG2HOFS, BG2VOFS, line2);
}
if(layerEnable & 0x0800)
{
gfxDrawTextScreen(BG3CNT, BG3HOFS, BG3VOFS, line3);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line0[x] < color)
{
color = line0[x];
top = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(color >> 24))
{
color = line1[x];
top = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(color >> 24))
{
color = line2[x];
top = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(color >> 24))
{
color = line3[x];
top = 0x08;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line0[x]>>24) < (u8)(back >> 24))
{
back = line0[x];
top2 = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(back >> 24))
{
back = line1[x];
top2 = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(back >> 24))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
}
void mode0RenderLineNoWindow()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
return;
}
if(layerEnable & 0x0100)
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if(layerEnable & 0x0200)
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if(layerEnable & 0x0400)
{
gfxDrawTextScreen(BG2CNT, BG2HOFS, BG2VOFS, line2);
}
if(layerEnable & 0x0800)
{
gfxDrawTextScreen(BG3CNT, BG3HOFS, BG3VOFS, line3);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
int effect = (BLDMOD >> 6) & 3;
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line0[x] < color)
{
color = line0[x];
top = 0x01;
}
if(line1[x] < (color & 0xFF000000))
{
color = line1[x];
top = 0x02;
}
if(line2[x] < (color & 0xFF000000))
{
color = line2[x];
top = 0x04;
}
if(line3[x] < (color & 0xFF000000))
{
color = line3[x];
top = 0x08;
}
if(lineOBJ[x] < (color & 0xFF000000))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch(effect)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if(line0[x] < back)
{
if(top != 0x01)
{
back = line0[x];
top2 = 0x01;
}
}
if(line1[x] < (back & 0xFF000000))
{
if(top != 0x02)
{
back = line1[x];
top2 = 0x02;
}
}
if(line2[x] < (back & 0xFF000000))
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if(line3[x] < (back & 0xFF000000))
{
if(top != 0x08)
{
back = line3[x];
top2 = 0x08;
}
}
if(lineOBJ[x] < (back & 0xFF000000))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if(line0[x] < back)
{
back = line0[x];
top2 = 0x01;
}
if(line1[x] < (back & 0xFF000000))
{
back = line1[x];
top2 = 0x02;
}
if(line2[x] < (back & 0xFF000000))
{
back = line2[x];
top2 = 0x04;
}
if(line3[x] < (back & 0xFF000000))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
}
void mode0RenderLineAll()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
return;
}
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if((layerEnable & 0x0100))
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if((layerEnable & 0x0200))
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if((layerEnable & 0x0400))
{
gfxDrawTextScreen(BG2CNT, BG2HOFS, BG2VOFS, line2);
}
if((layerEnable & 0x0800))
{
gfxDrawTextScreen(BG3CNT, BG3HOFS, BG3VOFS, line3);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if((mask & 1) && (line0[x] < color))
{
color = line0[x];
top = 0x01;
}
if((mask & 2) && ((u8)(line1[x]>>24) < (u8)(color >> 24)))
{
color = line1[x];
top = 0x02;
}
if((mask & 4) && ((u8)(line2[x]>>24) < (u8)(color >> 24)))
{
color = line2[x];
top = 0x04;
}
if((mask & 8) && ((u8)(line3[x]>>24) < (u8)(color >> 24)))
{
color = line3[x];
top = 0x08;
}
if((mask & 16) && ((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)))
{
color = lineOBJ[x];
top = 0x10;
}
// special FX on in the window
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24))
{
if(top != 0x01)
{
back = line0[x];
top2 = 0x01;
}
}
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24))
{
if(top != 0x02)
{
back = line1[x];
top2 = 0x02;
}
}
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24))
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24))
{
if(top != 0x08)
{
back = line3[x];
top2 = 0x08;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && ((u8)(line0[x]>>24) < (u8)(back >> 24)))
{
back = line0[x];
top2 = 0x01;
}
if((mask & 2) && ((u8)(line1[x]>>24) < (u8)(back >> 24)))
{
back = line1[x];
top2 = 0x02;
}
if((mask & 4) && ((u8)(line2[x]>>24) < (u8)(back >> 24)))
{
back = line2[x];
top2 = 0x04;
}
if((mask & 8) && ((u8)(line3[x]>>24) < (u8)(back >> 24)))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && ((u8)(line0[x]>>24) < (u8)(back >> 24)))
{
back = line0[x];
top2 = 0x01;
}
if((mask & 2) && ((u8)(line1[x]>>24) < (u8)(back >> 24)))
{
back = line1[x];
top2 = 0x02;
}
if((mask & 4) && ((u8)(line2[x]>>24) < (u8)(back >> 24)))
{
back = line2[x];
top2 = 0x04;
}
if((mask & 8) && ((u8)(line3[x]>>24) < (u8)(back >> 24)))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
}

599
src/Mode1.cpp Normal file
View File

@ -0,0 +1,599 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Globals.h"
#include "Gfx.h"
void mode1RenderLine()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0100)
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if(layerEnable & 0x0200)
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed, line2);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line0[x] < color)
{
color = line0[x];
top = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(color >> 24))
{
color = line1[x];
top = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(color >> 24))
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line0[x]>>24) < (u8)(back >> 24))
{
back = line0[x];
top2 = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(back >> 24))
{
back = line1[x];
top2 = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode1RenderLineNoWindow()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0100)
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if(layerEnable & 0x0200)
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed, line2);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line0[x] < color)
{
color = line0[x];
top = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(color >> 24))
{
color = line1[x];
top = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(color >> 24))
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line0[x]>>24) < (u8)(back >> 24))
{
if(top != 0x01)
{
back = line0[x];
top2 = 0x01;
}
}
if((u8)(line1[x]>>24) < (u8)(back >> 24))
{
if(top != 0x02)
{
back = line1[x];
top2 = 0x02;
}
}
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line0[x]>>24) < (u8)(back >> 24))
{
back = line0[x];
top2 = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(back >> 24))
{
back = line1[x];
top2 = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode1RenderLineAll()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x0100)
{
gfxDrawTextScreen(BG0CNT, BG0HOFS, BG0VOFS, line0);
}
if(layerEnable & 0x0200)
{
gfxDrawTextScreen(BG1CNT, BG1HOFS, BG1VOFS, line1);
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed, line2);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if(line0[x] < color && (mask & 1))
{
color = line0[x];
top = 0x01;
}
if((u8)(line1[x]>>24) < (u8)(color >> 24) && (mask & 2))
{
color = line1[x];
top = 0x02;
}
if((u8)(line2[x]>>24) < (u8)(color >> 24) && (mask & 4))
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16))
{
color = lineOBJ[x];
top = 0x10;
}
// special FX on the window
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24))
{
if(top != 0x01)
{
back = line0[x];
top2 = 0x01;
}
}
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24))
{
if(top != 0x02)
{
back = line1[x];
top2 = 0x02;
}
}
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24))
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24))
{
back = line0[x];
top2 = 0x01;
}
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24))
{
back = line1[x];
top2 = 0x02;
}
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24))
{
back = line0[x];
top2 = 0x01;
}
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24))
{
back = line1[x];
top2 = 0x02;
}
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}

550
src/Mode2.cpp Normal file
View File

@ -0,0 +1,550 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Globals.h"
#include "Gfx.h"
void mode2RenderLine()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
changed, line2);
}
if(layerEnable & 0x0800)
{
int changed = gfxBG3Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
changed, line3);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if((u8)(line2[x]>>24) < (u8)(color >> 24))
{
color = line2[x];
top = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(color >> 24))
{
color = line3[x];
top = 0x08;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(back >> 24))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxBG3Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode2RenderLineNoWindow()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
changed, line2);
}
if(layerEnable & 0x0800)
{
int changed = gfxBG3Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
changed, line3);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if((u8)(line2[x]>>24) < (u8)(color >> 24))
{
color = line2[x];
top = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(color >> 24))
{
color = line3[x];
top = 0x08;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((u8)(line3[x]>>24) < (u8)(back >> 24))
{
if(top != 0x08)
{
back = line3[x];
top2 = 0x08;
}
}
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((u8)(line2[x]>>24) < (u8)(back >> 24))
{
back = line2[x];
top2 = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(back >> 24))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxBG3Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode2RenderLineAll()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
changed, line2);
}
if(layerEnable & 0x0800)
{
int changed = gfxBG3Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
changed, line3);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if(line2[x] < color && (mask & 4))
{
color = line2[x];
top = 0x04;
}
if((u8)(line3[x]>>24) < (u8)(color >> 24) && (mask & 8))
{
color = line3[x];
top = 0x08;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16))
{
color = lineOBJ[x];
top = 0x10;
}
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24))
{
if(top != 0x08)
{
back = line3[x];
top2 = 0x08;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24))
{
back = line3[x];
top2 = 0x08;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxBG3Changed = 0;
gfxLastVCOUNT = VCOUNT;
}

463
src/Mode3.cpp Normal file
View File

@ -0,0 +1,463 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Globals.h"
#include "Gfx.h"
void mode3RenderLine()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 background = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >>24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode3RenderLineNoWindow()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 background = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >>24))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode3RenderLineAll()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x80)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
u32 background = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if((mask & 4) && (line2[x] < color))
{
color = line2[x];
top = 0x04;
}
if((mask & 16) && ((u8)(lineOBJ[x]>>24) < (u8)(color >>24)))
{
color = lineOBJ[x];
top = 0x10;
}
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}

460
src/Mode4.cpp Normal file
View File

@ -0,0 +1,460 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Gfx.h"
#include "Globals.h"
void mode4RenderLine()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode4RenderLineNoWindow()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
if(layerEnable & 0x400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if(line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode4RenderLineAll()
{
u16 *palette = (u16 *)paletteRAM;
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
BG2PA, BG2PB, BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
u32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
for(int x = 0; x < 240; x++)
{
u32 color = backdrop;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if((mask & 4) && (line2[x] < color))
{
color = line2[x];
top = 0x04;
}
if((mask & 16) && ((u8)(lineOBJ[x]>>24) < (u8)(color >>24)))
{
color = lineOBJ[x];
top = 0x10;
}
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = backdrop;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}

463
src/Mode5.cpp Normal file
View File

@ -0,0 +1,463 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Globals.h"
#include "Gfx.h"
void mode5RenderLine()
{
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
u16 *palette = (u16 *)paletteRAM;
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 background = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >>24))
{
color = lineOBJ[x];
top = 0x10;
}
if((top & 0x10) && (color & 0x00010000))
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode5RenderLineNoWindow()
{
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
u16 *palette = (u16 *)paletteRAM;
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
u32 background = ( READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
if(line2[x] < color)
{
color = line2[x];
top = 0x04;
}
if((u8)(lineOBJ[x]>>24) < (u8)(color >>24))
{
color = lineOBJ[x];
top = 0x10;
}
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if(line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}
void mode5RenderLineAll()
{
if(DISPCNT & 0x0080)
{
for(int x = 0; x < 240; x++)
{
lineMix[x] = 0x7fff;
}
gfxLastVCOUNT = VCOUNT;
return;
}
u16 *palette = (u16 *)paletteRAM;
if(layerEnable & 0x0400)
{
int changed = gfxBG2Changed;
if(gfxLastVCOUNT > VCOUNT)
changed = 3;
gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
BG2Y_L, BG2Y_H, BG2PA, BG2PB,
BG2PC, BG2PD,
gfxBG2X, gfxBG2Y, changed,
line2);
}
gfxDrawSprites(lineOBJ);
gfxDrawOBJWin(lineOBJWin);
bool inWindow0 = false;
bool inWindow1 = false;
if(layerEnable & 0x2000)
{
u8 v0 = WIN0V >> 8;
u8 v1 = WIN0V & 255;
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
}
if(layerEnable & 0x4000)
{
u8 v0 = WIN1V >> 8;
u8 v1 = WIN1V & 255;
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
if(v1 >= v0)
inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
else
inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
}
u8 inWin0Mask = WININ & 0xFF;
u8 inWin1Mask = WININ >> 8;
u8 outMask = WINOUT & 0xFF;
u32 background = (READ16LE(&palette[0]) | 0x30000000);
for(int x = 0; x < 240; x++)
{
u32 color = background;
u8 top = 0x20;
u8 mask = outMask;
if(!(lineOBJWin[x] & 0x80000000))
{
mask = WINOUT >> 8;
}
if(inWindow1)
{
if(gfxInWin1[x])
mask = inWin1Mask;
}
if(inWindow0)
{
if(gfxInWin0[x])
{
mask = inWin0Mask;
}
}
if((mask & 4) && (line2[x] < color))
{
color = line2[x];
top = 0x04;
}
if((mask & 16) && ((u8)(lineOBJ[x]>>24) < (u8)(color >>24)))
{
color = lineOBJ[x];
top = 0x10;
}
if(mask & 32)
{
if(!(color & 0x00010000))
{
switch((BLDMOD >> 6) & 3)
{
case 0:
break;
case 1:
{
if(top & BLDMOD)
{
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
if(top != 0x04)
{
back = line2[x];
top2 = 0x04;
}
}
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24))
{
if(top != 0x10)
{
back = lineOBJ[x];
top2 = 0x10;
}
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
}
}
break;
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
else
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
}
else if(color & 0x00010000)
{
// semi-transparent OBJ
u32 back = background;
u8 top2 = 0x20;
if((mask & 4) && line2[x] < back)
{
back = line2[x];
top2 = 0x04;
}
if(top2 & (BLDMOD>>8))
color = gfxAlphaBlend(color, back,
coeff[COLEV & 0x1F],
coeff[(COLEV >> 8) & 0x1F]);
else
{
switch((BLDMOD >> 6) & 3)
{
case 2:
if(BLDMOD & top)
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
break;
case 3:
if(BLDMOD & top)
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
break;
}
}
}
lineMix[x] = color;
}
gfxBG2Changed = 0;
gfxLastVCOUNT = VCOUNT;
}

62
src/NLS.h Normal file
View File

@ -0,0 +1,62 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define N_(String) (String)
#define MSG_UNSUPPORTED_VBA_SGM 1
#define MSG_CANNOT_LOAD_SGM 2
#define MSG_SAVE_GAME_NOT_USING_BIOS 3
#define MSG_SAVE_GAME_USING_BIOS 4
#define MSG_UNSUPPORTED_SAVE_TYPE 5
#define MSG_CANNOT_OPEN_FILE 6
#define MSG_BAD_ZIP_FILE 7
#define MSG_NO_IMAGE_ON_ZIP 8
#define MSG_ERROR_OPENING_IMAGE 9
#define MSG_ERROR_READING_IMAGE 10
#define MSG_UNSUPPORTED_BIOS_FUNCTION 11
#define MSG_INVALID_BIOS_FILE_SIZE 12
#define MSG_INVALID_CHEAT_CODE 13
#define MSG_UNKNOWN_ARM_OPCODE 14
#define MSG_UNKNOWN_THUMB_OPCODE 15
#define MSG_ERROR_CREATING_FILE 16
#define MSG_FAILED_TO_READ_SGM 17
#define MSG_FAILED_TO_READ_RTC 18
#define MSG_UNSUPPORTED_VB_SGM 19
#define MSG_CANNOT_LOAD_SGM_FOR 20
#define MSG_ERROR_OPENING_IMAGE_FROM 21
#define MSG_ERROR_READING_IMAGE_FROM 22
#define MSG_UNSUPPORTED_ROM_SIZE 23
#define MSG_UNSUPPORTED_RAM_SIZE 24
#define MSG_UNKNOWN_CARTRIDGE_TYPE 25
#define MSG_MAXIMUM_NUMBER_OF_CHEATS 26
#define MSG_INVALID_GAMESHARK_CODE 27
#define MSG_INVALID_GAMEGENIE_CODE 28
#define MSG_INVALID_CHEAT_TO_REMOVE 29
#define MSG_INVALID_CHEAT_CODE_ADDRESS 30
#define MSG_UNSUPPORTED_CHEAT_LIST_VERSION 31
#define MSG_UNSUPPORTED_CHEAT_LIST_TYPE 32
#define MSG_INVALID_GSA_CODE 33
#define MSG_CANNOT_IMPORT_SNAPSHOT_FOR 34
#define MSG_UNSUPPORTED_SNAPSHOT_FILE 35
#define MSG_UNSUPPORTED_ARM_MODE 36
#define MSG_UNSUPPORTED_CODE_FILE 37
#define MSG_GBA_CODE_WARNING 38
#define MSG_INVALID_CBA_CODE 39
#define MSG_CBA_CODE_WARNING 40
#define MSG_OUT_OF_MEMORY 41

77
src/Port.h Normal file
View File

@ -0,0 +1,77 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_PORT_H
#define VBA_PORT_H
// swaps a 16-bit value
static inline u16 swap16(u16 v)
{
return (v<<8)|(v>>8);
}
// swaps a 32-bit value
static inline u32 swap32(u32 v)
{
return (v<<24)|((v<<8)&0xff0000)|((v>>8)&0xff00)|(v>>24);
}
#ifdef WORDS_BIGENDIAN
#define __ppc__
#if defined(__GNUC__) && defined(__ppc__)
#define READ16LE(base) \
({ unsigned short lhbrxResult; \
__asm__ ("lhbrx %0, 0, %1" : "=r" (lhbrxResult) : "r" (base) : "memory"); \
lhbrxResult; })
#define READ32LE(base) \
({ unsigned long lwbrxResult; \
__asm__ ("lwbrx %0, 0, %1" : "=r" (lwbrxResult) : "r" (base) : "memory"); \
lwbrxResult; })
#define WRITE16LE(base, value) \
__asm__ ("sthbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
#define WRITE32LE(base, value) \
__asm__ ("stwbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
#else
#define READ16LE(x) \
swap16(*((u16 *)(x)))
#define READ32LE(x) \
swap32(*((u32 *)(x)))
#define WRITE16LE(x,v) \
*((u16 *)x) = swap16((v))
#define WRITE32LE(x,v) \
*((u32 *)x) = swap32((v))
#endif
#else
#define READ16LE(x) \
*((u16 *)x)
#define READ32LE(x) \
*((u32 *)x)
#define WRITE16LE(x,v) \
*((u16 *)x) = (v)
#define WRITE32LE(x,v) \
*((u32 *)x) = (v)
#endif
#endif

245
src/RTC.cpp Normal file
View File

@ -0,0 +1,245 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
#include "GBA.h"
#include "Globals.h"
#include "Port.h"
#include "Util.h"
#include "NLS.h"
#include "vmmem.h"
#include <time.h>
#include <string.h>
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
typedef struct
{
u8 byte0;
u8 byte1;
u8 byte2;
u8 command;
int dataLen;
int bits;
RTCSTATE state;
u8 data[12];
// reserved variables for future
u8 reserved[12];
bool reserved2;
u32 reserved3;
}
RTCCLOCKDATA;
static RTCCLOCKDATA rtcClockData;
static bool rtcEnabled = false;
void rtcEnable(bool e)
{
rtcEnabled = e;
}
bool rtcIsEnabled()
{
return rtcEnabled;
}
u16 rtcRead(u32 address)
{
if(rtcEnabled)
{
if(address == 0x80000c8)
return rtcClockData.byte2;
else if(address == 0x80000c6)
return rtcClockData.byte1;
else if(address == 0x80000c4)
{
return rtcClockData.byte0;
}
}
//return READ16LE((&rom[address & 0x1FFFFFE]));
return VMRead16( address & 0x1FFFFFE );
}
static u8 toBCD(u8 value)
{
value = value % 100;
int l = value % 10;
int h = value / 10;
return h * 16 + l;
}
bool rtcWrite(u32 address, u16 value)
{
if(!rtcEnabled)
return false;
if(address == 0x80000c8)
{
rtcClockData.byte2 = (u8)value; // enable ?
}
else if(address == 0x80000c6)
{
rtcClockData.byte1 = (u8)value; // read/write
}
else if(address == 0x80000c4)
{
if(rtcClockData.byte2 & 1)
{
if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5)
{
rtcClockData.state = COMMAND;
rtcClockData.bits = 0;
rtcClockData.command = 0;
}
else if(!(rtcClockData.byte0 & 1) && (value & 1))
{ // bit transfer
rtcClockData.byte0 = (u8)value;
switch(rtcClockData.state)
{
case COMMAND:
rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
rtcClockData.bits++;
if(rtcClockData.bits == 8)
{
rtcClockData.bits = 0;
switch(rtcClockData.command)
{
case 0x60:
// not sure what this command does but it doesn't take parameters
// maybe it is a reset or stop
rtcClockData.state = IDLE;
rtcClockData.bits = 0;
break;
case 0x62:
// this sets the control state but not sure what those values are
rtcClockData.state = READDATA;
rtcClockData.dataLen = 1;
break;
case 0x63:
rtcClockData.dataLen = 1;
rtcClockData.data[0] = 0x40;
rtcClockData.state = DATA;
break;
case 0x65:
{
struct tm *newtime;
time_t long_time;
time( &long_time ); /* Get time as long integer. */
newtime = localtime( &long_time ); /* Convert to local time. */
rtcClockData.dataLen = 7;
rtcClockData.data[0] = toBCD(newtime->tm_year);
rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
rtcClockData.data[2] = toBCD(newtime->tm_mday);
rtcClockData.data[3] = 0;
rtcClockData.data[4] = toBCD(newtime->tm_hour);
rtcClockData.data[5] = toBCD(newtime->tm_min);
rtcClockData.data[6] = toBCD(newtime->tm_sec);
rtcClockData.state = DATA;
}
break;
case 0x67:
{
struct tm *newtime;
time_t long_time;
time( &long_time ); /* Get time as long integer. */
newtime = localtime( &long_time ); /* Convert to local time. */
rtcClockData.dataLen = 3;
rtcClockData.data[0] = toBCD(newtime->tm_hour);
rtcClockData.data[1] = toBCD(newtime->tm_min);
rtcClockData.data[2] = toBCD(newtime->tm_sec);
rtcClockData.state = DATA;
}
break;
default:
systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
rtcClockData.state = IDLE;
break;
}
}
break;
case DATA:
if(rtcClockData.byte1 & 2)
{}
else
{
rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
((rtcClockData.data[rtcClockData.bits >> 3] >>
(rtcClockData.bits & 7)) & 1)*2;
rtcClockData.bits++;
if(rtcClockData.bits == 8*rtcClockData.dataLen)
{
rtcClockData.bits = 0;
rtcClockData.state = IDLE;
}
}
break;
case READDATA:
if(!(rtcClockData.byte1 & 2))
{}
else
{
rtcClockData.data[rtcClockData.bits >> 3] =
(rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
((value << 6) & 128);
rtcClockData.bits++;
if(rtcClockData.bits == 8*rtcClockData.dataLen)
{
rtcClockData.bits = 0;
rtcClockData.state = IDLE;
}
}
break;
default:
break;
}
}
else
rtcClockData.byte0 = (u8)value;
}
}
return true;
}
void rtcReset()
{
memset(&rtcClockData, 0, sizeof(rtcClockData));
rtcClockData.byte0 = 0;
rtcClockData.byte1 = 0;
rtcClockData.byte2 = 0;
rtcClockData.command = 0;
rtcClockData.dataLen = 0;
rtcClockData.bits = 0;
rtcClockData.state = IDLE;
}
void rtcSaveGame(gzFile gzFile)
{
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
}
void rtcReadGame(gzFile gzFile)
{
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
}

31
src/RTC.h Normal file
View File

@ -0,0 +1,31 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_RTC_H
#define VBA_RTC_H
extern u16 rtcRead(u32 address);
extern bool rtcWrite(u32 address, u16 value);
extern void rtcEnable(bool);
extern bool rtcIsEnabled();
extern void rtcReset();
extern void rtcReadGame(gzFile gzFile);
extern void rtcSaveGame(gzFile gzFile);
#endif

1463
src/Sound.cpp Normal file

File diff suppressed because it is too large Load Diff

82
src/Sound.h Normal file
View File

@ -0,0 +1,82 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_SOUND_H
#define VBA_SOUND_H
#define NR10 0x60
#define NR11 0x62
#define NR12 0x63
#define NR13 0x64
#define NR14 0x65
#define NR21 0x68
#define NR22 0x69
#define NR23 0x6c
#define NR24 0x6d
#define NR30 0x70
#define NR31 0x72
#define NR32 0x73
#define NR33 0x74
#define NR34 0x75
#define NR41 0x78
#define NR42 0x79
#define NR43 0x7c
#define NR44 0x7d
#define NR50 0x80
#define NR51 0x81
#define NR52 0x84
#define SGCNT0_H 0x82
#define FIFOA_L 0xa0
#define FIFOA_H 0xa2
#define FIFOB_L 0xa4
#define FIFOB_H 0xa6
extern void soundTick();
extern void soundShutdown();
extern bool soundInit();
extern void soundPause();
extern void soundResume();
extern void soundEnable(int);
extern void soundDisable(int);
extern int soundGetEnable();
extern void soundReset();
extern void soundSaveGame(gzFile);
extern void soundReadGame(gzFile, int);
extern void soundEvent(u32, u8);
extern void soundEvent(u32, u16);
extern void soundTimerOverflow(int);
extern void soundSetQuality(int);
//extern int SOUND_TICKS;
extern int SOUND_CLOCK_TICKS;
extern int soundTicks;
extern int soundPaused;
extern bool soundOffFlag;
extern int soundQuality;
extern int soundBufferLen;
extern int soundBufferTotalLen;
extern u32 soundNextPosition;
extern u16 soundFinalWave[1470];
extern int soundVolume;
extern bool soundEcho;
extern bool soundLowPass;
extern bool soundReverse;
#endif // VBA_SOUND_H

32
src/Sram.cpp Normal file
View File

@ -0,0 +1,32 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GBA.h"
#include "Flash.h"
#include "Sram.h"
u8 sramRead(u32 address)
{
return flashSaveMemory[address & 0xFFFF];
}
void sramWrite(u32 address, u8 byte)
{
flashSaveMemory[address & 0xFFFF] = byte;
systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
}

26
src/Sram.h Normal file
View File

@ -0,0 +1,26 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_SRAM_H
#define VBA_SRAM_H
extern u8 sramRead(u32 address);
extern void sramWrite(u32 address, u8 byte);
#endif // VBA_SRAM_H

127
src/System.h Normal file
View File

@ -0,0 +1,127 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_SYSTEM_H
#define VBA_SYSTEM_H
#include "unzip.h"
#ifndef NULL
#define NULL 0
#endif
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#ifdef _MSC_VER
typedef unsigned __int64 u64;
#else
typedef unsigned long long u64;
#endif
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
#ifdef _MSC_VER
typedef signed __int64 s64;
#else
typedef signed long long s64;
#endif
struct EmulatedSystem
{
// main emulation function
void (*emuMain)(int);
// reset emulator
void (*emuReset)();
// clean up memory
void (*emuCleanUp)();
// load battery file
bool (*emuReadBattery)(const char *);
// write battery file
bool (*emuWriteBattery)(const char *);
// load state
bool (*emuReadState)(const char *);
// save state
bool (*emuWriteState)(const char *);
// load memory state (rewind)
bool (*emuReadMemState)(char *, int);
// write memory state (rewind)
bool (*emuWriteMemState)(char *, int);
// write PNG file
bool (*emuWritePNG)(const char *);
// write BMP file
bool (*emuWriteBMP)(const char *);
// emulator update CPSR (ARM only)
void (*emuUpdateCPSR)();
// emulator has debugger
bool emuHasDebugger;
// clock ticks to emulate
int emuCount;
};
extern void log(const char *,...);
extern bool systemPauseOnFrame();
extern void systemGbPrint(u8 *,int,int,int,int);
extern void systemScreenCapture(int);
extern void systemDrawScreen();
// updates the joystick data
extern bool systemReadJoypads();
// return information about the given joystick, -1 for default joystick
extern u32 systemReadJoypad(int);
extern u32 systemGetClock();
extern void systemMessage(int, const char *, ...);
extern void systemSetTitle(const char *);
extern void systemWriteDataToSoundBuffer();
extern void systemSoundShutdown();
extern void systemSoundPause();
extern void systemSoundResume();
extern void systemSoundReset();
extern bool systemSoundInit();
extern void systemScreenMessage(const char *);
extern void systemUpdateMotionSensor();
extern int systemGetSensorX();
extern int systemGetSensorY();
extern bool systemCanChangeSoundQuality();
extern void systemShowSpeed(int);
extern void system10Frames(int);
extern void systemFrame();
extern void systemGbBorderOn();
extern bool systemSoundOn;
extern u16 systemColorMap16[0x10000];
//extern u32 systemColorMap32[0x10000];
extern u32 *systemColorMap32;
extern u16 systemGbPalette[24];
extern int systemRedShift;
extern int systemGreenShift;
extern int systemBlueShift;
extern int systemColorDepth;
extern int systemDebug;
extern int systemVerbose;
extern int systemFrameSkip;
extern int systemSaveUpdateCounter;
#define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0
#endif //VBA_SYSTEM_H

180
src/Text.cpp Normal file
View File

@ -0,0 +1,180 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Ben Parnell
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Code originally from fceu/drawing.h file, adapted by Forgotten
*/
#include "System.h"
extern int RGB_LOW_BITS_MASK;
static const u8 fontdata2[2048] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00,0x1c,0x3e,0x1c,0x7f,0x7f,0x3e,0x1c,0x3e,0x08,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07,0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00,0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00,0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x33,0x1e,0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00,0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x1e,0x0c,0x0c,0x00,0x0c,0x00,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00,0x0c,0x3e,0x03,0x1e,0x30,0x1f,0x0c,0x00,0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00,0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00,0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x3e,0x63,0x73,0x7b,0x6f,0x67,0x3e,0x00,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00,0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00,0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00,0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00,0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x06,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00,0x00,0x00,0x3f,0x00,0x00,0x3f,0x00,0x00,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00,0x1e,0x33,0x30,0x18,0x0c,0x00,0x0c,0x00,
0x3e,0x63,0x7b,0x7b,0x7b,0x03,0x1e,0x00,0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00,0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00,0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00,0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00,0x3c,0x66,0x03,0x03,0x73,0x66,0x7c,0x00,0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00,0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00,0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00,0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00,0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00,0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00,0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00,0x1e,0x33,0x33,0x33,0x3b,0x1e,0x38,0x00,0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00,0x1e,0x33,0x07,0x0e,0x38,0x33,0x1e,0x00,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00,0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00,0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00,0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00,0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00,0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00,0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x1c,0x36,0x06,0x0f,0x06,0x06,0x0f,0x00,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f,0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00,0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1e,0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x33,0x7f,0x7f,0x6b,0x63,0x00,0x00,0x00,0x1f,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00,0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78,0x00,0x00,0x3b,0x6e,0x66,0x06,0x0f,0x00,0x00,0x00,0x3e,0x03,0x1e,0x30,0x1f,0x00,0x08,0x0c,0x3e,0x0c,0x0c,0x2c,0x18,0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00,0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00,0x00,0x00,0x63,0x6b,0x7f,0x7f,0x36,0x00,0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00,0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f,0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00,0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,
0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e,0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00,0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c,0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00,0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00,0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00,0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00,0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00,0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00,0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00,0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f,0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00,0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18,0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00,0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c,0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3,0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e,
0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00,0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00,0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00,0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00,0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00,0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0,0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00,0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03,0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00,0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00,0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00,0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03,0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00,0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f,0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00,0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00,0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03,0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00,0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00,0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e,0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00,0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38,0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static void drawTextInternal(u8 *screen, int pitch, int x, int y,
const char *string, bool trans)
{
screen += y*pitch;
int inc = 2;
switch(systemColorDepth)
{
case 24:
inc = 3;
break;
case 32:
inc = 4;
break;
}
screen += x*inc;
switch(systemColorDepth)
{
case 16:
{
while(*string)
{
char c = *string++;
u8 *scr = screen;
u16 mask = ~RGB_LOW_BITS_MASK;
int h, w;
u16 *s = (u16 *)scr;
for (h = 0; h < 8; h++)
{
for (w = 0; w < 8; w++, s++)
{
int on = (fontdata2[(c<<3)+h]>>w)&1;
if(trans)
{
if(on)
*s = ((0xf) << systemRedShift) +
((*s & mask) >>1);
}
else
{
if(on)
*s = (0x1f) << systemRedShift;
}
}
scr += pitch;
s = (u16 *)scr;
}
screen += inc*8;
}
}
break;
case 24:
{
while(*string)
{
char c = *string++;
u8 *scr = screen;
int h, w;
u8 *s = (u8 *)scr;
for (h = 0; h < 8; h++)
{
for (w = 0; w < 8; w++, s+=3)
{
int on = (fontdata2[(c<<3)+h]>>w)&1;
if(trans)
{
if(on)
{
u32 color = (0x1f) << systemRedShift;
*s = ((color & 255)>>1)+(*s>>1);
*(s+1) = (((color >> 8) & 255)>>1)+(*(s+1)>>1);
*(s+2) = (((color >> 16) & 255)>>1)+(*(s+2)>>1);
}
}
else
{
if(on)
{
u32 color = (0x1f) << systemRedShift;
*s = (color & 255);
*(s+1) = (color >> 8) & 255;
*(s+2) = (color >> 16) & 255;
}
}
}
scr += pitch;
s = (u8 *)scr;
}
screen += inc*8;
}
}
break;
case 32:
{
while(*string)
{
char c = *string++;
u8 *scr = screen;
int h, w;
u32 mask = 0xfefefe;
u32 *s = (u32 *)scr;
for (h = 0; h < 8; h++)
{
for (w = 0; w < 8; w++, s++)
{
int on = (fontdata2[(c<<3)+h]>>w)&1;
if(trans)
{
if(on)
*s = ((0xf) << systemRedShift) + ((*s & mask)>>1);
}
else
{
if(on)
*s = (0x1f) << systemRedShift;
}
}
scr += pitch;
s = (u32 *)scr;
}
screen += inc*8;
}
}
break;
}
}
void drawText(u8 *screen, int pitch, int x, int y, const char *string)
{
drawTextInternal(screen, pitch, x, y, string, false);
}
void drawTextTransp(u8 *screen, int pitch, int x, int y, const char *string)
{
drawTextInternal(screen, pitch, x, y, string, true);
}

21
src/Text.h Normal file
View File

@ -0,0 +1,21 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern void drawText(u8 *, int, int, int, const char *);
extern void drawTextTransp(u8 *, int, int, int, const char *);

1196
src/Util.cpp Normal file

File diff suppressed because it is too large Load Diff

66
src/Util.h Normal file
View File

@ -0,0 +1,66 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_UTIL_H
#define VBA_UTIL_H
enum IMAGE_TYPE {
IMAGE_UNKNOWN = -1,
IMAGE_GBA = 0,
IMAGE_GB = 1
};
// save game
typedef struct
{
void *address;
int size;
}
variable_desc;
extern bool utilWritePNGFile(const char *, int, int, u8 *);
extern bool utilWriteBMPFile(const char *, int, int, u8 *);
extern void utilApplyIPS(const char *ips, u8 **rom, int *size);
extern void utilWriteBMP(char *, int, int, u8 *);
extern bool utilIsGBAImage(const char *);
extern bool utilIsGBImage(const char *);
extern bool utilIsZipFile(const char *);
extern bool utilIsGzipFile(const char *);
extern bool utilIsRarFile(const char *);
extern void utilGetBaseName(const char *, char *);
extern IMAGE_TYPE utilFindType(const char *);
extern u8 *utilLoad(const char *,
bool (*)(const char*),
u8 *,
int &);
extern void utilPutDword(u8 *, u32);
extern void utilPutWord(u8 *, u16);
extern void utilWriteData(gzFile, variable_desc *);
extern void utilReadData(gzFile, variable_desc *);
extern int utilReadInt(gzFile);
extern void utilWriteInt(gzFile, int);
extern gzFile utilGzOpen(const char *file, const char *mode);
extern gzFile utilMemGzOpen(char *memory, int available, char *mode);
extern int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
extern int utilGzRead(gzFile file, voidp buffer, unsigned int len);
extern int utilGzClose(gzFile file);
extern long utilGzMemTell(gzFile file);
extern void utilGBAFindSave(const u8 *, const int);
#endif

1033
src/admame.cpp Normal file

File diff suppressed because it is too large Load Diff

106
src/agbprint.cpp Normal file
View File

@ -0,0 +1,106 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <string.h>
#include "GBA.h"
#include "Globals.h"
#include "Port.h"
#define debuggerWriteHalfWord(addr, value) \
WRITE16LE((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], (value))
#define debuggerReadHalfWord(addr) \
READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
static bool agbPrintEnabled = false;
static bool agbPrintProtect = false;
bool agbPrintWrite(u32 address, u16 value)
{
if(agbPrintEnabled)
{
if(address == 0x9fe2ffe)
{ // protect
agbPrintProtect = (value != 0);
debuggerWriteHalfWord(address, value);
return true;
}
else
{
if(agbPrintProtect &&
((address >= 0x9fe20f8 && address <= 0x9fe20ff) // control structure
|| (address >= 0x8fd0000 && address <= 0x8fdffff)
|| (address >= 0x9fd0000 && address <= 0x9fdffff)))
{
debuggerWriteHalfWord(address, value);
return true;
}
}
}
return false;
}
void agbPrintReset()
{
agbPrintProtect = false;
}
void agbPrintEnable(bool enable)
{
agbPrintEnabled = enable;
}
bool agbPrintIsEnabled()
{
return agbPrintEnabled;
}
extern void (*dbgOutput)(char *, u32);
void agbPrintFlush()
{
u16 get = debuggerReadHalfWord(0x9fe20fc);
u16 put = debuggerReadHalfWord(0x9fe20fe);
u32 address = (debuggerReadHalfWord(0x9fe20fa) << 16);
if(address != 0xfd0000 && address != 0x1fd0000)
{
dbgOutput("Did you forget to call AGBPrintInit?\n", 0);
// get rid of the text otherwise we will continue to be called
debuggerWriteHalfWord(0x9fe20fc, put);
return;
}
u8 *data = &rom[address];
while(get != put)
{
char c = data[get++];
char s[2];
s[0] = c;
s[1] = 0;
if(systemVerbose & VERBOSE_AGBPRINT)
dbgOutput(s, 0);
if(c == '\n')
break;
}
debuggerWriteHalfWord(0x9fe20fc, get);
}

27
src/agbprint.h Normal file
View File

@ -0,0 +1,27 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_AGBPRINT_H
#define VBA_AGBPRINT_H
extern void agbPrintEnable(bool);
extern bool agbPrintIsEnabled();
extern void agbPrintReset();
extern bool agbPrintWrite(u32, u16);
extern void agbPrintFlush();
#endif

7472
src/arm-new.h Normal file

File diff suppressed because it is too large Load Diff

809
src/armdis.cpp Normal file
View File

@ -0,0 +1,809 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/************************************************************************/
/* Arm/Thumb command set disassembler */
/************************************************************************/
#include <stdio.h>
#include "System.h"
#include "Port.h"
#include "GBA.h"
#include "armdis.h"
#include "elf.h"
struct Opcodes
{
u32 mask;
u32 cval;
char *mnemonic;
};
#define debuggerReadMemory(addr) \
READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
#define debuggerReadHalfWord(addr) \
READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
#define debuggerReadByte(addr) \
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
const char hdig[] = "0123456789abcdef";
const char *decVals[16] =
{
"0","1","2","3","4","5","6","7","8",
"9","10","11","12","13","14","15"
};
const char *regs[16] =
{
"r0","r1","r2","r3","r4","r5","r6","r7",
"r8","r9","r10","r11","r12","sp","lr","pc"
};
const char *conditions[16] =
{
"eq","ne","cs","cc","mi","pl","vs","vc",
"hi","ls","ge","lt","gt","le","","nv"
};
const char *shifts[5] =
{
"lsl","lsr","asr","ror","rrx"
};
const char *armMultLoadStore[12] =
{
// non-stack
"da","ia","db","ib",
// stack store
"ed","ea","fd","fa",
// stack load
"fa","fd","ea","ed"
};
const Opcodes thumbOpcodes[] =
{
// Format 1
{0xf800, 0x0000, "lsl %r0, %r3, %o"},
{0xf800, 0x0800, "lsr %r0, %r3, %o"},
{0xf800, 0x1000, "asr %r0, %r3, %o"},
// Format 2
{0xfe00, 0x1800, "add %r0, %r3, %r6"},
{0xfe00, 0x1a00, "sub %r0, %r3, %r6"},
{0xfe00, 0x1c00, "add %r0, %r3, %i"},
{0xfe00, 0x1e00, "sub %r0, %r3, %i"},
// Format 3
{0xf800, 0x2000, "mov %r8, %O"},
{0xf800, 0x2800, "cmp %r8, %O"},
{0xf800, 0x3000, "add %r8, %O"},
{0xf800, 0x3800, "sub %r8, %O"},
// Format 4
{0xffc0, 0x4000, "and %r0, %r3"},
{0xffc0, 0x4040, "eor %r0, %r3"},
{0xffc0, 0x4080, "lsl %r0, %r3"},
{0xffc0, 0x40c0, "lsr %r0, %r3"},
{0xffc0, 0x4100, "asr %r0, %r3"},
{0xffc0, 0x4140, "adc %r0, %r3"},
{0xffc0, 0x4180, "sbc %r0, %r3"},
{0xffc0, 0x41c0, "ror %r0, %r3"},
{0xffc0, 0x4200, "tst %r0, %r3"},
{0xffc0, 0x4240, "neg %r0, %r3"},
{0xffc0, 0x4280, "cmp %r0, %r3"},
{0xffc0, 0x42c0, "cmn %r0, %r3"},
{0xffc0, 0x4300, "orr %r0, %r3"},
{0xffc0, 0x4340, "mul %r0, %r3"},
{0xffc0, 0x4380, "bic %r0, %r3"},
{0xffc0, 0x43c0, "mvn %r0, %r3"},
// Format 5
{0xff80, 0x4700, "bx %h36"},
{0xfcc0, 0x4400, "[ ??? ]"},
{0xff00, 0x4400, "add %h07, %h36"},
{0xff00, 0x4500, "cmp %h07, %h36"},
{0xff00, 0x4600, "mov %h07, %h36"},
// Format 6
{0xf800, 0x4800, "ldr %r8, [%I] (=%J)"},
// Format 7
{0xfa00, 0x5000, "str%b %r0, [%r3, %r6]"},
{0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]"},
// Format 8
{0xfe00, 0x5200, "strh %r0, [%r3, %r6]"},
{0xfe00, 0x5600, "ldrh %r0, [%r3, %r6]"},
{0xfe00, 0x5a00, "ldsb %r0, [%r3, %r6]"},
{0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]"},
// Format 9
{0xe800, 0x6000, "str%B %r0, [%r3, %p]"},
{0xe800, 0x6800, "ldr%B %r0, [%r3, %p]"},
// Format 10
{0xf800, 0x8000, "strh %r0, [%r3, %e]"},
{0xf800, 0x8800, "ldrh %r0, [%r3, %e]"},
// Format 11
{0xf800, 0x9000, "str %r8, [sp, %w]"},
{0xf800, 0x9800, "ldr %r8, [sp, %w]"},
// Format 12
{0xf800, 0xa000, "add %r8, pc, %w (=%K)"},
{0xf800, 0xa800, "add %r8, sp, %w"},
// Format 13
{0xff00, 0xb000, "add sp, %s"},
// Format 14
{0xffff, 0xb500, "push {lr}"},
{0xff00, 0xb400, "push {%l}"},
{0xff00, 0xb500, "push {%l,lr}"},
{0xffff, 0xbd00, "pop {pc}"},
{0xff00, 0xbd00, "pop {%l,pc}"},
{0xff00, 0xbc00, "pop {%l}"},
// Format 15
{0xf800, 0xc000, "stmia %r8!, {%l}"},
{0xf800, 0xc800, "ldmia %r8!, {%l}"},
// Format 17
{0xff00, 0xdf00, "swi %m"},
// Format 16
{0xf000, 0xd000, "b%c %W"},
// Format 18
{0xf800, 0xe000, "b %a"},
// Format 19
{0xf800, 0xf000, "bl %A"},
{0xf800, 0xf800, "blh %Z"},
{0xff00, 0xbe00, "bkpt %O"},
// Unknown
{0x0000, 0x0000, "[ ??? ]"}
};
const Opcodes armOpcodes[] =
{
// Undefined
{0x0e000010, 0x06000010, "[ undefined ]"},
// Branch instructions
{0x0ff000f0, 0x01200010, "bx%c %r0"},
{0x0f000000, 0x0a000000, "b%c %o"},
{0x0f000000, 0x0b000000, "bl%c %o"},
{0x0f000000, 0x0f000000, "swi%c %q"},
// PSR transfer
{0x0fbf0fff, 0x010f0000, "mrs%c %r3, %p"},
{0x0db0f000, 0x0120f000, "msr%c %p, %i"},
// Multiply instructions
{0x0fe000f0, 0x00000090, "mul%c%s %r4, %r0, %r2"},
{0x0fe000f0, 0x00200090, "mla%c%s %r4, %r0, %r2, %r3"},
{0x0fa000f0, 0x00800090, "%umull%c%s %r3, %r4, %r0, %r2"},
{0x0fa000f0, 0x00a00090, "%umlal%c%s %r3, %r4, %r0, %r2"},
// Load/Store instructions
{0x0fb00ff0, 0x01000090, "swp%c%b %r3, %r0, [%r4]"},
{0x0fb000f0, 0x01000090, "[ ??? ]"},
{0x0c100000, 0x04000000, "str%c%b%t %r3, %a"},
{0x0c100000, 0x04100000, "ldr%c%b%t %r3, %a"},
{0x0e100090, 0x00000090, "str%c%h %r3, %a"},
{0x0e100090, 0x00100090, "ldr%c%h %r3, %a"},
{0x0e100000, 0x08000000, "stm%c%m %r4%l"},
{0x0e100000, 0x08100000, "ldm%c%m %r4%l"},
// Data processing
{0x0de00000, 0x00000000, "and%c%s %r3, %r4, %i"},
{0x0de00000, 0x00200000, "eor%c%s %r3, %r4, %i"},
{0x0de00000, 0x00400000, "sub%c%s %r3, %r4, %i"},
{0x0de00000, 0x00600000, "rsb%c%s %r3, %r4, %i"},
{0x0de00000, 0x00800000, "add%c%s %r3, %r4, %i"},
{0x0de00000, 0x00a00000, "adc%c%s %r3, %r4, %i"},
{0x0de00000, 0x00c00000, "sbc%c%s %r3, %r4, %i"},
{0x0de00000, 0x00e00000, "rsc%c%s %r3, %r4, %i"},
{0x0de00000, 0x01000000, "tst%c%s %r4, %i"},
{0x0de00000, 0x01200000, "teq%c%s %r4, %i"},
{0x0de00000, 0x01400000, "cmp%c%s %r4, %i"},
{0x0de00000, 0x01600000, "cmn%c%s %r4, %i"},
{0x0de00000, 0x01800000, "orr%c%s %r3, %r4, %i"},
{0x0de00000, 0x01a00000, "mov%c%s %r3, %i"},
{0x0de00000, 0x01c00000, "bic%c%s %r3, %r4, %i"},
{0x0de00000, 0x01e00000, "mvn%c%s %r3, %i"},
// Coprocessor operations
{0x0f000010, 0x0e000000, "cdp%c %P, %N, %r3, %R4, %R0%V"},
{0x0e100000, 0x0c000000, "stc%c%L %P, %r3, %A"},
{0x0f100010, 0x0e000010, "mcr%c %P, %N, %r3, %R4, %R0%V"},
{0x0f100010, 0x0e100010, "mrc%c %P, %N, %r3, %R4, %R0%V"},
// Unknown
{0x00000000, 0x00000000, "[ ??? ]"}
};
char* addStr(char *dest, const char *src)
{
while (*src)
{
*dest++ = *src++;
}
return dest;
}
char* addHex(char *dest, int siz, u32 val)
{
if (siz==0)
{
siz = 28;
while ( (((val>>siz)&15)==0) && (siz>=4) )
siz -= 4;
siz += 4;
}
while (siz>0)
{
siz -= 4;
*dest++ = hdig[(val>>siz)&15];
}
return dest;
}
int disArm(u32 offset, char *dest, int flags)
{
u32 opcode = debuggerReadMemory(offset);
const Opcodes *sp = armOpcodes;
while( sp->cval != (opcode & sp->mask) )
sp++;
if (flags&DIS_VIEW_ADDRESS)
{
dest = addHex(dest, 32, offset);
*dest++ = ' ';
}
if (flags&DIS_VIEW_CODE)
{
dest = addHex(dest, 32, opcode);
*dest++ = ' ';
}
char *src = sp->mnemonic;
while (*src)
{
if (*src!='%')
*dest++ = *src++;
else
{
src++;
switch (*src)
{
case 'c':
dest = addStr(dest, conditions[opcode>>28]);
break;
case 'r':
dest = addStr(dest, regs[(opcode>>((*(++src)-'0')*4))&15]);
break;
case 'o':
{
*dest++ = '$';
int off = opcode&0xffffff;
if (off&0x800000)
off |= 0xff000000;
off <<= 2;
dest = addHex(dest, 32, offset+8+off);
}
break;
case 'i':
if (opcode&(1<<25))
{
dest = addStr(dest, "#0x");
int imm = opcode&0xff;
int rot = (opcode&0xf00)>>7;
int val = (imm<<(32-rot))|(imm>>rot);
dest = addHex(dest, 0, val);
}
else
{
dest = addStr(dest, regs[opcode&0x0f]);
int shi = (opcode>>5)&3;
int sdw = (opcode>>7)&0x1f;
if ((sdw==0)&&(shi==3))
shi = 4;
if ( (sdw) || (opcode&0x10) || (shi))
{
dest = addStr(dest, ", ");
dest = addStr(dest, shifts[shi]);
if (opcode&0x10)
{
*dest++ = ' ';
dest = addStr(dest, regs[(opcode>>8)&15]);
}
else
{
if (sdw==0 && ( (shi==1) || (shi==2) ))
sdw = 32;
if(shi != 4)
{
dest = addStr(dest, " #0x");
dest = addHex(dest, 8, sdw);
}
}
}
}
break;
case 'p':
if (opcode&(1<<22))
dest = addStr(dest, "spsr");
else
dest = addStr(dest, "cpsr");
if(opcode & 0x00F00000)
{
*dest++ = '_';
if(opcode & 0x00080000)
*dest++ = 'f';
if(opcode & 0x00040000)
*dest++ = 's';
if(opcode & 0x00020000)
*dest++ = 'x';
if(opcode & 0x00010000)
*dest++ = 'c';
}
break;
case 's':
if (opcode&(1<<20))
*dest++ = 's';
break;
case 'S':
if (opcode&(1<<22))
*dest++ = 's';
break;
case 'u':
if (opcode&(1<<22))
*dest++ = 's';
else
*dest++ = 'u';
break;
case 'b':
if (opcode&(1<<22))
*dest++ = 'b';
break;
case 'a':
if ((opcode&0x076f0000)==0x004f0000)
{
*dest++ = '[';
*dest++ = '$';
int adr = offset+8;
int add = (opcode&15)|((opcode>>8)&0xf0);
if (opcode&(1<<23))
adr += add;
else
adr -= add;
dest = addHex(dest, 32, adr);
*dest++ = ']';
dest = addStr(dest, " (=");
*dest++ = '$';
dest = addHex(dest ,32, debuggerReadMemory(adr));
*dest++=')';
}
if ((opcode&0x072f0000)==0x050f0000)
{
*dest++ = '[';
*dest++ = '$';
int adr = offset+8;
if (opcode&(1<<23))
adr += opcode&0xfff;
else
adr -= opcode&0xfff;
dest = addHex(dest, 32, adr);
*dest++ = ']';
dest = addStr(dest, " (=");
*dest++ = '$';
dest = addHex(dest ,32, debuggerReadMemory(adr));
*dest++=')';
}
else
{
int reg = (opcode>>16)&15;
*dest++ = '[';
dest = addStr(dest, regs[reg]);
if (!(opcode&(1<<24)))
*dest++ = ']';
if ( ((opcode&(1<<25))&&(opcode&(1<<26))) || (!(opcode&(1<<22))&&!(opcode&(1<<26))) )
{
dest = addStr(dest, ", ");
if (!(opcode&(1<<23)))
*dest++ = '-';
dest = addStr(dest, regs[opcode&0x0f]);
int shi = (opcode>>5)&3;
if (opcode&(1<<26))
{
if ( ((opcode>>7)&0x1f) || (opcode&0x10) || (shi==1) || (shi==2))
{
dest = addStr(dest, ", ");
dest = addStr(dest, shifts[shi]);
if (opcode&0x10)
{
*dest++ = ' ';
dest = addStr(dest, regs[(opcode>>8)&15]);
}
else
{
int sdw = (opcode>>7)&0x1f;
if (sdw==0 && ( (shi==1) || (shi==2) ))
sdw = 32;
dest = addStr(dest, " #0x");
dest = addHex(dest, 8, sdw);
}
}
}
}
else
{
int off;
if (opcode&(1<<26))
off = opcode&0xfff;
else
off = (opcode&15)|((opcode>>4)&0xf0);
if (off)
{
dest = addStr(dest, ", ");
if (!(opcode&(1<<23)))
*dest++ = '-';
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, off);
}
}
if (opcode&(1<<24))
{
*dest++ = ']';
if (opcode&(1<<21))
*dest++ = '!';
}
}
break;
case 't':
if ((opcode&0x01200000)==0x01200000)
*dest++ = 't';
break;
case 'h':
if (opcode&(1<<6))
*dest++ = 's';
if (opcode&(1<<5))
*dest++ = 'h';
else
*dest++ = 'b';
break;
case 'm':
if (((opcode>>16)&15)==13)
{
if(opcode & 0x00100000)
dest = addStr(dest, armMultLoadStore[8+((opcode>>23)&3)]);
else
dest = addStr(dest, armMultLoadStore[4+((opcode>>23)&3)]);
}
else
dest = addStr(dest, armMultLoadStore[(opcode>>23)&3]);
break;
case 'l':
if (opcode&(1<<21))
*dest++ = '!';
dest = addStr(dest, ", {");
{
int rlst = opcode&0xffff;
int msk = 0;
int not_first = 0;
while (msk<16)
{
if (rlst&(1<<msk))
{
int fr = msk;
while (rlst&(1<<msk))
msk++;
int to = msk-1;
if (not_first)
//dest = addStr(dest, ", ");
*dest++ = ',';
dest = addStr(dest, regs[fr]);
if (fr!=to)
{
if (fr==to-1)
//dest = addStr(", ");
*dest++ = ',';
else
*dest++ = '-';
dest = addStr(dest, regs[to]);
}
not_first = 1;
}
else
msk++;
}
*dest++ = '}';
if (opcode&(1<<22))
*dest++ = '^';
}
break;
case 'q':
*dest++ = '$';
dest = addHex(dest, 24, opcode&0xffffff);
break;
case 'P':
*dest++ = 'p';
dest = addStr(dest, decVals[(opcode>>8)&15]);
break;
case 'N':
if (opcode&0x10)
dest = addStr(dest, decVals[(opcode>>21)&7]);
else
dest = addStr(dest, decVals[(opcode>>20)&15]);
break;
case 'R':
{
src++;
int reg = 4*(*src-'0');
*dest++ = 'c';
dest = addStr(dest, decVals[(opcode>>reg)&15]);
}
break;
case 'V':
{
int val = (opcode>>5)&7;
if (val)
{
dest = addStr(dest, ", ");
dest = addStr(dest, decVals[val]);
}
}
break;
case 'L':
if (opcode&(1<<22))
*dest++ = 'l';
break;
case 'A':
if ((opcode&0x012f0000)==0x010f0000)
{
int adr = offset+8;
int add = (opcode&0xff)<<2;
if (opcode&(1<<23))
adr += add;
else
adr -= add;
*dest++ = '$';
addHex(dest, 32, adr);
}
else
{
*dest++ = '[';
dest = addStr(dest, regs[(opcode>>16)&15]);
if (!(opcode&(1<<24)))
*dest++ = ']';
int off = (opcode&0xff)<<2;
if (off)
{
dest = addStr(dest, ", ");
if (!(opcode&(1<<23)))
*dest++ = '-';
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, off);
}
if (opcode&(1<<24))
{
*dest++ = ']';
if (opcode&(1<<21))
*dest++ = '!';
}
}
break;
}
src++;
}
}
*dest++ = 0;
return 4;
}
int disThumb(u32 offset, char *dest, int flags)
{
u32 opcode = debuggerReadHalfWord(offset);
const Opcodes *sp = thumbOpcodes;
int ret = 2;
while( sp->cval != (opcode & sp->mask) )
sp++;
if (flags&DIS_VIEW_ADDRESS)
{
dest = addHex(dest, 32, offset);
*dest++ = ' ';
}
if (flags&DIS_VIEW_CODE)
{
dest = addHex(dest, 16, opcode);
*dest++ = ' ';
}
char *src = sp->mnemonic;
while (*src)
{
if (*src!='%')
*dest++ = *src++;
else
{
src++;
switch (*src)
{
case 'r':
src++;
dest = addStr(dest, regs[(opcode>>(*src-'0'))&7]);
break;
case 'o':
dest = addStr(dest, "#0x");
{
int val = (opcode>>6)&0x1f;
dest = addHex(dest, 8, val);
}
break;
case 'p':
dest = addStr(dest, "#0x");
{
int val = (opcode>>6)&0x1f;
if (!(opcode&(1<<12)))
val <<= 2;
dest = addHex(dest, 0, val);
}
break;
case 'e':
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, ((opcode>>6)&0x1f)<<1);
break;
case 'i':
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, (opcode>>6)&7);
break;
case 'h':
{
src++;
int reg = (opcode>>(*src-'0'))&7;
src++;
if (opcode&(1<<(*src-'0')))
reg += 8;
dest = addStr(dest, regs[reg]);
}
break;
case 'O':
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, (opcode&0xff));
break;
case 'I':
*dest++ = '$';
dest = addHex(dest, 32, (offset&0xfffffffc)+4+((opcode&0xff)<<2));
break;
case 'J':
{
u32 value = debuggerReadMemory((offset&0xfffffffc)+4+
((opcode & 0xff)<<2));
*dest++ = '$';
dest = addHex(dest, 32, value);
char *s = elfGetAddressSymbol(value);
if(*s)
{
*dest++ = ' ';
dest = addStr(dest, s);
}
}
break;
case 'K':
{
u32 value = (offset&0xfffffffc)+4+((opcode & 0xff)<<2);
*dest++ = '$';
dest = addHex(dest, 32, value);
char *s = elfGetAddressSymbol(value);
if(*s)
{
*dest++ = ' ';
dest = addStr(dest, s);
}
}
break;
case 'b':
if (opcode&(1<<10))
*dest++ = 'b';
break;
case 'B':
if (opcode&(1<<12))
*dest++ = 'b';
break;
case 'w':
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, (opcode&0xff)<<2);
break;
case 'W':
*dest++ = '$';
{
int add = opcode&0xff;
if (add&0x80)
add |= 0xffffff00;
dest = addHex(dest, 32, (offset&0xfffffffe)+4+(add<<1));
}
break;
case 'c':
dest = addStr(dest, conditions[(opcode>>8)&15]);
break;
case 's':
if (opcode&(1<<7))
*dest++ = '-';
dest = addStr(dest, "#0x");
dest = addHex(dest, 0, (opcode&0x7f)<<2);
break;
case 'l':
{
int rlst = opcode&0xff;
int msk = 0;
int not_first = 0;
while (msk<8)
{
if (rlst&(1<<msk))
{
int fr = msk;
while (rlst&(1<<msk))
msk++;
int to = msk-1;
if (not_first)
*dest++ = ',';
dest = addStr(dest, regs[fr]);
if (fr!=to)
{
if (fr==to-1)
*dest++ = ',';
else
*dest++ = '-';
dest = addStr(dest, regs[to]);
}
not_first = 1;
}
else
msk++;
}
}
break;
case 'm':
*dest++ = '$';
dest = addHex(dest, 8, opcode&0xff);
break;
case 'Z':
*dest++ = '$';
dest = addHex(dest, 16, (opcode&0x7ff)<<1);
break;
case 'a':
*dest++ = '$';
{
int add = opcode&0x07ff;
if (add&0x400)
add |= 0xfffff800;
add <<= 1;
dest = addHex(dest, 32, offset+4+add);
}
break;
case 'A':
{
int nopcode = debuggerReadHalfWord(offset+2);
int add = opcode&0x7ff;
if (add&0x400)
add |= 0xfff800;
add = (add<<12)|((nopcode&0x7ff)<<1);
*dest++ = '$';
dest = addHex(dest,32, offset+4+add);
char *s = elfGetAddressSymbol(offset+4+add);
if(*s)
{
*dest++ = ' ';
*dest++ = '(';
dest = addStr(dest, s);
*dest++ = ')';
}
ret = 4;
}
break;
}
src++;
}
}
*dest++ = 0;
return ret;
}

33
src/armdis.h Normal file
View File

@ -0,0 +1,33 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/************************************************************************/
/* Arm/Thumb command set disassembler */
/************************************************************************/
#ifndef __ARMDIS_H__
#define __ARMDIS_H__
#define DIS_VIEW_ADDRESS 1
#define DIS_VIEW_CODE 2
int disThumb(u32 offset, char *dest, int flags);
int disArm(u32 offset, char *dest, int flags);
#endif // __ARMDIS_H__

432
src/bilinear.cpp Normal file
View File

@ -0,0 +1,432 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** Code adapted from Exult source code by Forgotten
** Scale.cc - Trying to scale with bilinear interpolation.
**
** Written: 6/14/00 - JSF
**/
#include "System.h"
static u8 row_cur[3*322];
static u8 row_next[3*322];
static u8 *rgb_row_cur = row_cur;
static u8 *rgb_row_next = row_next;
#define RGB(r,g,b) ((r)>>3) << systemRedShift |\
((g) >> 3) << systemGreenShift |\
((b) >> 3) << systemBlueShift\
static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width)
{
u8 *copy_start = row + src_width*3;
u8 *all_stop = row + width*3;
while (row < copy_start)
{
u16 color = *from++;
*row++ = ((color >> systemRedShift) & 0x1f) << 3;
*row++ = ((color >> systemGreenShift) & 0x1f) << 3;
*row++ = ((color >> systemBlueShift) & 0x1f) << 3;
}
// any remaining elements to be written to 'row' are a replica of the
// preceding pixel
u8 *p = row-3;
while (row < all_stop)
{
// we're guaranteed three elements per pixel; could unroll the loop
// further, especially with a Duff's Device, but the gains would be
// probably limited (judging by profiler output)
*row++ = *p++;
*row++ = *p++;
*row++ = *p++;
}
}
static void fill_rgb_row_32(u32 *from, int src_width, u8 *row, int width)
{
u8 *copy_start = row + src_width*3;
u8 *all_stop = row + width*3;
while (row < copy_start)
{
u32 color = *from++;
*row++ = ((color >> systemRedShift) & 0x1f) << 3;
*row++ = ((color >> systemGreenShift) & 0x1f) << 3;
*row++ = ((color >> systemBlueShift) & 0x1f) << 3;
}
// any remaining elements to be written to 'row' are a replica of the
// preceding pixel
u8 *p = row-3;
while (row < all_stop)
{
// we're guaranteed three elements per pixel; could unroll the loop
// further, especially with a Duff's Device, but the gains would be
// probably limited (judging by profiler output)
*row++ = *p++;
*row++ = *p++;
*row++ = *p++;
}
}
void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u16 *to = (u16 *)dstPtr;
u16 *to_odd = (u16 *)(dstPtr + dstPitch);
int from_width = width;
u16 *from = (u16 *)srcPtr;
fill_rgb_row_16(from, from_width, rgb_row_cur, width+1);
for(int y = 0; y < height; y++)
{
u16 *from_orig = from;
u16 *to_orig = to;
if (y+1 < height)
fill_rgb_row_16(from+width+2, from_width, rgb_row_next,
width+1);
else
fill_rgb_row_16(from, from_width, rgb_row_next, width+1);
// every pixel in the src region, is extended to 4 pixels in the
// destination, arranged in a square 'quad'; if the current src
// pixel is 'a', then in what follows 'b' is the src pixel to the
// right, 'c' is the src pixel below, and 'd' is the src pixel to
// the right and down
u8 *cur_row = rgb_row_cur;
u8 *next_row = rgb_row_next;
u8 *ar = cur_row++;
u8 *ag = cur_row++;
u8 *ab = cur_row++;
u8 *cr = next_row++;
u8 *cg = next_row++;
u8 *cb = next_row++;
for(int x=0; x < width; x++)
{
u8 *br = cur_row++;
u8 *bg = cur_row++;
u8 *bb = cur_row++;
u8 *dr = next_row++;
u8 *dg = next_row++;
u8 *db = next_row++;
// upper left pixel in quad: just copy it in
*to++ = RGB(*ar, *ag, *ab);
// upper right
*to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
// lower left
*to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
// lower right
*to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
(*ag+*bg+*cg+*dg)>>2,
(*ab+*bb+*cb+*db)>>2);
// 'b' becomes 'a', 'd' becomes 'c'
ar = br;
ag = bg;
ab = bb;
cr = dr;
cg = dg;
cb = db;
}
// the "next" rgb row becomes the current; the old current rgb row is
// recycled and serves as the new "next" row
u8 *temp;
temp = rgb_row_cur;
rgb_row_cur = rgb_row_next;
rgb_row_next = temp;
// update the pointers for start of next pair of lines
from = (u16 *)((u8 *)from_orig + srcPitch);
to = (u16 *)((u8 *)to_orig + (dstPitch << 1));
to_odd = (u16 *)((u8 *)to + dstPitch);
}
}
void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u16 *to = (u16 *)dstPtr;
u16 *to_odd = (u16 *)(dstPtr + dstPitch);
int from_width = width;
u16 *from = (u16 *)srcPtr;
fill_rgb_row_16(from, from_width, rgb_row_cur, width+1);
for(int y = 0; y < height; y++)
{
u16 *from_orig = from;
u16 *to_orig = to;
if (y+1 < height)
fill_rgb_row_16(from+width+2, from_width, rgb_row_next,
width+1);
else
fill_rgb_row_16(from, from_width, rgb_row_next, width+1);
// every pixel in the src region, is extended to 4 pixels in the
// destination, arranged in a square 'quad'; if the current src
// pixel is 'a', then in what follows 'b' is the src pixel to the
// right, 'c' is the src pixel below, and 'd' is the src pixel to
// the right and down
u8 *cur_row = rgb_row_cur;
u8 *next_row = rgb_row_next;
u8 *ar = cur_row++;
u8 *ag = cur_row++;
u8 *ab = cur_row++;
u8 *cr = next_row++;
u8 *cg = next_row++;
u8 *cb = next_row++;
for(int x=0; x < width; x++)
{
u8 *br = cur_row++;
u8 *bg = cur_row++;
u8 *bb = cur_row++;
u8 *dr = next_row++;
u8 *dg = next_row++;
u8 *db = next_row++;
// upper left pixel in quad: just copy it in
//*to++ = manip.rgb(*ar, *ag, *ab);
#ifdef USE_ORIGINAL_BILINEAR_PLUS
*to++ = RGB(
(((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3,
(((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3,
(((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3);
#else
*to++ = RGB(
(((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4,
(((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4,
(((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4);
#endif
// upper right
*to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
// lower left
*to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
// lower right
*to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
(*ag+*bg+*cg+*dg)>>2,
(*ab+*bb+*cb+*db)>>2);
// 'b' becomes 'a', 'd' becomes 'c'
ar = br;
ag = bg;
ab = bb;
cr = dr;
cg = dg;
cb = db;
}
// the "next" rgb row becomes the current; the old current rgb row is
// recycled and serves as the new "next" row
u8 *temp;
temp = rgb_row_cur;
rgb_row_cur = rgb_row_next;
rgb_row_next = temp;
// update the pointers for start of next pair of lines
from = (u16 *)((u8 *)from_orig + srcPitch);
to = (u16 *)((u8 *)to_orig + (dstPitch << 1));
to_odd = (u16 *)((u8 *)to + dstPitch);
}
}
void Bilinear32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u32 *to = (u32 *)dstPtr;
u32 *to_odd = (u32 *)(dstPtr + dstPitch);
int from_width = width;
if(width+1 < from_width)
from_width = width+1;
u32 *from = (u32 *)srcPtr;
fill_rgb_row_32(from, from_width, rgb_row_cur, width+1);
for(int y = 0; y < height; y++)
{
u32 *from_orig = from;
u32 *to_orig = to;
if (y+1 < height)
fill_rgb_row_32(from+width+1, from_width, rgb_row_next,
width+1);
else
fill_rgb_row_32(from, from_width, rgb_row_next, width+1);
// every pixel in the src region, is extended to 4 pixels in the
// destination, arranged in a square 'quad'; if the current src
// pixel is 'a', then in what follows 'b' is the src pixel to the
// right, 'c' is the src pixel below, and 'd' is the src pixel to
// the right and down
u8 *cur_row = rgb_row_cur;
u8 *next_row = rgb_row_next;
u8 *ar = cur_row++;
u8 *ag = cur_row++;
u8 *ab = cur_row++;
u8 *cr = next_row++;
u8 *cg = next_row++;
u8 *cb = next_row++;
for(int x=0; x < width; x++)
{
u8 *br = cur_row++;
u8 *bg = cur_row++;
u8 *bb = cur_row++;
u8 *dr = next_row++;
u8 *dg = next_row++;
u8 *db = next_row++;
// upper left pixel in quad: just copy it in
*to++ = RGB(*ar, *ag, *ab);
// upper right
*to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
// lower left
*to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
// lower right
*to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
(*ag+*bg+*cg+*dg)>>2,
(*ab+*bb+*cb+*db)>>2);
// 'b' becomes 'a', 'd' becomes 'c'
ar = br;
ag = bg;
ab = bb;
cr = dr;
cg = dg;
cb = db;
}
// the "next" rgb row becomes the current; the old current rgb row is
// recycled and serves as the new "next" row
u8 *temp;
temp = rgb_row_cur;
rgb_row_cur = rgb_row_next;
rgb_row_next = temp;
// update the pointers for start of next pair of lines
from = (u32 *)((u8 *)from_orig + srcPitch);
to = (u32 *)((u8 *)to_orig + (dstPitch << 1));
to_odd = (u32 *)((u8 *)to + dstPitch);
}
}
void BilinearPlus32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u32 *to = (u32 *)dstPtr;
u32 *to_odd = (u32 *)(dstPtr + dstPitch);
int from_width = width;
if(width+1 < from_width)
from_width = width+1;
u32 *from = (u32 *)srcPtr;
fill_rgb_row_32(from, from_width, rgb_row_cur, width+1);
for(int y = 0; y < height; y++)
{
u32 *from_orig = from;
u32 *to_orig = to;
if (y+1 < height)
fill_rgb_row_32(from+width+1, from_width, rgb_row_next,
width+1);
else
fill_rgb_row_32(from, from_width, rgb_row_next, width+1);
// every pixel in the src region, is extended to 4 pixels in the
// destination, arranged in a square 'quad'; if the current src
// pixel is 'a', then in what follows 'b' is the src pixel to the
// right, 'c' is the src pixel below, and 'd' is the src pixel to
// the right and down
u8 *cur_row = rgb_row_cur;
u8 *next_row = rgb_row_next;
u8 *ar = cur_row++;
u8 *ag = cur_row++;
u8 *ab = cur_row++;
u8 *cr = next_row++;
u8 *cg = next_row++;
u8 *cb = next_row++;
for(int x=0; x < width; x++)
{
u8 *br = cur_row++;
u8 *bg = cur_row++;
u8 *bb = cur_row++;
u8 *dr = next_row++;
u8 *dg = next_row++;
u8 *db = next_row++;
// upper left pixel in quad: just copy it in
//*to++ = manip.rgb(*ar, *ag, *ab);
#ifdef USE_ORIGINAL_BILINEAR_PLUS
*to++ = RGB(
(((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3,
(((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3,
(((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3);
#else
*to++ = RGB(
(((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4,
(((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4,
(((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4);
#endif
// upper right
*to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
// lower left
*to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
// lower right
*to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
(*ag+*bg+*cg+*dg)>>2,
(*ab+*bb+*cb+*db)>>2);
// 'b' becomes 'a', 'd' becomes 'c'
ar = br;
ag = bg;
ab = bb;
cr = dr;
cg = dg;
cb = db;
}
// the "next" rgb row becomes the current; the old current rgb row is
// recycled and serves as the new "next" row
u8 *temp;
temp = rgb_row_cur;
rgb_row_cur = rgb_row_next;
rgb_row_next = temp;
// update the pointers for start of next pair of lines
from = (u32 *)((u8 *)from_orig + srcPitch);
to = (u32 *)((u8 *)to_orig + (dstPitch << 1));
to_odd = (u32 *)((u8 *)to + dstPitch);
}
}

1293
src/bios.cpp Normal file

File diff suppressed because it is too large Load Diff

46
src/bios.h Normal file
View File

@ -0,0 +1,46 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_BIOS_H
#define VBA_BIOS_H
extern void BIOS_ArcTan();
extern void BIOS_ArcTan2();
extern void BIOS_BitUnPack();
extern void BIOS_BgAffineSet();
extern void BIOS_CpuSet();
extern void BIOS_CpuFastSet();
extern void BIOS_Diff8bitUnFilterWram();
extern void BIOS_Diff8bitUnFilterVram();
extern void BIOS_Diff16bitUnFilter();
extern void BIOS_Div();
extern void BIOS_DivARM();
extern void BIOS_HuffUnComp();
extern void BIOS_LZ77UnCompVram();
extern void BIOS_LZ77UnCompWram();
extern void BIOS_ObjAffineSet();
extern void BIOS_RegisterRamReset();
extern void BIOS_RegisterRamReset(u32);
extern void BIOS_RLUnCompVram();
extern void BIOS_RLUnCompWram();
extern void BIOS_SoftReset();
extern void BIOS_Sqrt();
extern void BIOS_MidiKey2Freq();
extern void BIOS_SndDriverJmpTableCopy();
#endif // VBA_BIOS_H

3248
src/elf.cpp Normal file

File diff suppressed because it is too large Load Diff

311
src/elf.h Normal file
View File

@ -0,0 +1,311 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_ELF_H
#define VBA_ELF_H
#include <fat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/dir.h>
enum LocationType {
LOCATION_register,
LOCATION_memory,
LOCATION_value
};
#define DW_ATE_boolean 0x02
#define DW_ATE_signed 0x05
#define DW_ATE_unsigned 0x07
#define DW_ATE_unsigned_char 0x08
struct ELFHeader
{
u32 magic;
u8 clazz;
u8 data;
u8 version;
u8 pad[9];
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
};
struct ELFProgramHeader
{
u32 type;
u32 offset;
u32 vaddr;
u32 paddr;
u32 filesz;
u32 memsz;
u32 flags;
u32 align;
};
struct ELFSectionHeader
{
u32 name;
u32 type;
u32 flags;
u32 addr;
u32 offset;
u32 size;
u32 link;
u32 info;
u32 addralign;
u32 entsize;
};
struct ELFSymbol
{
u32 name;
u32 value;
u32 size;
u8 info;
u8 other;
u16 shndx;
};
struct ELFBlock
{
int length;
u8 *data;
};
struct ELFAttr
{
u32 name;
u32 form;
union {
u32 value;
char *string;
u8 *data;
bool flag;
ELFBlock *block;
};
};
struct ELFAbbrev
{
u32 number;
u32 tag;
bool hasChildren;
int numAttrs;
ELFAttr *attrs;
ELFAbbrev *next;
};
enum TypeEnum {
TYPE_base,
TYPE_pointer,
TYPE_function,
TYPE_void,
TYPE_array,
TYPE_struct,
TYPE_reference,
TYPE_enum,
TYPE_union
};
struct Type;
struct Object;
struct FunctionType
{
Type *returnType;
Object *args;
};
struct Member
{
char *name;
Type *type;
int bitSize;
int bitOffset;
int byteSize;
ELFBlock *location;
};
struct Struct
{
int memberCount;
Member *members;
};
struct Array
{
Type *type;
int maxBounds;
int *bounds;
};
struct EnumMember
{
char *name;
u32 value;
};
struct Enum
{
int count;
EnumMember *members;
};
struct Type
{
u32 offset;
TypeEnum type;
char *name;
int encoding;
int size;
int bitSize;
union {
Type *pointer;
FunctionType *function;
Array *array;
Struct *structure;
Enum *enumeration;
};
Type *next;
};
struct Object
{
char *name;
int file;
int line;
bool external;
Type *type;
ELFBlock *location;
u32 startScope;
u32 endScope;
Object *next;
};
struct Function
{
char *name;
u32 lowPC;
u32 highPC;
int file;
int line;
bool external;
Type *returnType;
Object *parameters;
Object *variables;
ELFBlock *frameBase;
Function *next;
};
struct LineInfoItem
{
u32 address;
char *file;
int line;
};
struct LineInfo
{
int fileCount;
char **files;
int number;
LineInfoItem *lines;
};
struct ARange
{
u32 lowPC;
u32 highPC;
};
struct ARanges
{
u32 offset;
int count;
ARange *ranges;
};
struct CompileUnit
{
u32 length;
u8 *top;
u32 offset;
ELFAbbrev **abbrevs;
ARanges *ranges;
char *name;
char *compdir;
u32 lowPC;
u32 highPC;
bool hasLineInfo;
u32 lineInfo;
LineInfo *lineInfoTable;
Function *functions;
Function *lastFunction;
Object *variables;
Type *types;
CompileUnit *next;
};
struct DebugInfo
{
u8 *debugfile;
u8 *abbrevdata;
u8 *debugdata;
u8 *infodata;
int numRanges;
ARanges *ranges;
};
struct Symbol
{
char *name;
int type;
int binding;
u32 address;
u32 value;
u32 size;
};
extern u32 elfReadLEB128(u8 *, int *);
extern s32 elfReadSignedLEB128(u8 *, int *);
extern bool elfRead(const char *, int &, FILE* f);
extern bool elfGetSymbolAddress(char *,u32 *, u32 *, int *);
extern char *elfGetAddressSymbol(u32);
extern char *elfGetSymbol(int, u32 *, u32 *, int *);
extern void elfCleanUp();
extern bool elfGetCurrentFunction(u32, Function **, CompileUnit **c);
extern bool elfGetObject(char *, Function *, CompileUnit *, Object **);
extern bool elfFindLineInUnit(u32 *, CompileUnit *, int);
extern bool elfFindLineInModule(u32 *, char *, int);
u32 elfDecodeLocation(Function *, ELFBlock *, LocationType *);
u32 elfDecodeLocation(Function *, ELFBlock *, LocationType *, u32);
int elfFindLine(CompileUnit *unit, Function *func, u32 addr, char **);
#endif

69
src/exprNode.h Normal file
View File

@ -0,0 +1,69 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
struct Node
{
Type *type;
u32 location;
u32 objLocation;
LocationType locType;
int value;
int index;
char *name;
Node *expression;
Member *member;
void (*print)(Node *);
bool (*resolve)(Node *, Function *f, CompileUnit *u);
};
extern void exprNodeCleanUp();
extern Node *exprNodeIdentifier();
extern void exprNodeIdentifierPrint(Node *);
extern bool exprNodeIdentifierResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeNumber();
extern void exprNodeNumberPrint(Node *);
extern bool exprNodeNumberResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeStar(Node *);
extern void exprNodeStarPrint(Node *);
extern bool exprNodeStarResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeDot(Node *, Node *);
extern void exprNodeDotPrint(Node *);
extern bool exprNodeDotResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeArrow(Node *, Node *);
extern void exprNodeArrowPrint(Node *);
extern bool exprNodeArrowResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeAddr(Node *);
extern void exprNodeAddrPrint(Node *);
extern bool exprNodeAddrResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeSizeof(Node *);
extern void exprNodeSizeofPrint(Node *);
extern bool exprNodeSizeofResolve(Node *, Function *, CompileUnit *);
extern Node *exprNodeArray(Node *, Node *);
extern void exprNodeArrayPrint(Node *);
extern bool exprNodeArrayResolve(Node *, Function *, CompileUnit *);
#define YYSTYPE struct Node *

110
src/fileio/sdfileio.c Normal file
View File

@ -0,0 +1,110 @@
/****************************************************************************
* Generic File I/O for VisualBoyAdvance
*
* Currently only supports SD
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fat.h>
#include <sys/dir.h>
#define MAXDIRENTRIES 1000
char direntries[MAXDIRENTRIES][255];
/**
* SDInit
*/
void SDInit( void )
{
fatInitDefault();
}
/**
* SD Card f_open
*/
FILE* gen_fopen( const char *filename, const char *mode )
{
return fopen( filename, mode );
}
/**
* SD Card f_write
*/
int gen_fwrite( const void *buffer, int len, int block, FILE* f )
{
return fwrite(buffer, len, block, f);
}
/**
* SD Card f_read
*/
int gen_fread( void *buffer, int len, int block, FILE* f )
{
return fread(buffer, len, block, f);
}
/**
* SD Card fclose
*/
void gen_fclose( FILE* f )
{
fclose(f);
}
/**
* SD Card fseek
*
* NB: Only supports SEEK_SET
*/
int gen_fseek(FILE* f, int where, int whence)
{
fseek(f, where, whence);
return 1;
}
/**
* Simple fgetc
*/
int gen_fgetc( FILE* f )
{
return fgetc(f);
}
static struct stat _fstat;
char filename[1024];
int fcount = 0;
/**
* Get directory listing
*/
int gen_getdir( char *thisdir )
{
memset(&direntries[0],0,MAXDIRENTRIES*255);
DIR_ITER* dp = diropen( thisdir );
if ( dp )
{
while ( dirnext(dp, filename, &_fstat) == 0 )
{
// Skip any sub directories
if ( !(_fstat.st_mode & S_IFDIR) )
{
memcpy(&direntries[fcount],&filename,strlen(filename));
fcount++;
}
}
dirclose(dp);
}
else
return 0;
return fcount;
}

33
src/fileio/sdfileio.h Normal file
View File

@ -0,0 +1,33 @@
/****************************************************************************
* Generic File I/O for VisualBoyAdvance
*
* Currently only supports SD
****************************************************************************/
#ifndef __SDFILEIO__
#define __SDFILEIO__
#define MAXDIRENTRIES 1000
#include <fat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/dir.h>
extern "C"
{
/* Required Functions */
FILE* gen_fopen( const char *filename, const char *mode );
int gen_fwrite( const void *buffer, int len, int block, FILE* f );
int gen_fread( void *buffer, int len, int block, FILE* f );
void gen_fclose( FILE* f );
int gen_fseek(FILE* f, int where, int whence);
int gen_fgetc( FILE* f );
int SDInit( void );
int gen_getdir( char *thisdir );
extern char direntries[MAXDIRENTRIES][255];
}
#endif

3468
src/gb/GB.cpp Normal file

File diff suppressed because it is too large Load Diff

62
src/gb/GB.h Normal file
View File

@ -0,0 +1,62 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef VBA_GB_GB_H
#define VBA_GB_GB_H
#define C_FLAG 0x10
#define H_FLAG 0x20
#define N_FLAG 0x40
#define Z_FLAG 0x80
typedef union {
struct
{
#ifdef WORDS_BIGENDIAN
u8 B1, B0;
#else
u8 B0,B1;
#endif
}
B;
u16 W;
} gbRegister;
extern bool gbLoadRom(const char *);
extern void gbEmulate(int);
extern bool gbIsGameboyRom(const char *);
extern void gbSoundReset();
extern void gbSoundSetQuality(int);
extern void gbReset();
extern void gbCleanUp();
extern bool gbWriteBatteryFile(const char *);
extern bool gbWriteBatteryFile(const char *, bool);
extern bool gbReadBatteryFile(const char *);
extern bool gbWriteSaveState(const char *);
extern bool gbWriteMemSaveState(char *, int);
extern bool gbReadSaveState(const char *);
extern bool gbReadMemSaveState(char *, int);
extern void gbSgbRenderBorder();
extern bool gbWritePNGFile(const char *);
extern bool gbWriteBMPFile(const char *);
extern bool gbReadGSASnapshot(const char *);
extern struct EmulatedSystem GBSystem;
#endif

498
src/gb/gbCheats.cpp Normal file
View File

@ -0,0 +1,498 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sdfileio.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "../System.h"
#include "../NLS.h"
#include "../Util.h"
#include "gbCheats.h"
#include "gbGlobals.h"
gbCheat gbCheatList[100];
int gbCheatNumber = 0;
bool gbCheatMap[0x10000];
extern bool cheatsEnabled;
#define GBCHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
#define GBCHEAT_HEX_VALUE(a) ( (a) >= 'A' ? (a) - 'A' + 10 : (a) - '0')
void gbCheatUpdateMap()
{
memset(gbCheatMap, 0, 0x10000);
for(int i = 0; i < gbCheatNumber; i++)
{
if(gbCheatList[i].enabled)
gbCheatMap[gbCheatList[i].address] = true;
}
}
void gbCheatsSaveGame(gzFile gzFile)
{
utilWriteInt(gzFile, gbCheatNumber);
if(gbCheatNumber)
utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
}
void gbCheatsReadGame(gzFile gzFile, int version)
{
if(version <= 8)
{
int gbGgOn = utilReadInt(gzFile);
if(gbGgOn)
{
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for(int i = 0; i < n; i++)
{
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat));
gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
}
int gbGsOn = utilReadInt(gzFile);
if(gbGsOn)
{
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for(int i = 0; i < n; i++)
{
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat));
gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
}
}
else
{
gbCheatNumber = utilReadInt(gzFile);
if(gbCheatNumber)
{
utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
}
}
gbCheatUpdateMap();
}
void gbCheatsSaveCheatList(const char *file)
{
if(gbCheatNumber == 0)
return;
FILE* f = gen_fopen(file, "wb");
if(f == NULL)
return;
int version = 1;
gen_fwrite(&version, 1, sizeof(version), f);
int type = 1;
gen_fwrite(&type, 1, sizeof(type), f);
gen_fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f);
gen_fwrite(gbCheatList, 1, sizeof(gbCheatList), f);
gen_fclose(f);
}
bool gbCheatsLoadCheatList(const char *file)
{
gbCheatNumber = 0;
gbCheatUpdateMap();
int count = 0;
FILE* f = gen_fopen(file, "rb");
if(f == NULL)
return false;
int version = 0;
if(gen_fread(&version, 1, sizeof(version), f) != sizeof(version))
{
gen_fclose(f);
return false;
}
if(version != 1)
{
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
N_("Unsupported cheat list version %d"), version);
gen_fclose(f);
return false;
}
int type = 0;
if(gen_fread(&type, 1, sizeof(type), f) != sizeof(type))
{
gen_fclose(f);
return false;
}
if(type != 1)
{
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
N_("Unsupported cheat list type %d"), type);
gen_fclose(f);
return false;
}
if(gen_fread(&count, 1, sizeof(count), f) != sizeof(count))
{
gen_fclose(f);
return false;
}
if(gen_fread(gbCheatList, 1, sizeof(gbCheatList), f) != sizeof(gbCheatList))
{
gen_fclose(f);
return false;
}
gbCheatNumber = count;
gbCheatUpdateMap();
return true;
}
bool gbVerifyGsCode(const char *code)
{
int len = strlen(code);
if(len == 0)
return true;
if(len != 8)
return false;
for(int i = 0; i < 8; i++)
if(!GBCHEAT_IS_HEX(code[i]))
return false;
int address = GBCHEAT_HEX_VALUE(code[6]) << 12 |
GBCHEAT_HEX_VALUE(code[7]) << 8 |
GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);
if(address < 0xa000 ||
address > 0xdfff)
return false;
return true;
}
void gbAddGsCheat(const char *code, const char *desc)
{
if(gbCheatNumber > 99)
{
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return;
}
if(!gbVerifyGsCode(code))
{
systemMessage(MSG_INVALID_GAMESHARK_CODE,
N_("Invalid GameShark code: %s"), code);
return;
}
int i = gbCheatNumber;
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 |
GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 |
GBCHEAT_HEX_VALUE(code[3]);
gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 |
GBCHEAT_HEX_VALUE(code[7]) << 8 |
GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);
gbCheatList[i].compare = 0;
gbCheatList[i].enabled = true;
gbCheatMap[gbCheatList[i].address] = true;
gbCheatNumber++;
}
bool gbVerifyGgCode(const char *code)
{
int len = strlen(code);
if(len != 11 &&
len != 7 &&
len != 6 &&
len != 0)
return false;
if(len == 0)
return true;
if(!GBCHEAT_IS_HEX(code[0]))
return false;
if(!GBCHEAT_IS_HEX(code[1]))
return false;
if(!GBCHEAT_IS_HEX(code[2]))
return false;
if(code[3] != '-')
return false;
if(!GBCHEAT_IS_HEX(code[4]))
return false;
if(!GBCHEAT_IS_HEX(code[5]))
return false;
if(!GBCHEAT_IS_HEX(code[6]))
return false;
if(code[7] != 0)
{
if(code[7] != '-')
return false;
if(code[8] != 0)
{
if(!GBCHEAT_IS_HEX(code[8]))
return false;
if(!GBCHEAT_IS_HEX(code[9]))
return false;
if(!GBCHEAT_IS_HEX(code[10]))
return false;
}
}
// int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
// GBCHEAT_HEX_VALUE(code[1]);
int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) +
(GBCHEAT_HEX_VALUE(code[4]) << 4) +
(GBCHEAT_HEX_VALUE(code[5])) +
((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
if(address >= 0x8000 && address <= 0x9fff)
return false;
if(address >= 0xc000)
return false;
if(code[7] == 0 || code[8] == '0')
return true;
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) +
(GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0);
compare ^= 0x45;
int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9]));
if(cloak >=1 && cloak <= 7)
return false;
return true;
}
void gbAddGgCheat(const char *code, const char *desc)
{
if(gbCheatNumber > 99)
{
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return;
}
if(!gbVerifyGgCode(code))
{
systemMessage(MSG_INVALID_GAMEGENIE_CODE,
N_("Invalid GameGenie code: %s"), code);
return;
}
int i = gbCheatNumber;
int len = strlen(code);
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = 1;
gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) +
(GBCHEAT_HEX_VALUE(code[4]) << 4) +
(GBCHEAT_HEX_VALUE(code[5])) +
((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
gbCheatList[i].compare = 0;
if(len != 7 && len != 8)
{
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) +
(GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0);
compare ^= 0x45;
gbCheatList[i].compare = compare;
gbCheatList[i].code = 0;
}
gbCheatList[i].enabled = true;
gbCheatMap[gbCheatList[i].address] = true;
gbCheatNumber++;
}
void gbCheatRemove(int i)
{
if(i < 0 || i >= gbCheatNumber)
{
systemMessage(MSG_INVALID_CHEAT_TO_REMOVE,
N_("Invalid cheat to remove %d"), i);
return;
}
if((i+1) < gbCheatNumber)
{
memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)*
(gbCheatNumber-i-1));
}
gbCheatNumber--;
gbCheatUpdateMap();
}
void gbCheatRemoveAll()
{
gbCheatNumber = 0;
gbCheatUpdateMap();
}
void gbCheatEnable(int i)
{
if(i >=0 && i < gbCheatNumber)
{
if(!gbCheatList[i].enabled)
{
gbCheatList[i].enabled = true;
gbCheatUpdateMap();
}
}
}
void gbCheatDisable(int i)
{
if(i >=0 && i < gbCheatNumber)
{
if(gbCheatList[i].enabled)
{
gbCheatList[i].enabled = false;
gbCheatUpdateMap();
}
}
}
bool gbCheatReadGSCodeFile(const char *fileName)
{
FILE* file = gen_fopen(fileName, "rb");
if(!file)
{
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
return false;
}
gen_fseek(file, 0x18, SEEK_SET);
int count = 0;
gen_fread(&count, 1, 2, file);
int dummy = 0;
gbCheatRemoveAll();
char desc[13];
char code[9];
int i;
for(i = 0; i < count; i++)
{
gen_fread(&dummy, 1, 2, file);
gen_fread(desc, 1, 12, file);
desc[12] = 0;
gen_fread(code, 1, 8, file);
code[8] = 0;
gbAddGsCheat(code, desc);
}
for(i = 0; i < gbCheatNumber; i++)
gbCheatDisable(i);
gen_fclose(file);
return true;
}
u8 gbCheatRead(u16 address)
{
if(!cheatsEnabled)
return gbMemoryMap[address>>12][address & 0xFFF];
for(int i = 0; i < gbCheatNumber; i++)
{
if(gbCheatList[i].enabled && gbCheatList[i].address == address)
{
switch(gbCheatList[i].code)
{
case 0x100: // GameGenie support
if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare)
return gbCheatList[i].value;
break;
case 0x00:
case 0x01:
case 0x80:
return gbCheatList[i].value;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
if(address >= 0xd000 && address < 0xe000)
{
if(((gbMemoryMap[0x0d] - gbWram)/0x1000) ==
(gbCheatList[i].code - 0x90))
return gbCheatList[i].value;
}
else
return gbCheatList[i].value;
}
}
}
return gbMemoryMap[address>>12][address&0xFFF];
}

60
src/gb/gbCheats.h Normal file
View File

@ -0,0 +1,60 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __VBA_GB_GBCHEATS_H
#define __VBA_GB_GBCHEATS_H
#include "../System.h"
struct gbXxCheat
{
char cheatDesc[100];
char cheatCode[20];
};
struct gbCheat
{
char cheatCode[20];
char cheatDesc[32];
u16 address;
int code;
u8 compare;
u8 value;
bool enabled;
};
extern void gbCheatsSaveGame(gzFile);
extern void gbCheatsReadGame(gzFile, int);
extern void gbCheatsSaveCheatList(const char *);
extern bool gbCheatsLoadCheatList(const char *);
extern bool gbCheatReadGSCodeFile(const char *);
extern void gbAddGsCheat(const char *, const char*);
extern void gbAddGgCheat(const char *, const char*);
extern void gbCheatRemove(int);
extern void gbCheatRemoveAll();
extern void gbCheatEnable(int);
extern void gbCheatDisable(int);
extern u8 gbCheatRead(u16);
extern int gbCheatNumber;
extern gbCheat gbCheatList[100];
extern bool gbCheatMap[0x10000];
#endif

1445
src/gb/gbCodes.h Normal file

File diff suppressed because it is too large Load Diff

1336
src/gb/gbCodesCB.h Normal file

File diff suppressed because it is too large Load Diff

260
src/gb/gbDis.cpp Normal file
View File

@ -0,0 +1,260 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <string.h>
#include "../System.h"
#include "gbGlobals.h"
typedef struct
{
u8 mask;
u8 value;
char *mnen;
}
GBOPCODE;
#define GB_READ(x) gbMemoryMap[(x)>>12][(x)&0xfff]
static char *registers[] =
{ "B", "C", "D", "E", "H", "L", "(HL)", "A" };
static char *registers16[] =
{ "BC", "DE", "HL", "SP", // for some operations
"BC", "DE", "HL", "AF" }; // for push/pop
static char *cond[] =
{ "NZ", "Z", "NC", "C" };
static char hexDigits[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
static GBOPCODE opcodes[] = {
{ 0xff, 0x00, "NOP" },
{ 0xcf, 0x01, "LD %R4,%W" },
{ 0xff, 0x02, "LD (BC),A" },
{ 0xcf, 0x03, "INC %R4" },
{ 0xc7, 0x04, "INC %r3" },
{ 0xc7, 0x05, "DEC %r3" },
{ 0xc7, 0x06, "LD %r3,%B" },
{ 0xff, 0x07, "RLCA" },
{ 0xff, 0x08, "LD (%W),SP" },
{ 0xcf, 0x09, "ADD HL,%R4" },
{ 0xff, 0x0a, "LD A,(BC)" },
{ 0xcf, 0x0b, "DEC %R4" },
{ 0xff, 0x0f, "RRCA" },
{ 0xff, 0x10, "STOP" },
{ 0xff, 0x12, "LD (DE),A" },
{ 0xff, 0x17, "RLA" },
{ 0xff, 0x18, "JR %d" },
{ 0xff, 0x1a, "LD A,(DE)" },
{ 0xff, 0x1f, "RRA" },
{ 0xe7, 0x20, "JR %c3,%d" },
{ 0xff, 0x22, "LDI (HL),A" },
{ 0xff, 0x27, "DAA" },
{ 0xff, 0x2a, "LDI A,(HL)" },
{ 0xff, 0x2f, "CPL" },
{ 0xff, 0x32, "LDD (HL),A" },
{ 0xff, 0x37, "SCF" },
{ 0xff, 0x3a, "LDD A,(HL)" },
{ 0xff, 0x3f, "CCF" },
{ 0xff, 0x76, "HALT" },
{ 0xc0, 0x40, "LD %r3,%r0" },
{ 0xf8, 0x80, "ADD A,%r0" },
{ 0xf8, 0x88, "ADC A,%r0" },
{ 0xf8, 0x90, "SUB %r0" },
{ 0xf8, 0x98, "SBC A,%r0" },
{ 0xf8, 0xa0, "AND %r0" },
{ 0xf8, 0xa8, "XOR %r0" },
{ 0xf8, 0xb0, "OR %r0" },
{ 0xf8, 0xb8, "CP %r0" },
{ 0xe7, 0xc0, "RET %c3" },
{ 0xcf, 0xc1, "POP %t4" },
{ 0xe7, 0xc2, "JP %c3,%W" },
{ 0xff, 0xc3, "JP %W" },
{ 0xe7, 0xc4, "CALL %c3,%W" },
{ 0xcf, 0xc5, "PUSH %t4" },
{ 0xff, 0xc6, "ADD A,%B" },
{ 0xc7, 0xc7, "RST %P" },
{ 0xff, 0xc9, "RET" },
{ 0xff, 0xcd, "CALL %W" },
{ 0xff, 0xce, "ADC %B" },
{ 0xff, 0xd6, "SUB %B" },
{ 0xff, 0xd9, "RETI" },
{ 0xff, 0xde, "SBC %B" },
{ 0xff, 0xe0, "LD (FF%B),A" },
{ 0xff, 0xe2, "LD (FF00h+C),A" },
{ 0xff, 0xe6, "AND %B" },
{ 0xff, 0xe8, "ADD SP,%D" },
{ 0xff, 0xe9, "LD PC,HL" },
{ 0xff, 0xea, "LD (%W),A" },
{ 0xff, 0xee, "XOR %B" },
{ 0xff, 0xf0, "LD A,(FF%B)" },
{ 0xff, 0xf2, "LD A,(FF00h+C)" },
{ 0xff, 0xf3, "DI" },
{ 0xff, 0xf6, "OR %B" },
{ 0xff, 0xf8, "LD HL,SP%D" },
{ 0xff, 0xf9, "LD SP,HL" },
{ 0xff, 0xfa, "LD A,(%W)" },
{ 0xff, 0xfb, "EI" },
{ 0xff, 0xfe, "CP %B" },
{ 0x00, 0x00, "DB %B" }
};
static GBOPCODE cbOpcodes[] = {
{ 0xf8, 0x00, "RLC %r0" },
{ 0xf8, 0x08, "RRC %r0" },
{ 0xf8, 0x10, "RL %r0" },
{ 0xf8, 0x18, "RR %r0" },
{ 0xf8, 0x20, "SLA %r0" },
{ 0xf8, 0x28, "SRA %r0" },
{ 0xf8, 0x30, "SWAP %r0" },
{ 0xf8, 0x38, "SRL %r0" },
{ 0xc0, 0x40, "BIT %b,%r0" },
{ 0xc0, 0x80, "RES %b,%r0" },
{ 0xc0, 0xc0, "SET %b,%r0" },
{ 0x00, 0x00, "DB CBh,%B" }
};
static char *addHex(char *p, u8 value)
{
*p++ = hexDigits[value >> 4];
*p++ = hexDigits[value & 15];
return p;
}
static char *addHex16(char *p, u16 value)
{
p = addHex(p, value>>8);
return addHex(p, value & 255);
}
static char *addStr(char *p, char *s)
{
while(*s)
{
*p++ = *s++;
}
return p;
}
int gbDis(char *buffer, u16 address)
{
char *p = buffer;
int instr = 1;
u16 addr = address;
sprintf(p, "%04x ", address);
p += 12;
u8 opcode = GB_READ(address);
address++;
char *mnen;
GBOPCODE *op;
if(opcode == 0xcb)
{
opcode = GB_READ(address);
address++;
instr++;
op = cbOpcodes;
}
else
{
op = opcodes;
}
while(op->value != (opcode & op->mask)) op++;
mnen = op->mnen;
u8 b0, b1;
s8 disp;
int shift;
while(*mnen)
{
if(*mnen == '%')
{
mnen++;
switch(*mnen++)
{
case 'W':
b0 = GB_READ(address);
address++;
b1 = GB_READ(address);
address++;
p = addHex16(p, b0|b1<<8);
instr += 2;
*p++ = 'h';
break;
case 'B':
p = addHex(p, GB_READ(address));
*p++ = 'h';
address++;
instr++;
break;
case 'D':
disp = GB_READ(address);
if(disp >= 0)
*p++ = '+';
p += sprintf(p, "%d", disp);
instr++;
break;
case 'd':
disp = GB_READ(address);
address++;
p = addHex16(p, address+disp);
*p++ = 'h';
instr++;
break;
case 'b':
// kind of a hack, but it works :-)
*p++ = hexDigits[(opcode >> 3) & 7];
break;
case 'r':
shift = *mnen++ - '0';
p = addStr(p, registers[(opcode >> shift) & 7]);
break;
case 'R':
shift = *mnen++ - '0';
p = addStr(p, registers16[(opcode >> shift) & 3]);
break;
case 't':
shift = *mnen++ - '0';
p = addStr(p, registers16[4+((opcode >> shift) & 3)]);
break;
case 'P':
p = addHex(p, ((opcode >> 3) & 7) * 8);
break;
case 'c':
shift = *mnen++ - '0';
p = addStr(p, cond[(opcode >> shift) & 3]);
break;
}
}
else
*p++ = *mnen++;
}
for(int i = 0; i < instr; i++)
{
u16 a = addr + i;
addHex(buffer+5+i*2, GB_READ(a));
}
*p = 0;
return instr;
}

563
src/gb/gbGfx.cpp Normal file
View File

@ -0,0 +1,563 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <string.h>
#include "../GBA.h"
#include "gbGlobals.h"
#include "gbSGB.h"
u8 gbInvertTab[256] = {
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,
0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,
0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,
0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,
0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,
0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,
0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,
0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,
0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,
0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,
0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,
0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,
0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,
0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,
0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,
0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
};
u16 gbLineMix[160];
void gbRenderLine()
{
u8 * bank0;
u8 * bank1;
if(gbCgbMode)
{
bank0 = &gbVram[0x0000];
bank1 = &gbVram[0x2000];
}
else
{
bank0 = &gbMemory[0x8000];
bank1 = NULL;
}
int tile_map = 0x1800;
if((register_LCDC & 8) != 0)
tile_map = 0x1c00;
int tile_pattern = 0x0800;
if((register_LCDC & 16) != 0)
tile_pattern = 0x0000;
int x = 0;
int y = register_LY;
if(y >= 144)
return;
// int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip;
int sx = register_SCX;
int sy = register_SCY;
sy+=y;
sy &= 255;
int tx = sx >> 3;
int ty = sy >> 3;
int bx = 1 << (7 - (sx & 7));
int by = sy & 7;
int tile_map_line_y = tile_map + ty * 32;
int tile_map_address = tile_map_line_y + tx;
u8 attrs = 0;
if(bank1 != NULL)
attrs = bank1[tile_map_address];
u8 tile = bank0[tile_map_address];
tile_map_address++;
if((register_LCDC & 16) == 0)
{
if(tile < 128) tile += 128;
else tile -= 128;
}
int tile_pattern_address = tile_pattern + tile * 16 + by*2;
if(register_LCDC & 0x80)
{
if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100))
{
while(x < 160)
{
u8 tile_a = 0;
u8 tile_b = 0;
if(attrs & 0x40)
{
tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;
}
if(attrs & 0x08)
{
tile_a = bank1[tile_pattern_address++];
tile_b = bank1[tile_pattern_address];
}
else
{
tile_a = bank0[tile_pattern_address++];
tile_b = bank0[tile_pattern_address];
}
if(attrs & 0x20)
{
tile_a = gbInvertTab[tile_a];
tile_b = gbInvertTab[tile_b];
}
while(bx > 0)
{
u8 c = (tile_a & bx) ? 1 : 0;
c += ((tile_b & bx) ? 2 : 0);
gbLineBuffer[x] = c; // mark the gbLineBuffer color
if(attrs & 0x80)
gbLineBuffer[x] |= 0x300;
if(gbCgbMode)
{
c = c + (attrs & 7)*4;
}
else
{
c = gbBgp[c];
if(gbSgbMode && !gbCgbMode)
{
int dx = x >> 3;
int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx];
if(c == 0)
palette = 0;
c = c + 4*palette;
}
}
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
gbPalette[c];
x++;
if(x >= 160)
break;
bx >>= 1;
}
tx++;
if(tx == 32)
tx = 0;
bx = 128;
if(bank1)
attrs = bank1[tile_map_line_y + tx];
tile = bank0[tile_map_line_y + tx];
if((register_LCDC & 16) == 0)
{
if(tile < 128) tile += 128;
else tile -= 128;
}
tile_pattern_address = tile_pattern + tile * 16 + by * 2;
}
}
else
{
for(int i = 0; i < 160; i++)
{
gbLineMix[i] = gbPalette[0];
gbLineBuffer[i] = 0;
}
}
// do the window display
if((register_LCDC & 0x20) && (layerSettings & 0x2000))
{
int wy = register_WY;
if(y >= wy)
{
int wx = register_WX;
wx -= 7;
if( wx <= 159 && gbWindowLine <= 143)
{
tile_map = 0x1800;
if((register_LCDC & 0x40) != 0)
tile_map = 0x1c00;
if(gbWindowLine == -1)
{
gbWindowLine = 0;
}
tx = 0;
ty = gbWindowLine >> 3;
bx = 128;
by = gbWindowLine & 7;
if(wx < 0)
{
bx >>= (-wx);
wx = 0;
}
tile_map_line_y = tile_map + ty * 32;
tile_map_address = tile_map_line_y + tx;
x = wx;
tile = bank0[tile_map_address];
u8 attrs = 0;
if(bank1)
attrs = bank1[tile_map_address];
tile_map_address++;
if((register_LCDC & 16) == 0)
{
if(tile < 128) tile += 128;
else tile -= 128;
}
tile_pattern_address = tile_pattern + tile * 16 + by*2;
while(x < 160)
{
u8 tile_a = 0;
u8 tile_b = 0;
if(attrs & 0x40)
{
tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;
}
if(attrs & 0x08)
{
tile_a = bank1[tile_pattern_address++];
tile_b = bank1[tile_pattern_address];
}
else
{
tile_a = bank0[tile_pattern_address++];
tile_b = bank0[tile_pattern_address];
}
if(attrs & 0x20)
{
tile_a = gbInvertTab[tile_a];
tile_b = gbInvertTab[tile_b];
}
while(bx > 0)
{
u8 c = (tile_a & bx) != 0 ? 1 : 0;
c += ((tile_b & bx) != 0 ? 2 : 0);
if(attrs & 0x80)
gbLineBuffer[x] = 0x300 + c;
else
gbLineBuffer[x] = 0x100 + c;
if(gbCgbMode)
{
c = c + (attrs & 7) * 4;
}
else
{
c = gbBgp[c];
if(gbSgbMode && ! gbCgbMode)
{
int dx = x >> 3;
int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx];
if(c == 0)
palette = 0;
c = c + 4*palette;
}
}
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
gbPalette[c];
x++;
if(x >= 160)
break;
bx >>= 1;
}
tx++;
if(tx == 32)
tx = 0;
bx = 128;
tile = bank0[tile_map_line_y + tx];
if(bank1)
attrs = bank1[tile_map_line_y + tx];
if((register_LCDC & 16) == 0)
{
if(tile < 128) tile += 128;
else tile -= 128;
}
tile_pattern_address = tile_pattern + tile * 16 + by * 2;
}
gbWindowLine++;
}
}
}
}
else
{
for(int i = 0; i < 160; i++)
{
gbLineMix[i] = gbPalette[0];
gbLineBuffer[i] = 0;
}
}
}
void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int size,int spriteNumber)
{
u8 * bank0;
u8 * bank1;
if(gbCgbMode)
{
if(register_VBK & 1)
{
bank0 = &gbVram[0x0000];
bank1 = &gbVram[0x2000];
}
else
{
bank0 = &gbVram[0x0000];
bank1 = &gbVram[0x2000];
}
}
else
{
bank0 = &gbMemory[0x8000];
bank1 = NULL;
}
int init = 0x0000;
// int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip;
u8 *pal = gbObp0;
int flipx = (flags & 0x20);
int flipy = (flags & 0x40);
if((flags & 0x10))
pal = gbObp1;
if(flipy)
{
t = (size ? 15 : 7) - t;
}
int prio = flags & 0x80;
int address = init + tile * 16 + 2*t;
int a = 0;
int b = 0;
if(gbCgbMode && flags & 0x08)
{
a = bank1[address++];
b = bank1[address++];
}
else
{
a = bank0[address++];
b = bank0[address++];
}
for(int xx = 0; xx < 8; xx++)
{
u8 mask = 1 << (7-xx);
u8 c = 0;
if( (a & mask))
c++;
if( (b & mask))
c+=2;
if(c==0) continue;
int xxx = xx+x;
if(flipx)
xxx = (7-xx+x);
if(xxx < 0 || xxx > 159)
continue;
u16 color = gbLineBuffer[xxx];
if(prio)
{
if(color < 0x200 && ((color & 0xFF) != 0))
continue;
}
if(color >= 0x300 && color != 0x300)
continue;
else if(color >= 0x200 && color < 0x300)
{
int sprite = color & 0xff;
int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8;
if(spriteX == x)
{
if(sprite < spriteNumber)
continue;
}
else
{
if(gbCgbMode)
{
if(sprite < spriteNumber)
continue;
}
else
{
if(spriteX < x+8)
continue;
}
}
}
gbLineBuffer[xxx] = 0x200 + spriteNumber;
// make sure that sprites will work even in CGB mode
if(gbCgbMode)
{
c = c + (flags & 0x07)*4 + 32;
}
else
{
c = pal[c];
if(gbSgbMode && !gbCgbMode)
{
int dx = xxx >> 3;
int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx];
if(c == 0)
palette = 0;
c = c + 4*palette;
}
else
{
c += 4;
}
}
gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] :
gbPalette[c];
}
}
void gbDrawSprites()
{
int x = 0;
int y = 0;
int count = 0;
int size = (register_LCDC & 4);
if(!(register_LCDC & 0x80))
return;
if((register_LCDC & 2) && (layerSettings & 0x1000))
{
int yc = register_LY;
int address = 0xfe00;
for(int i = 0; i < 40; i++)
{
y = gbMemory[address++];
x = gbMemory[address++];
int tile = gbMemory[address++];
if(size)
tile &= 254;
int flags = gbMemory[address++];
if(x > 0 && y > 0 && x < 168 && y < 160)
{
// check if sprite intersects current line
int t = yc -y + 16;
if(size && t >=0 && t < 16)
{
gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i);
count++;
}
else if(!size && t >= 0 && t < 8)
{
gbDrawSpriteTile(tile, x-8, yc, t, flags,size,i);
count++;
}
}
// sprite limit reached!
if(count >= 10)
break;
}
}
}

54
src/gb/gbGlobals.cpp Normal file
View File

@ -0,0 +1,54 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../GBA.h"
u8 *gbMemoryMap[16];
int gbRomSizeMask = 0;
int gbRomSize = 0;
int gbRamSizeMask = 0;
int gbRamSize = 0;
u8 *gbMemory = NULL;
u8 *gbVram = NULL;
u8 *gbRom = NULL;
u8 *gbRam = NULL;
u8 *gbWram = NULL;
u16 *gbLineBuffer = NULL;
u16 gbPalette[128];
u8 gbBgp[4] = { 0, 1, 2, 3};
u8 gbObp0[4] = { 0, 1, 2, 3};
u8 gbObp1[4] = { 0, 1, 2, 3};
int gbWindowLine = -1;
int gbCgbMode = 0;
u16 gbColorFilter[32768];
int gbColorOption = 0;
int gbPaletteOption = 0;
int gbEmulatorType = 0;
int gbBorderOn = 1;
int gbBorderAutomatic = 0;
int gbBorderLineSkip = 160;
int gbBorderRowSkip = 0;
int gbBorderColumnSkip = 0;
int gbDmaTicks = 0;
u8 (*gbSerialFunction)(u8) = NULL;

68
src/gb/gbGlobals.h Normal file
View File

@ -0,0 +1,68 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern int gbRomSizeMask;
extern int gbRomSize;
extern int gbRamSize;
extern int gbRamSizeMask;
extern u8 *gbRom;
extern u8 *gbRam;
extern u8 *gbVram;
extern u8 *gbWram;
extern u8 *gbMemory;
extern u16 *gbLineBuffer;
extern u8 *gbMemoryMap[16];
extern int gbFrameSkip;
extern u16 gbColorFilter[32768];
extern int gbColorOption;
extern int gbPaletteOption;
extern int gbEmulatorType;
extern int gbBorderOn;
extern int gbBorderAutomatic;
extern int gbCgbMode;
extern int gbSgbMode;
extern int gbWindowLine;
extern int gbSpeed;
extern u8 gbBgp[4];
extern u8 gbObp0[4];
extern u8 gbObp1[4];
extern u16 gbPalette[128];
extern u8 register_LCDC;
extern u8 register_LY;
extern u8 register_SCY;
extern u8 register_SCX;
extern u8 register_WY;
extern u8 register_WX;
extern u8 register_VBK;
extern int emulating;
extern int gbBorderLineSkip;
extern int gbBorderRowSkip;
extern int gbBorderColumnSkip;
extern int gbDmaTicks;
extern void gbRenderLine();
extern void gbDrawSprites();
extern u8 (*gbSerialFunction)(u8);

1074
src/gb/gbMemory.cpp Normal file

File diff suppressed because it is too large Load Diff

156
src/gb/gbMemory.h Normal file
View File

@ -0,0 +1,156 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <time.h>
struct mapperMBC1
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
};
struct mapperMBC2
{
int mapperRAMEnable;
int mapperROMBank;
};
struct mapperMBC3
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperClockLatch;
int mapperClockRegister;
int mapperSeconds;
int mapperMinutes;
int mapperHours;
int mapperDays;
int mapperControl;
int mapperLSeconds;
int mapperLMinutes;
int mapperLHours;
int mapperLDays;
int mapperLControl;
time_t mapperLastTime;
};
struct mapperMBC5
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperROMHighAddress;
int mapperRAMAddress;
int isRumbleCartridge;
};
struct mapperMBC7
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int cs;
int sk;
int state;
int buffer;
int idle;
int count;
int code;
int address;
int writeEnable;
int value;
};
struct mapperHuC1
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
};
struct mapperHuC3
{
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperAddress;
int mapperRAMFlag;
int mapperRAMValue;
int mapperRegister1;
int mapperRegister2;
int mapperRegister3;
int mapperRegister4;
int mapperRegister5;
int mapperRegister6;
int mapperRegister7;
int mapperRegister8;
};
extern mapperMBC1 gbDataMBC1;
extern mapperMBC2 gbDataMBC2;
extern mapperMBC3 gbDataMBC3;
extern mapperMBC5 gbDataMBC5;
extern mapperHuC1 gbDataHuC1;
extern mapperHuC3 gbDataHuC3;
void mapperMBC1ROM(u16,u8);
void mapperMBC1RAM(u16,u8);
void mapperMBC2ROM(u16,u8);
void mapperMBC2RAM(u16,u8);
void mapperMBC3ROM(u16,u8);
void mapperMBC3RAM(u16,u8);
u8 mapperMBC3ReadRAM(u16);
void mapperMBC5ROM(u16,u8);
void mapperMBC5RAM(u16,u8);
void mapperMBC7ROM(u16,u8);
void mapperMBC7RAM(u16,u8);
u8 mapperMBC7ReadRAM(u16);
void mapperHuC1ROM(u16,u8);
void mapperHuC1RAM(u16,u8);
void mapperHuC3ROM(u16,u8);
void mapperHuC3RAM(u16,u8);
u8 mapperHuC3ReadRAM(u16);
//extern void (*mapper)(u16,u8);
//extern void (*mapperRAM)(u16,u8);
//extern u8 (*mapperReadRAM)(u16);
extern void memoryUpdateMapMBC1();
extern void memoryUpdateMapMBC2();
extern void memoryUpdateMapMBC3();
extern void memoryUpdateMapMBC5();
extern void memoryUpdateMapMBC7();
extern void memoryUpdateMapHuC1();
extern void memoryUpdateMapHuC3();

249
src/gb/gbPrinter.cpp Normal file
View File

@ -0,0 +1,249 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <string.h>
#include "../GBA.h"
u8 gbPrinterStatus = 0;
int gbPrinterState = 0;
u8 gbPrinterData[0x280*9];
u8 gbPrinterPacket[0x400];
int gbPrinterCount = 0;
int gbPrinterDataCount = 0;
int gbPrinterDataSize = 0;
int gbPrinterResult = 0;
bool gbPrinterCheckCRC()
{
u16 crc = 0;
for(int i = 2; i < (6+gbPrinterDataSize); i++)
{
crc += gbPrinterPacket[i];
}
int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] +
(gbPrinterPacket[7+gbPrinterDataSize]<<8);
return msgCrc == crc;
}
void gbPrinterReset()
{
gbPrinterState = 0;
gbPrinterDataSize = 0;
gbPrinterDataCount = 0;
gbPrinterCount = 0;
gbPrinterStatus = 0;
gbPrinterResult = 0;
}
void gbPrinterShowData()
{
systemGbPrint(gbPrinterData,
gbPrinterPacket[6],
gbPrinterPacket[7],
gbPrinterPacket[8],
gbPrinterPacket[9]);
/*
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0);
PALETTE pal;
pal[0].r = 255;
pal[0].g = 255;
pal[0].b = 255;
pal[1].r = 168;
pal[1].g = 168;
pal[1].b = 168;
pal[2].r = 96;
pal[2].g = 96;
pal[2].b = 96;
pal[3].r = 0;
pal[3].g = 0;
pal[3].b = 0;
set_palette(pal);
acquire_screen();
u8 *data = gbPrinterData;
for(int y = 0; y < 0x12; y++) {
for(int x = 0; x < 0x14; x++) {
for(int k = 0; k < 8; k++) {
int a = *data++;
int b = *data++;
for(int j = 0; j < 8; j++) {
int mask = 1 << (7-j);
int c = 0;
if(a & mask)
c++;
if(b & mask)
c+=2;
putpixel(screen, x*8+j, y*8+k, c);
}
}
}
}
release_screen();
while(!keypressed()) {
}
*/
}
void gbPrinterReceiveData()
{
if(gbPrinterPacket[3])
{ // compressed
u8 *data = &gbPrinterPacket[6];
u8 *dest = &gbPrinterData[gbPrinterDataCount];
int len = 0;
while(len < gbPrinterDataSize)
{
u8 control = *data++;
if(control & 0x80)
{ // repeated data
control &= 0x7f;
control += 2;
memset(dest, *data++, control);
len += control;
dest += control;
}
else
{ // raw data
control++;
memcpy(dest, data, control);
dest += control;
data += control;
len += control;
}
}
}
else
{
memcpy(&gbPrinterData[gbPrinterDataCount],
&gbPrinterPacket[6],
gbPrinterDataSize);
gbPrinterDataCount += gbPrinterDataSize;
}
}
void gbPrinterCommand()
{
switch(gbPrinterPacket[2])
{
case 0x01:
// reset/initialize packet
gbPrinterDataCount = 0;
gbPrinterStatus = 0;
break;
case 0x02:
// print packet
gbPrinterShowData();
break;
case 0x04:
// data packet
gbPrinterReceiveData();
break;
case 0x0f:
// NUL packet
break;
}
}
u8 gbPrinterSend(u8 b)
{
switch(gbPrinterState)
{
case 0:
gbPrinterCount = 0;
// receiving preamble
if(b == 0x88)
{
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
}
else
{
// todo: handle failure
gbPrinterReset();
}
break;
case 1:
// receiving preamble
if(b == 0x33)
{
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
}
else
{
// todo: handle failure
gbPrinterReset();
}
break;
case 2:
// receiving header
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == 6)
{
gbPrinterState++;
gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8);
}
break;
case 3:
// receiving data
if(gbPrinterDataSize)
{
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == (6+gbPrinterDataSize))
{
gbPrinterState++;
}
break;
}
gbPrinterState++;
// intentionally move to next if no data to receive
case 4:
// receiving CRC
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
break;
case 5:
// receiving CRC-2
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCheckCRC())
{
gbPrinterCommand();
}
gbPrinterState++;
break;
case 6:
// receiving dummy 1
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = 0x81;
gbPrinterState++;
break;
case 7:
// receiving dummy 2
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = gbPrinterStatus;
gbPrinterState = 0;
gbPrinterCount = 0;
break;
}
return gbPrinterResult;
}

20
src/gb/gbPrinter.h Normal file
View File

@ -0,0 +1,20 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern u8 gbPrinterSend(u8 b);

1014
src/gb/gbSGB.cpp Normal file

File diff suppressed because it is too large Load Diff

39
src/gb/gbSGB.h Normal file
View File

@ -0,0 +1,39 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void gbSgbInit();
void gbSgbShutdown();
void gbSgbCommand();
void gbSgbResetPacketState();
void gbSgbReset();
void gbSgbDoBitTransfer(u8);
void gbSgbSaveGame(gzFile);
void gbSgbReadGame(gzFile, int version);
void gbSgbRenderBorder();
extern u8 gbSgbATF[20*18];
extern int gbSgbMode;
extern int gbSgbMask;
extern int gbSgbMultiplayer;
extern u8 gbSgbNextController;
extern int gbSgbPacketTimeout;
extern u8 gbSgbReadingController;
extern int gbSgbFourPlayers;

1065
src/gb/gbSound.cpp Normal file

File diff suppressed because it is too large Load Diff

59
src/gb/gbSound.h Normal file
View File

@ -0,0 +1,59 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define NR10 0xff10
#define NR11 0xff11
#define NR12 0xff12
#define NR13 0xff13
#define NR14 0xff14
#define NR21 0xff16
#define NR22 0xff17
#define NR23 0xff18
#define NR24 0xff19
#define NR30 0xff1a
#define NR31 0xff1b
#define NR32 0xff1c
#define NR33 0xff1d
#define NR34 0xff1e
#define NR41 0xff20
#define NR42 0xff21
#define NR43 0xff22
#define NR44 0xff23
#define NR50 0xff24
#define NR51 0xff25
#define NR52 0xff26
#define SOUND_EVENT(address,value) \
gbSoundEvent(address,value)
extern void gbSoundTick();
extern void gbSoundPause();
extern void gbSoundResume();
extern void gbSoundEnable(int);
extern void gbSoundDisable(int);
extern int gbSoundGetEnable();
extern void gbSoundReset();
extern void gbSoundSaveGame(gzFile);
extern void gbSoundReadGame(int,gzFile);
extern void gbSoundEvent(register u16, register int);
extern void gbSoundSetQuality(int);
extern int soundTicks;
extern int soundQuality;
extern int SOUND_CLOCK_TICKS;

1061
src/getopt.c Normal file

File diff suppressed because it is too large Load Diff

142
src/getopt.h Normal file
View File

@ -0,0 +1,142 @@
/* Declarations for getopt.
Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000
Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org.
This program 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 2, or (at your option) any
later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C"
{
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if defined (__STDC__) && __STDC__
/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is
undefined, we haven't run the autoconf check so provide the
declaration without arguments. If it is 0, we checked and failed
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
#if defined (__GNU_LIBRARY__) || (defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
# if !defined (HAVE_DECL_GETOPT)
extern int getopt ();
# endif
#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* getopt.h */

191
src/getopt1.c Normal file
View File

@ -0,0 +1,191 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
NOTE: This source is derived from an old version taken from the GNU C
Library (glibc).
This program 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 2, or (at your option) any
later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0
},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

643
src/interframe.cpp Normal file
View File

@ -0,0 +1,643 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
#include <stdlib.h>
#include <string.h>
#ifdef MMX
extern "C" bool cpu_mmx;
#endif
/*
* Thanks to Kawaks' Mr. K for the code
Incorporated into vba by Anthony Di Franco
*/
static u8 *frm1 = NULL;
static u8 *frm2 = NULL;
static u8 *frm3 = NULL;
extern int RGB_LOW_BITS_MASK;
extern u32 qRGB_COLOR_MASK[2];
static void Init()
{
frm1 = (u8 *)calloc(322*242,4);
// 1 frame ago
frm2 = (u8 *)calloc(322*242,4);
// 2 frames ago
frm3 = (u8 *)calloc(322*242,4);
// 3 frames ago
}
void InterframeCleanup()
{
if(frm1)
free(frm1);
if(frm2)
free(frm2);
if(frm3)
free(frm3);
frm1 = frm2 = frm3 = NULL;
}
#ifdef MMX
static void SmartIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
{
u16 *src0 = (u16 *)srcPtr;
u16 *src1 = (u16 *)frm1;
u16 *src2 = (u16 *)frm2;
u16 *src3 = (u16 *)frm3;
int count = width >> 2;
for(int i = 0; i < height; i++)
{
#ifdef __GNUC__
asm volatile (
"push %4\n"
"movq 0(%5), %%mm7\n" // colorMask
"0:\n"
"movq 0(%0), %%mm0\n" // src0
"movq 0(%1), %%mm1\n" // src1
"movq 0(%2), %%mm2\n" // src2
"movq 0(%3), %%mm3\n" // src3
"movq %%mm0, 0(%3)\n" // src3 = src0
"movq %%mm0, %%mm4\n"
"movq %%mm1, %%mm5\n"
"pcmpeqw %%mm2, %%mm5\n" // src1 == src2 (A)
"pcmpeqw %%mm3, %%mm4\n" // src3 == src0 (B)
"por %%mm5, %%mm4\n" // A | B
"movq %%mm2, %%mm5\n"
"pcmpeqw %%mm0, %%mm5\n" // src0 == src2 (C)
"pcmpeqw %%mm1, %%mm3\n" // src1 == src3 (D)
"por %%mm3, %%mm5\n" // C|D
"pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
"movq %%mm0, %%mm2\n"
"pand %%mm7, %%mm2\n" // color & colorMask
"pand %%mm7, %%mm1\n" // src1 & colorMask
"psrlw $1, %%mm2\n" // (color & colorMask) >> 1 (E)
"psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
"paddw %%mm2, %%mm1\n" // E+F
"pand %%mm4, %%mm1\n" // (E+F) & res
"pandn %%mm0, %%mm4\n" // color& !res
"por %%mm1, %%mm4\n"
"movq %%mm4, 0(%0)\n" // src0 = res
"addl $8, %0\n"
"addl $8, %1\n"
"addl $8, %2\n"
"addl $8, %3\n"
"decl %4\n"
"jnz 0b\n"
"pop %4\n"
"emms\n"
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
: "r" (count), "r" (qRGB_COLOR_MASK)
);
#else
__asm {
movq mm7, qword ptr [qRGB_COLOR_MASK];
mov eax, src0;
mov ebx, src1;
mov ecx, src2;
mov edx, src3;
mov edi, count;
label0:
movq mm0, qword ptr [eax]; // src0
movq mm1, qword ptr [ebx]; // src1
movq mm2, qword ptr [ecx]; // src2
movq mm3, qword ptr [edx]; // src3
movq qword ptr [edx], mm0; // src3 = src0
movq mm4, mm0;
movq mm5, mm1;
pcmpeqw mm5, mm2; // src1 == src2 (A)
pcmpeqw mm4, mm3; // src3 == src0 (B)
por mm4, mm5; // A | B
movq mm5, mm2;
pcmpeqw mm5, mm0; // src0 == src2 (C)
pcmpeqw mm3, mm1; // src1 == src3 (D)
por mm5, mm3; // C|D
pandn mm4, mm5; // (!(A|B))&(C|D)
movq mm2, mm0;
pand mm2, mm7; // color & colorMask
pand mm1, mm7; // src1 & colorMask
psrlw mm2, 1; // (color & colorMask) >> 1 (E)
psrlw mm1, 1; // (src & colorMask) >> 1 (F)
paddw mm1, mm2; // E+F
pand mm1, mm4; // (E+F) & res
pandn mm4, mm0; // color & !res
por mm4, mm1;
movq qword ptr [eax], mm4; // src0 = res
add eax, 8;
add ebx, 8;
add ecx, 8;
add edx, 8;
dec edi;
jnz label0;
mov src0, eax;
mov src1, ebx;
mov src2, ecx;
mov src3, edx;
emms;
}
#endif
src0+=2;
src1+=2;
src2+=2;
src3+=2;
}
/* Swap buffers around */
u8 *temp = frm1;
frm1 = frm3;
frm3 = frm2;
frm2 = temp;
}
#endif
void SmartIB(u8 *srcPtr, u32 srcPitch, int width, int height)
{
if(frm1 == NULL)
{
Init();
}
#ifdef MMX
if(cpu_mmx)
{
SmartIB_MMX(srcPtr, srcPitch, width, height);
return;
}
#endif
u16 colorMask = ~RGB_LOW_BITS_MASK;
u16 *src0 = (u16 *)srcPtr;
u16 *src1 = (u16 *)frm1;
u16 *src2 = (u16 *)frm2;
u16 *src3 = (u16 *)frm3;
int sPitch = srcPitch >> 1;
int pos = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < sPitch; i++)
{
u16 color = src0[pos];
src0[pos] =
(src1[pos] != src2[pos]) &&
(src3[pos] != color) &&
((color == src2[pos]) || (src1[pos] == src3[pos]))
? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
color;
src3[pos] = color; /* oldest buffer now holds newest frame */
pos++;
}
/* Swap buffers around */
u8 *temp = frm1;
frm1 = frm3;
frm3 = frm2;
frm2 = temp;
}
#ifdef MMX
static void SmartIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
{
u32 *src0 = (u32 *)srcPtr;
u32 *src1 = (u32 *)frm1;
u32 *src2 = (u32 *)frm2;
u32 *src3 = (u32 *)frm3;
int count = width >> 1;
for(int i = 0; i < height; i++)
{
#ifdef __GNUC__
asm volatile (
"push %4\n"
"movq 0(%5), %%mm7\n" // colorMask
"0:\n"
"movq 0(%0), %%mm0\n" // src0
"movq 0(%1), %%mm1\n" // src1
"movq 0(%2), %%mm2\n" // src2
"movq 0(%3), %%mm3\n" // src3
"movq %%mm0, 0(%3)\n" // src3 = src0
"movq %%mm0, %%mm4\n"
"movq %%mm1, %%mm5\n"
"pcmpeqd %%mm2, %%mm5\n" // src1 == src2 (A)
"pcmpeqd %%mm3, %%mm4\n" // src3 == src0 (B)
"por %%mm5, %%mm4\n" // A | B
"movq %%mm2, %%mm5\n"
"pcmpeqd %%mm0, %%mm5\n" // src0 == src2 (C)
"pcmpeqd %%mm1, %%mm3\n" // src1 == src3 (D)
"por %%mm3, %%mm5\n" // C|D
"pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
"movq %%mm0, %%mm2\n"
"pand %%mm7, %%mm2\n" // color & colorMask
"pand %%mm7, %%mm1\n" // src1 & colorMask
"psrld $1, %%mm2\n" // (color & colorMask) >> 1 (E)
"psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
"paddd %%mm2, %%mm1\n" // E+F
"pand %%mm4, %%mm1\n" // (E+F) & res
"pandn %%mm0, %%mm4\n" // color& !res
"por %%mm1, %%mm4\n"
"movq %%mm4, 0(%0)\n" // src0 = res
"addl $8, %0\n"
"addl $8, %1\n"
"addl $8, %2\n"
"addl $8, %3\n"
"decl %4\n"
"jnz 0b\n"
"pop %4\n"
"emms\n"
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
: "r" (count), "r" (qRGB_COLOR_MASK)
);
#else
__asm {
movq mm7, qword ptr [qRGB_COLOR_MASK];
mov eax, src0;
mov ebx, src1;
mov ecx, src2;
mov edx, src3;
mov edi, count;
label0:
movq mm0, qword ptr [eax]; // src0
movq mm1, qword ptr [ebx]; // src1
movq mm2, qword ptr [ecx]; // src2
movq mm3, qword ptr [edx]; // src3
movq qword ptr [edx], mm0; // src3 = src0
movq mm4, mm0;
movq mm5, mm1;
pcmpeqd mm5, mm2; // src1 == src2 (A)
pcmpeqd mm4, mm3; // src3 == src0 (B)
por mm4, mm5; // A | B
movq mm5, mm2;
pcmpeqd mm5, mm0; // src0 == src2 (C)
pcmpeqd mm3, mm1; // src1 == src3 (D)
por mm5, mm3; // C|D
pandn mm4, mm5; // (!(A|B))&(C|D)
movq mm2, mm0;
pand mm2, mm7; // color & colorMask
pand mm1, mm7; // src1 & colorMask
psrld mm2, 1; // (color & colorMask) >> 1 (E)
psrld mm1, 1; // (src & colorMask) >> 1 (F)
paddd mm1, mm2; // E+F
pand mm1, mm4; // (E+F) & res
pandn mm4, mm0; // color & !res
por mm4, mm1;
movq qword ptr [eax], mm4; // src0 = res
add eax, 8;
add ebx, 8;
add ecx, 8;
add edx, 8;
dec edi;
jnz label0;
mov src0, eax;
mov src1, ebx;
mov src2, ecx;
mov src3, edx;
emms;
}
#endif
src0++;
src1++;
src2++;
src3++;
}
/* Swap buffers around */
u8 *temp = frm1;
frm1 = frm3;
frm3 = frm2;
frm2 = temp;
}
#endif
void SmartIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
{
if(frm1 == NULL)
{
Init();
}
#ifdef MMX
if(cpu_mmx)
{
SmartIB32_MMX(srcPtr, srcPitch, width, height);
return;
}
#endif
u32 *src0 = (u32 *)srcPtr;
u32 *src1 = (u32 *)frm1;
u32 *src2 = (u32 *)frm2;
u32 *src3 = (u32 *)frm3;
u32 colorMask = 0xfefefe;
int sPitch = srcPitch >> 2;
int pos = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < sPitch; i++)
{
u32 color = src0[pos];
src0[pos] =
(src1[pos] != src2[pos]) &&
(src3[pos] != color) &&
((color == src2[pos]) || (src1[pos] == src3[pos]))
? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
color;
src3[pos] = color; /* oldest buffer now holds newest frame */
pos++;
}
/* Swap buffers around */
u8 *temp = frm1;
frm1 = frm3;
frm3 = frm2;
frm2 = temp;
}
#ifdef MMX
static void MotionBlurIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
{
u16 *src0 = (u16 *)srcPtr;
u16 *src1 = (u16 *)frm1;
int count = width >> 2;
for(int i = 0; i < height; i++)
{
#ifdef __GNUC__
asm volatile (
"push %2\n"
"movq 0(%3), %%mm7\n" // colorMask
"0:\n"
"movq 0(%0), %%mm0\n" // src0
"movq 0(%1), %%mm1\n" // src1
"movq %%mm0, 0(%1)\n" // src1 = src0
"pand %%mm7, %%mm0\n" // color & colorMask
"pand %%mm7, %%mm1\n" // src1 & colorMask
"psrlw $1, %%mm0\n" // (color & colorMask) >> 1 (E)
"psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
"paddw %%mm1, %%mm0\n" // E+F
"movq %%mm0, 0(%0)\n" // src0 = res
"addl $8, %0\n"
"addl $8, %1\n"
"decl %2\n"
"jnz 0b\n"
"pop %2\n"
"emms\n"
: "+r" (src0), "+r" (src1)
: "r" (count), "r" (qRGB_COLOR_MASK)
);
#else
__asm {
movq mm7, qword ptr [qRGB_COLOR_MASK];
mov eax, src0;
mov ebx, src1;
mov edi, count;
label0:
movq mm0, qword ptr [eax]; // src0
movq mm1, qword ptr [ebx]; // src1
movq qword ptr [ebx], mm0; // src1 = src0
pand mm0, mm7; // color & colorMask
pand mm1, mm7; // src1 & colorMask
psrlw mm0, 1; // (color & colorMask) >> 1 (E)
psrlw mm1, 1; // (src & colorMask) >> 1 (F)
paddw mm0, mm1; // E+F
movq qword ptr [eax], mm0; // src0 = res
add eax, 8;
add ebx, 8;
dec edi;
jnz label0;
mov src0, eax;
mov src1, ebx;
emms;
}
#endif
src0+=2;
src1+=2;
}
}
#endif
void MotionBlurIB(u8 *srcPtr, u32 srcPitch, int width, int height)
{
if(frm1 == NULL)
{
Init();
}
#ifdef MMX
if(cpu_mmx)
{
MotionBlurIB_MMX(srcPtr, srcPitch, width, height);
return;
}
#endif
u16 colorMask = ~RGB_LOW_BITS_MASK;
u16 *src0 = (u16 *)srcPtr;
u16 *src1 = (u16 *)frm1;
int sPitch = srcPitch >> 1;
int pos = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < sPitch; i++)
{
u16 color = src0[pos];
src0[pos] =
(((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1));
src1[pos] = color;
pos++;
}
}
#ifdef MMX
static void MotionBlurIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
{
u32 *src0 = (u32 *)srcPtr;
u32 *src1 = (u32 *)frm1;
int count = width >> 1;
for(int i = 0; i < height; i++)
{
#ifdef __GNUC__
asm volatile (
"push %2\n"
"movq 0(%3), %%mm7\n" // colorMask
"0:\n"
"movq 0(%0), %%mm0\n" // src0
"movq 0(%1), %%mm1\n" // src1
"movq %%mm0, 0(%1)\n" // src1 = src0
"pand %%mm7, %%mm0\n" // color & colorMask
"pand %%mm7, %%mm1\n" // src1 & colorMask
"psrld $1, %%mm0\n" // (color & colorMask) >> 1 (E)
"psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
"paddd %%mm1, %%mm0\n" // E+F
"movq %%mm0, 0(%0)\n" // src0 = res
"addl $8, %0\n"
"addl $8, %1\n"
"decl %2\n"
"jnz 0b\n"
"pop %2\n"
"emms\n"
: "+r" (src0), "+r" (src1)
: "r" (count), "r" (qRGB_COLOR_MASK)
);
#else
__asm {
movq mm7, qword ptr [qRGB_COLOR_MASK];
mov eax, src0;
mov ebx, src1;
mov edi, count;
label0:
movq mm0, qword ptr [eax]; // src0
movq mm1, qword ptr [ebx]; // src1
movq qword ptr [ebx], mm0; // src1 = src0
pand mm0, mm7; // color & colorMask
pand mm1, mm7; // src1 & colorMask
psrld mm0, 1; // (color & colorMask) >> 1 (E)
psrld mm1, 1; // (src & colorMask) >> 1 (F)
paddd mm0, mm1; // E+F
movq qword ptr [eax], mm0; // src0 = res
add eax, 8;
add ebx, 8;
dec edi;
jnz label0;
mov src0, eax;
mov src1, ebx;
emms;
}
#endif
src0++;
src1++;
}
}
#endif
void MotionBlurIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
{
if(frm1 == NULL)
{
Init();
}
#ifdef MMX
if(cpu_mmx)
{
MotionBlurIB32_MMX(srcPtr, srcPitch, width, height);
return;
}
#endif
u32 *src0 = (u32 *)srcPtr;
u32 *src1 = (u32 *)frm1;
u32 colorMask = 0xfefefe;
int sPitch = srcPitch >> 2;
int pos = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < sPitch; i++)
{
u32 color = src0[pos];
src0[pos] = (((color & colorMask) >> 1) +
((src1[pos] & colorMask) >> 1));
src1[pos] = color;
pos++;
}
}
static int count = 0;
void InterlaceIB(u8 *srcPtr, u32 srcPitch, int width, int height)
{
if(frm1 == NULL)
{
Init();
}
u16 colorMask = ~RGB_LOW_BITS_MASK;
u16 *src0 = (u16 *)srcPtr;
u16 *src1 = (u16 *)frm1;
int sPitch = srcPitch >> 1;
int pos = 0;
for (int j = 0; j < height; j++)
{
bool render = count ? (j & 1) != 0 : (j & 1) == 0;
if(render)
{
for (int i = 0; i < sPitch; i++)
{
u16 color = src0[pos];
src0[pos] =
(((color & colorMask) >> 1) + ((((src1[pos] & colorMask) >> 1) & colorMask) >> 1));
src1[pos] = color;
pos++;
}
}
else
{
for (int i = 0; i < sPitch; i++)
{
u16 color = src0[pos];
src0[pos] =
(((((color & colorMask) >> 1) & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1));
src1[pos] = color;
pos++;
}
}
}
count = count ^ 1;
}

298
src/interp.h Normal file
View File

@ -0,0 +1,298 @@
/*
* This file is part of the Advance project.
*
* Copyright (C) 2003 Andrea Mazzoleni
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Andrea Mazzoleni
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#ifndef __INTERP_H
#define __INTERP_H
/***************************************************************************/
/* Basic types */
/***************************************************************************/
/* interpolation */
static unsigned interp_mask[2];
static unsigned interp_bits_per_pixel;
#define INTERP_16_MASK_1(v) (v & interp_mask[0])
#define INTERP_16_MASK_2(v) (v & interp_mask[1])
static inline u16 interp_16_521(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8);
}
static inline u16 interp_16_332(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8);
}
static inline u16 interp_16_611(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8);
}
static inline u16 interp_16_71(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8);
}
static inline u16 interp_16_211(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4);
}
static inline u16 interp_16_772(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16)
| INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16);
}
static inline u16 interp_16_11(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2);
}
static inline u16 interp_16_31(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4);
}
static inline u16 interp_16_1411(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16);
}
static inline u16 interp_16_431(u16 p1, u16 p2, u16 p3)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8);
}
static inline u16 interp_16_53(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8);
}
static inline u16 interp_16_151(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16);
}
static inline u16 interp_16_97(u16 p1, u16 p2)
{
return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16)
| INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16);
}
#define INTERP_32_MASK_1(v) (v & 0xFF00FF)
#define INTERP_32_MASK_2(v) (v & 0x00FF00)
static inline u32 interp_32_521(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8);
}
static inline u32 interp_32_332(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8);
}
static inline u32 interp_32_211(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4);
}
static inline u32 interp_32_611(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8);
}
static inline u32 interp_32_71(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8);
}
static inline u32 interp_32_772(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16)
| INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16);
}
static inline u32 interp_32_11(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2);
}
static inline u32 interp_32_31(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4);
}
static inline u32 interp_32_1411(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16);
}
static inline u32 interp_32_431(u32 p1, u32 p2, u32 p3)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8);
}
static inline u32 interp_32_53(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8);
}
static inline u32 interp_32_151(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16);
}
static inline u32 interp_32_97(u32 p1, u32 p2)
{
return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16)
| INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16);
}
/***************************************************************************/
/* diff */
#define INTERP_Y_LIMIT (0x30*4)
#define INTERP_U_LIMIT (0x07*4)
#define INTERP_V_LIMIT (0x06*8)
static int interp_16_diff(u16 p1, u16 p2)
{
int r, g, b;
int y, u, v;
if (p1 == p2)
return 0;
if (interp_bits_per_pixel == 16)
{
b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3;
r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8;
}
else
{
b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2;
r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7;
}
y = r + g + b;
u = r - b;
v = -r + 2*g - b;
if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
return 1;
if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
return 1;
if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
return 1;
return 0;
}
static int interp_32_diff(u32 p1, u32 p2)
{
int r, g, b;
int y, u, v;
if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8))
return 0;
b = (int)((p1 & 0xFF) - (p2 & 0xFF));
g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8;
r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16;
y = r + g + b;
u = r - b;
v = -r + 2*g - b;
if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
return 1;
if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
return 1;
if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
return 1;
return 0;
}
static void interp_set(unsigned bits_per_pixel)
{
interp_bits_per_pixel = bits_per_pixel;
switch (bits_per_pixel)
{
case 15 :
interp_mask[0] = 0x7C1F;
interp_mask[1] = 0x03E0;
break;
case 16 :
interp_mask[0] = 0xF81F;
interp_mask[1] = 0x07E0;
break;
case 32 :
interp_mask[0] = 0xFF00FF;
interp_mask[1] = 0x00FF00;
break;
}
}
#endif

750
src/memgzio.c Normal file
View File

@ -0,0 +1,750 @@
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-2002 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Compile this file with -DNO_DEFLATE to avoid the compression code.
*/
/* memgzio.c - IO on .gz files in memory
* Adapted from original gzio.c from zlib library by Forgotten
*/
/* @(#) $Id: memgzio.c,v 1.3 2004/01/17 23:07:32 kxu Exp $ */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "memgzio.h"
/*struct internal_state {int dummy;};*/ /* for buggy compilers */
#ifndef Z_BUFSIZE
# ifdef MAXSEG_64K
# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
# else
# define Z_BUFSIZE 16384
# endif
#endif
#ifndef Z_PRINTF_BUFSIZE
# define Z_PRINTF_BUFSIZE 4096
#endif
#define ALLOC(size) malloc(size)
#define TRYFREE(p) {if (p) free(p);}
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef struct _MemFile
{
char *memory;
char *next;
int available;
int error;
char mode;
}
MEMFILE;
typedef struct mem_stream
{
z_stream stream;
int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */
MEMFILE *file; /* memoru file */
Byte *inbuf; /* input buffer */
Byte *outbuf; /* output buffer */
uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */
int transparent; /* 1 if input file is not a .gz file */
char mode; /* 'w' or 'r' */
long startpos; /* start of compressed data in file (header skipped) */
}
mem_stream;
local gzFile gz_open OF((char *memory, const int available, const char *mode));
local int do_flush OF((gzFile file, int flush));
local int get_byte OF((mem_stream *s));
local void check_header OF((mem_stream *s));
local int destroy OF((mem_stream *s));
local void putLong OF((MEMFILE *file, uLong x));
local uLong getLong OF((mem_stream *s));
local MEMFILE *memOpen(char *memory, int available, char mode)
{
MEMFILE *f;
if(available <= 8)
return NULL;
if(mode != 'w' && mode != 'r')
return NULL;
f = (MEMFILE *)malloc(sizeof(MEMFILE));
f->memory = memory;
f->mode = mode;
f->error = 0;
if(mode == 'w')
{
f->available = available - 8;
f->next = memory + 8;
memory[0] = 'V';
memory[1] = 'B';
memory[2] = 'A';
memory[3] = ' ';
*((int *)(memory+4)) = 0;
}
else
{
if(memory[0] != 'V' || memory[1] != 'B' || memory[2] != 'A' ||
memory[3] != ' ')
{
free(f);
return NULL;
}
f->available = *((int *)(memory+4));
f->next = memory+8;
}
return f;
}
local size_t memWrite(const void *buffer, size_t size, size_t count,
MEMFILE *file)
{
size_t total = size*count;
if(file->mode != 'w')
{
file->error = 1;
return 0;
}
if(total > (size_t)file->available)
{
total = file->available;
}
memcpy(file->next, buffer, total);
file->available -= total;
file->next += total;
return total;
}
local size_t memRead(void *buffer, size_t size, size_t count,
MEMFILE *file)
{
size_t total = size*count;
if(file->mode != 'r')
{
file->error = 1;
return 0;
}
if(file->available == 0)
return -1;
if(total > (size_t)file->available)
{
total = file->available;
}
memcpy(buffer, file->next, total);
file->available -= total;
file->next += total;
return total;
}
local int memPutc(int c, MEMFILE *file)
{
if(file->mode != 'w')
{
file->error = 1;
return -1;
}
if(file->available >= 1)
{
*file->next++ = c;
file->available--;
}
else
return -1;
return c;
}
local long memTell(MEMFILE *f)
{
return (f->next - f->memory) - 8;
}
local int memError(MEMFILE *f)
{
return f->error;
}
local int memClose(MEMFILE *f)
{
if(f->mode == 'w')
{
*((int *)(f->memory+4)) = memTell(f);
}
free(f);
return 0;
}
local int memPrintf(MEMFILE *f, const char *format, ...)
{
char buffer[80];
va_list list;
int len;
va_start(list, format);
len = vsprintf(buffer, format, list);
va_end(list);
return memWrite(buffer, 1, len, f);
}
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing. The mode parameter
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
or path name (if fd == -1).
gz_open return NULL if the file could not be opened or if there was
insufficient memory to allocate the (de)compression state; errno
can be checked to distinguish the two cases (if errno is zero, the
zlib error is Z_MEM_ERROR).
*/
local gzFile gz_open (memory, available, mode)
char *memory;
const int available;
const char *mode;
{
int err;
int level = Z_DEFAULT_COMPRESSION; /* compression level */
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
char *p = (char*)mode;
mem_stream *s;
char fmode[80]; /* copy of mode, without the compression level */
char *m = fmode;
s = (mem_stream *)ALLOC(sizeof(mem_stream));
if (!s) return Z_NULL;
s->stream.zalloc = (alloc_func)0;
s->stream.zfree = (free_func)0;
s->stream.opaque = (voidpf)0;
s->stream.next_in = s->inbuf = Z_NULL;
s->stream.next_out = s->outbuf = Z_NULL;
s->stream.avail_in = s->stream.avail_out = 0;
s->z_err = Z_OK;
s->z_eof = 0;
s->crc = crc32(0L, Z_NULL, 0);
s->msg = NULL;
s->transparent = 0;
s->file = NULL;
s->mode = '\0';
do
{
if (*p == 'r') s->mode = 'r';
if (*p == 'w' || *p == 'a') s->mode = 'w';
if (*p >= '0' && *p <= '9')
{
level = *p - '0';
}
else if (*p == 'f')
{
strategy = Z_FILTERED;
}
else if (*p == 'h')
{
strategy = Z_HUFFMAN_ONLY;
}
else
{
*m++ = *p; /* copy the mode */
}
}
while (*p++ && m != fmode + sizeof(fmode));
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
if (s->mode == 'w')
{
#ifdef NO_DEFLATE
err = Z_STREAM_ERROR;
#else
err = deflateInit2(&(s->stream), level,
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
/* windowBits is passed < 0 to suppress zlib header */
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
#endif
if (err != Z_OK || s->outbuf == Z_NULL)
{
return destroy(s), (gzFile)Z_NULL;
}
}
else
{
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
err = inflateInit2(&(s->stream), -MAX_WBITS);
/* windowBits is passed < 0 to tell that there is no zlib header.
* Note that in this case inflate *requires* an extra "dummy" byte
* after the compressed stream in order to complete decompression and
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
* present after the compressed stream.
*/
if (err != Z_OK || s->inbuf == Z_NULL)
{
return destroy(s), (gzFile)Z_NULL;
}
}
s->stream.avail_out = Z_BUFSIZE;
errno = 0;
s->file = memOpen(memory, available, s->mode);
if (s->file == NULL)
{
return destroy(s), (gzFile)Z_NULL;
}
if (s->mode == 'w')
{
/* Write a very simple .gz header:
*/
memPrintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
s->startpos = 10L;
/* We use 10L instead of ftell(s->file) to because ftell causes an
* fflush on some systems. This version of the library doesn't use
* startpos anyway in write mode, so this initialization is not
* necessary.
*/
}
else
{
check_header(s); /* skip the .gz header */
s->startpos = (memTell(s->file) - s->stream.avail_in);
}
return (gzFile)s;
}
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing.
*/
gzFile ZEXPORT memgzopen (memory, available, mode)
char *memory;
int available;
const char *mode;
{
return gz_open (memory, available, mode);
}
/* ===========================================================================
Read a byte from a mem_stream; update next_in and avail_in. Return EOF
for end of file.
IN assertion: the stream s has been sucessfully opened for reading.
*/
local int get_byte(s)
mem_stream *s;
{
if (s->z_eof) return EOF;
if (s->stream.avail_in == 0)
{
errno = 0;
s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0)
{
s->z_eof = 1;
if (memError(s->file)) s->z_err = Z_ERRNO;
return EOF;
}
s->stream.next_in = s->inbuf;
}
s->stream.avail_in--;
return *(s->stream.next_in)++;
}
/* ===========================================================================
Check the gzip header of a mem_stream opened for reading. Set the stream
mode to transparent if the gzip magic header is not present; set s->err
to Z_DATA_ERROR if the magic header is present but the rest of the header
is incorrect.
IN assertion: the stream s has already been created sucessfully;
s->stream.avail_in is zero for the first time, but may be non-zero
for concatenated .gz files.
*/
local void check_header(s)
mem_stream *s;
{
int method; /* method byte */
int flags; /* flags byte */
uInt len;
int c;
/* Check the gzip magic header */
for (len = 0; len < 2; len++)
{
c = get_byte(s);
if (c != gz_magic[len])
{
if (len != 0) s->stream.avail_in++, s->stream.next_in--;
if (c != EOF)
{
s->stream.avail_in++, s->stream.next_in--;
s->transparent = 1;
}
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
return;
}
}
method = get_byte(s);
flags = get_byte(s);
if (method != Z_DEFLATED || (flags & RESERVED) != 0)
{
s->z_err = Z_DATA_ERROR;
return;
}
/* Discard time, xflags and OS code: */
for (len = 0; len < 6; len++) (void)get_byte(s);
if ((flags & EXTRA_FIELD) != 0)
{ /* skip the extra field */
len = (uInt)get_byte(s);
len += ((uInt)get_byte(s))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && get_byte(s) != EOF) ;
}
if ((flags & ORIG_NAME) != 0)
{ /* skip the original file name */
while ((c = get_byte(s)) != 0 && c != EOF) ;
}
if ((flags & COMMENT) != 0)
{ /* skip the .gz file comment */
while ((c = get_byte(s)) != 0 && c != EOF) ;
}
if ((flags & HEAD_CRC) != 0)
{ /* skip the header crc */
for (len = 0; len < 2; len++) (void)get_byte(s);
}
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
}
/* ===========================================================================
* Cleanup then free the given mem_stream. Return a zlib error code.
Try freeing in the reverse order of allocations.
*/
local int destroy (s)
mem_stream *s;
{
int err = Z_OK;
if (!s) return Z_STREAM_ERROR;
TRYFREE(s->msg);
if (s->stream.state != NULL)
{
if (s->mode == 'w')
{
#ifdef NO_DEFLATE
err = Z_STREAM_ERROR;
#else
err = deflateEnd(&(s->stream));
#endif
}
else if (s->mode == 'r')
{
err = inflateEnd(&(s->stream));
}
}
if (s->file != NULL && memClose(s->file))
{
#ifdef ESPIPE
if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
#endif
err = Z_ERRNO;
}
if (s->z_err < 0) err = s->z_err;
TRYFREE(s->inbuf);
TRYFREE(s->outbuf);
TRYFREE(s);
return err;
}
/* ===========================================================================
Reads the given number of uncompressed bytes from the compressed file.
gzread returns the number of bytes actually read (0 for end of file).
*/
int ZEXPORT memgzread (file, buf, len)
gzFile file;
voidp buf;
unsigned len;
{
mem_stream *s = (mem_stream*)file;
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
next_out = (Byte*)buf;
s->stream.next_out = (Bytef*)buf;
s->stream.avail_out = len;
while (s->stream.avail_out != 0)
{
if (s->transparent)
{
/* Copy first the lookahead bytes: */
uInt n = s->stream.avail_in;
if (n > s->stream.avail_out) n = s->stream.avail_out;
if (n > 0)
{
zmemcpy(s->stream.next_out, s->stream.next_in, n);
next_out += n;
s->stream.next_out = next_out;
s->stream.next_in += n;
s->stream.avail_out -= n;
s->stream.avail_in -= n;
}
if (s->stream.avail_out > 0)
{
s->stream.avail_out -= memRead(next_out, 1, s->stream.avail_out,
s->file);
}
len -= s->stream.avail_out;
s->stream.total_in += (uLong)len;
s->stream.total_out += (uLong)len;
if (len == 0) s->z_eof = 1;
return (int)len;
}
if (s->stream.avail_in == 0 && !s->z_eof)
{
errno = 0;
s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0)
{
s->z_eof = 1;
if (memError(s->file))
{
s->z_err = Z_ERRNO;
break;
}
}
s->stream.next_in = s->inbuf;
}
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
if (s->z_err == Z_STREAM_END)
{
/* Check CRC and original size */
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
start = s->stream.next_out;
if (getLong(s) != s->crc)
{
s->z_err = Z_DATA_ERROR;
}
else
{
(void)getLong(s);
/* The uncompressed length returned by above getlong() may
* be different from s->stream.total_out) in case of
* concatenated .gz files. Check for such files:
*/
check_header(s);
if (s->z_err == Z_OK)
{
uLong total_in = s->stream.total_in;
uLong total_out = s->stream.total_out;
inflateReset(&(s->stream));
s->stream.total_in = total_in;
s->stream.total_out = total_out;
s->crc = crc32(0L, Z_NULL, 0);
}
}
}
if (s->z_err != Z_OK || s->z_eof) break;
}
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
return (int)(len - s->stream.avail_out);
}
#ifndef NO_DEFLATE
/* ===========================================================================
Writes the given number of uncompressed bytes into the compressed file.
gzwrite returns the number of bytes actually written (0 in case of error).
*/
int ZEXPORT memgzwrite (file, buf, len)
gzFile file;
const voidp buf;
unsigned len;
{
mem_stream *s = (mem_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.next_in = (Bytef*)buf;
s->stream.avail_in = len;
while (s->stream.avail_in != 0)
{
if (s->stream.avail_out == 0)
{
s->stream.next_out = s->outbuf;
if (memWrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE)
{
s->z_err = Z_ERRNO;
break;
}
s->stream.avail_out = Z_BUFSIZE;
}
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
if (s->z_err != Z_OK) break;
}
s->crc = crc32(s->crc, (const Bytef *)buf, len);
return (int)(len - s->stream.avail_in);
}
#endif
/* ===========================================================================
Flushes all pending output into the compressed file. The parameter
flush is as in the deflate() function.
*/
local int do_flush (file, flush)
gzFile file;
int flush;
{
uInt len;
int done = 0;
mem_stream *s = (mem_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.avail_in = 0; /* should be zero already anyway */
for (;;)
{
len = Z_BUFSIZE - s->stream.avail_out;
if (len != 0)
{
if ((uInt)memWrite(s->outbuf, 1, len, s->file) != len)
{
s->z_err = Z_ERRNO;
return Z_ERRNO;
}
s->stream.next_out = s->outbuf;
s->stream.avail_out = Z_BUFSIZE;
}
if (done) break;
s->z_err = deflate(&(s->stream), flush);
/* Ignore the second of two consecutive flushes: */
if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
/* deflate has finished flushing only when it hasn't used up
* all the available space in the output buffer:
*/
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
}
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
}
/* ===========================================================================
Outputs a long in LSB order to the given file
*/
local void putLong (file, x)
MEMFILE *file;
uLong x;
{
int n;
for (n = 0; n < 4; n++)
{
memPutc((int)(x & 0xff), file);
x >>= 8;
}
}
/* ===========================================================================
Reads a long in LSB order from the given mem_stream. Sets z_err in case
of error.
*/
local uLong getLong (s)
mem_stream *s;
{
uLong x = (uLong)get_byte(s);
int c;
x += ((uLong)get_byte(s))<<8;
x += ((uLong)get_byte(s))<<16;
c = get_byte(s);
if (c == EOF) s->z_err = Z_DATA_ERROR;
x += ((uLong)c)<<24;
return x;
}
/* ===========================================================================
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state.
*/
int ZEXPORT memgzclose (file)
gzFile file;
{
int err;
mem_stream *s = (mem_stream*)file;
if (s == NULL) return Z_STREAM_ERROR;
if (s->mode == 'w')
{
#ifdef NO_DEFLATE
return Z_STREAM_ERROR;
#else
err = do_flush (file, Z_FINISH);
if (err != Z_OK) return destroy((mem_stream*)file);
putLong (s->file, s->crc);
putLong (s->file, s->stream.total_in);
#endif
}
return destroy((mem_stream*)file);
}
long ZEXPORT memtell(file)
gzFile file;
{
mem_stream *s = (mem_stream*)file;
if (s == NULL) return Z_STREAM_ERROR;
return memTell(s->file);
}

21
src/memgzio.h Normal file
View File

@ -0,0 +1,21 @@
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-2002 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Compile this file with -DNO_DEFLATE to avoid the compression code.
*/
/* memgzio.c - IO on .gz files in memory
* Adapted from original gzio.c from zlib library by Forgotten
*/
#ifndef HAVE_ZUTIL_H
#include "../win32/include/zlib/zutil.h"
#else
#include <zutil.h>
#endif
gzFile ZEXPORT memgzopen(char *memory, int, const char *);
int ZEXPORT memgzread(gzFile, voidp, unsigned);
int ZEXPORT memgzwrite(gzFile, const voidp, unsigned);
int ZEXPORT memgzclose(gzFile);
long ZEXPORT memtell(gzFile);

289
src/ngc/gcpad.cpp Normal file
View File

@ -0,0 +1,289 @@
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
* Nintendo GameCube Joypad Wrapper
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#define VBA_BUTTON_A 1
#define VBA_BUTTON_B 2
#define VBA_BUTTON_SELECT 4
#define VBA_BUTTON_START 8
#define VBA_RIGHT 16
#define VBA_LEFT 32
#define VBA_UP 64
#define VBA_DOWN 128
#define VBA_BUTTON_R 256
#define VBA_BUTTON_L 512
#define VBA_SPEED 1024
#define VBA_CAPTURE 2048
#ifdef WII_BUILD
#include <math.h>
#include <wiiuse/wpad.h>
int isClassicAvailable = 0;
int isWiimoteAvailable = 0;
/*
#ifndef PI
#define PI 3.14159f
#endif
enum { STICK_X, STICK_Y };
static int getStickValue(joystick_t* j, int axis, int maxAbsValue){
double angle = PI * j->ang/180.0f;
double magnitude = (j->mag > 1.0f) ? 1.0f :
(j->mag < -1.0f) ? -1.0f : j->mag;
double value;
if(axis == STICK_X)
value = magnitude * sin( angle );
else
value = magnitude * cos( angle );
return (int)(value * maxAbsValue);
}*/
#endif
int menuCalled = 0;
u32
NGCPad()
{
u32 res = 0;
short p;
signed char x,
y;
int padcal = 90;
float t;
#ifdef WII_BUILD
//wiimote
if(isWiimoteAvailable)
{
WPADData wpad;
WPAD_Read(0, &wpad);
unsigned short b = wpad.btns_d;
if (b & WPAD_BUTTON_2)
res |= VBA_BUTTON_A;
if (b & WPAD_BUTTON_1)
res |= VBA_BUTTON_B;
if (b & WPAD_BUTTON_MINUS)
res |= VBA_BUTTON_SELECT;
if (b & WPAD_BUTTON_PLUS)
res |= VBA_BUTTON_START;
if (b & WPAD_BUTTON_RIGHT)
res |= VBA_UP;
if (b & WPAD_BUTTON_LEFT)
res |= VBA_DOWN;
if (b & WPAD_BUTTON_UP)
res |= VBA_LEFT;
if (b & WPAD_BUTTON_DOWN)
res |= VBA_RIGHT;
if (b & WPAD_BUTTON_A)
res |= VBA_BUTTON_L;
if (b & WPAD_BUTTON_B)
res |= VBA_BUTTON_R;
if (b & WPAD_BUTTON_HOME)
menuCalled = 1;
}
//classic controller
if(isClassicAvailable)
{
WPADData wpad;
WPAD_Read(0, &wpad);
int b = wpad.exp.classic.btns;
int x_s = 0; //getStickValue(&wpad.exp.classic.ljs, STICK_X, 127);
int y_s = 0; //getStickValue(&wpad.exp.classic.ljs, STICK_Y, 127);
if (b & CLASSIC_CTRL_BUTTON_A)
res |= VBA_BUTTON_A;
if (b & CLASSIC_CTRL_BUTTON_B)
res |= VBA_BUTTON_B;
if (b & CLASSIC_CTRL_BUTTON_MINUS)
res |= VBA_BUTTON_SELECT;
if (b & CLASSIC_CTRL_BUTTON_PLUS)
res |= VBA_BUTTON_START;
if ((b & CLASSIC_CTRL_BUTTON_UP) || (y_s > 0))
res |= VBA_UP;
if ((b & CLASSIC_CTRL_BUTTON_DOWN) || (y_s < 0))
res |= VBA_DOWN;
if ((b & CLASSIC_CTRL_BUTTON_LEFT) || (x_s < 0))
res |= VBA_LEFT;
if ((b & CLASSIC_CTRL_BUTTON_RIGHT) || (x_s > 0))
res |= VBA_RIGHT;
if (b & CLASSIC_CTRL_BUTTON_FULL_L)
res |= VBA_BUTTON_L;
if (b & CLASSIC_CTRL_BUTTON_FULL_R)
res |= VBA_BUTTON_R;
if (b & CLASSIC_CTRL_BUTTON_HOME)
menuCalled = 1;
}
//user needs a GC remote
else if((!(isWiimoteAvailable)) && (!(isClassicAvailable)))
{
p = PAD_ButtonsHeld(0);
x = PAD_StickX(0);
y = PAD_StickY(0);
if (x * x + y * y > padcal * padcal)
{
if (x > 0 && y == 0)
res |= VBA_RIGHT;
if (x < 0 && y == 0)
res |= VBA_LEFT;
if (x == 0 && y > 0)
res |= VBA_UP;
if (x == 0 && y < 0)
res |= VBA_DOWN;
/*** Recalc left / right ***/
t = (float) y / x;
if (t >= -2.41421356237 && t < 2.41421356237)
{
if (x >= 0)
res |= VBA_RIGHT;
else
res |= VBA_LEFT;
}
/*** Recalc up / down ***/
t = (float) x / y;
if (t >= -2.41421356237 && t < 2.41421356237)
{
if (y >= 0)
res |= VBA_UP;
else
res |= VBA_DOWN;
}
}
if (p & PAD_BUTTON_A)
res |= VBA_BUTTON_A;
if (p & PAD_BUTTON_B)
res |= VBA_BUTTON_B;
if (p & PAD_TRIGGER_Z)
res |= VBA_BUTTON_SELECT;
if (p & PAD_BUTTON_START)
res |= VBA_BUTTON_START;
if (p & PAD_BUTTON_UP)
res |= VBA_UP;
if (p & PAD_BUTTON_DOWN)
res |= VBA_DOWN;
if (p & PAD_BUTTON_LEFT)
res |= VBA_LEFT;
if (p & PAD_BUTTON_RIGHT)
res |= VBA_RIGHT;
if (p & PAD_TRIGGER_L)
res |= VBA_BUTTON_L;
if (p & PAD_TRIGGER_R)
res |= VBA_BUTTON_R;
if((p & PAD_BUTTON_X) && (p & PAD_BUTTON_Y))
menuCalled = 1;
}
#endif
#ifdef GC_BUILD
p = PAD_ButtonsHeld(0);
x = PAD_StickX(0);
y = PAD_StickY(0);
if (x * x + y * y > padcal * padcal)
{
if (x > 0 && y == 0)
res |= VBA_RIGHT;
if (x < 0 && y == 0)
res |= VBA_LEFT;
if (x == 0 && y > 0)
res |= VBA_UP;
if (x == 0 && y < 0)
res |= VBA_DOWN;
/*** Recalc left / right ***/
t = (float) y / x;
if (t >= -2.41421356237 && t < 2.41421356237)
{
if (x >= 0)
res |= VBA_RIGHT;
else
res |= VBA_LEFT;
}
/*** Recalc up / down ***/
t = (float) x / y;
if (t >= -2.41421356237 && t < 2.41421356237)
{
if (y >= 0)
res |= VBA_UP;
else
res |= VBA_DOWN;
}
}
if (p & PAD_BUTTON_A)
res |= VBA_BUTTON_A;
if (p & PAD_BUTTON_B)
res |= VBA_BUTTON_B;
if (p & PAD_TRIGGER_Z)
res |= VBA_BUTTON_SELECT;
if (p & PAD_BUTTON_START)
res |= VBA_BUTTON_START;
if ((p & PAD_BUTTON_UP))
res |= VBA_UP;
if ((p & PAD_BUTTON_DOWN))
res |= VBA_DOWN;
if ((p & PAD_BUTTON_LEFT))
res |= VBA_LEFT;
if ((p & PAD_BUTTON_RIGHT))
res |= VBA_RIGHT;
if (p & PAD_TRIGGER_L)
res |= VBA_BUTTON_L;
if (p & PAD_TRIGGER_R)
res |= VBA_BUTTON_R;
if((p & PAD_BUTTON_X) && (p & PAD_BUTTON_Y))
menuCalled = 1;
#endif
if ((res & 48) == 48)
res &= ~16;
if ((res & 192) == 192)
res &= ~128;
return res;
}

11
src/ngc/gcpad.h Normal file
View File

@ -0,0 +1,11 @@
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
* Nintendo GameCube Joypad Wrapper
****************************************************************************/
#ifndef __NGCPADH__
#define __NGCPADH__
u32 NGCPad();
#endif

264
src/ngc/gx_supp.c Normal file
View File

@ -0,0 +1,264 @@
/****************************************************************************
* Generic GX Support for Emulators
* softdev 2007
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* NGC GX Video Functions
*
* These are pretty standard functions to setup and use GX scaling.
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
/*** External 2D Video ***/
extern u32 whichfb;
extern u32 *xfb[2];
extern GXRModeObj *vmode;
/*** 3D GX ***/
#define DEFAULT_FIFO_SIZE ( 256 * 1024 )
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
/*** Texture memory ***/
static u8 *texturemem;
static int texturesize;
GXTexObj texobj;
static Mtx view;
static int vwidth, vheight, oldvwidth, oldvheight;
#define HASPECT 80
#define VASPECT 60
/* New texture based scaler */
typedef struct tagcamera
{
Vector pos;
Vector up;
Vector view;
}
camera;
/*** Square Matrix
This structure controls the size of the image on the screen.
Think of the output as a -80 x 80 by -60 x 60 graph.
***/
static s16 square[] ATTRIBUTE_ALIGN(32) = {
/*
* X, Y, Z
* Values set are for roughly 4:3 aspect
*/
-HASPECT, VASPECT, 0, // 0
HASPECT, VASPECT, 0, // 1
HASPECT, -VASPECT, 0, // 2
-HASPECT, -VASPECT, 0, // 3
};
static camera cam = { {0.0F, 0.0F, 0.0F},
{0.0F, 0.5F, 0.0F},
{0.0F, 0.0F, -0.5F}
};
/****************************************************************************
* Scaler Support Functions
****************************************************************************/
static void draw_init(void)
{
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_INDEX8);
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetArray(GX_VA_POS, square, 3 * sizeof(s16));
GX_SetNumTexGens(1);
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GX_InvalidateTexAll();
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
GX_CLAMP, GX_CLAMP, GX_FALSE);
}
static void draw_vert(u8 pos, u8 c, f32 s, f32 t)
{
GX_Position1x8(pos);
GX_Color1x8(c);
GX_TexCoord2f32(s, t);
}
static void draw_square(Mtx v)
{
Mtx m; // model matrix.
Mtx mv; // modelview matrix.
guMtxIdentity(m);
guMtxTransApply(m, m, 0, 0, -100);
guMtxConcat(v, m, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
draw_vert(0, 0, 0.0, 0.0);
draw_vert(1, 0, 1.0, 0.0);
draw_vert(2, 0, 1.0, 1.0);
draw_vert(3, 0, 0.0, 1.0);
GX_End();
}
/****************************************************************************
* StartGX
****************************************************************************/
void GX_Start(int width, int height, int haspect, int vaspect)
{
Mtx p;
/*** Set new aspect ***/
square[0] = square[9] = -haspect;
square[3] = square[6] = haspect;
square[1] = square[4] = vaspect;
square[7] = square[10] = -vaspect;
/*** Allocate 32byte aligned texture memory ***/
texturesize = (width * height) * 2;
texturemem = (u8 *) memalign(32, texturesize);
GXColor gxbackground = { 0, 0, 0, 0xff };
/*** Clear out FIFO area ***/
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
/*** Initialise GX ***/
GX_Init(&gp_fifo, DEFAULT_FIFO_SIZE);
GX_SetCopyClear(gxbackground, 0x00ffffff);
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
GX_SetDispCopyYScale((f32) vmode->xfbHeight / (f32) vmode->efbHeight);
GX_SetScissor(0, 0, vmode->fbWidth, vmode->efbHeight);
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE,
vmode->vfilter);
GX_SetFieldMode(vmode->field_rendering,
((vmode->viHeight ==
2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
GX_SetCullMode(GX_CULL_NONE);
GX_CopyDisp(xfb[whichfb ^ 1], GX_TRUE);
GX_SetDispCopyGamma(GX_GM_1_0);
guPerspective(p, 60, 1.33F, 10.0F, 1000.0F);
GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
memset(texturemem, 0, texturesize);
/*** Setup for first call to scaler ***/
vwidth = vheight = -1;
}
/****************************************************************************
* GX_Render
*
* Pass in a buffer, width and height to update as a tiled RGB565 texture
****************************************************************************/
void GX_Render(int width, int height, u8 * buffer, int pitch)
{
int h, w;
long long int *dst = (long long int *) texturemem;
long long int *src1 = (long long int *) buffer;
long long int *src2 = (long long int *) (buffer + pitch);
long long int *src3 = (long long int *) (buffer + (pitch * 2));
long long int *src4 = (long long int *) (buffer + (pitch * 3));
int rowpitch = (pitch >> 3) * 3;
int rowadjust = ( pitch % 8 ) * 4;
char *ra = NULL;
vwidth = width;
vheight = height;
whichfb ^= 1;
if ((oldvheight != vheight) || (oldvwidth != vwidth))
{
/** Update scaling **/
oldvwidth = vwidth;
oldvheight = vheight;
draw_init();
memset(&view, 0, sizeof(Mtx));
guLookAt(view, &cam.pos, &cam.up, &cam.view);
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
}
GX_InvVtxCache();
GX_InvalidateTexAll();
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
for (h = 0; h < vheight; h += 4)
{
for (w = 0; w < (vwidth >> 2); w++)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
src1 += rowpitch;
src2 += rowpitch;
src3 += rowpitch;
src4 += rowpitch;
if ( rowadjust )
{
ra = (char *)src1;
src1 = (long long int *)(ra + rowadjust);
ra = (char *)src2;
src2 = (long long int *)(ra + rowadjust);
ra = (char *)src3;
src3 = (long long int *)(ra + rowadjust);
ra = (char *)src4;
src4 = (long long int *)(ra + rowadjust);
}
}
DCFlushRange(texturemem, texturesize);
GX_SetNumChans(1);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
draw_square(view);
GX_DrawDone();
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_Flush();
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
//VIDEO_WaitVSync();
}

29
src/ngc/gx_supp.h Normal file
View File

@ -0,0 +1,29 @@
/****************************************************************************
* Generic GX Scaler
* softdev 2007
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* NGC GX Video Functions
*
* These are pretty standard functions to setup and use GX scaling.
****************************************************************************/
#ifndef __GXHDR__
#define __GXHDR__
void GX_Start(int width, int height, int haspect, int vaspect);
void GX_Render(int width, int height, u8 * buffer, int pitch);
#endif

1
src/ngc/main.c Normal file
View File

@ -0,0 +1 @@

260
src/ngc/menu.cpp Normal file
View File

@ -0,0 +1,260 @@
/****************************************************************************
* File Selection Menu
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include "sdfileio.h"
extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
extern u32 *xfb[2]; /*** Framebuffers ***/
extern int whichfb; /*** Frame buffer toggle ***/
/** Bits from SD lib **/
#define PAGE_SIZE 14
/*** Use OGC built in font ***/
extern u8 console_font_8x16[];
static u32 forecolour = COLOR_WHITE;
static u32 backcolour = COLOR_BLACK;
/****************************************************************************
* MENU_DrawChar
****************************************************************************/
void MENU_DrawChar( int x, int y, char c, int style )
{
u8 bits;
int offset;
int h,w;
u32 colour[2];
u32 scroffs;
offset = c << 4;
scroffs = ( y * 320 ) + ( x >> 1 );
for( h = 0; h < 16; h++ )
{
bits = console_font_8x16[ offset++ ];
if ( style )
{
for( w = 0; w < 8; w++ )
{
xfb[whichfb][scroffs + w] = ( bits & 0x80 ) ? forecolour : backcolour;
bits <<= 1;
}
}
else
{
for( w = 0; w < 4; w++ )
{
colour[0] = ( bits & 0x80 ) ? forecolour : backcolour;
colour[1] = ( bits & 0x40 ) ? forecolour : backcolour;
xfb[whichfb][scroffs + w] = ( colour[0] & 0xFFFF00FF ) | ( colour[1] & 0x0000FF00 );
bits <<= 2;
}
}
scroffs += 320;
}
}
/****************************************************************************
* MENU_DrawString
****************************************************************************/
void MENU_DrawString( int x, int y, char *msg, int style )
{
int i,len;
/* Centred ? */
if ( x == -1 )
{
if ( style )
x = strlen(msg) << 4;
else
x = strlen(msg) << 3;
x = ( 640 - x ) >> 1;
}
if((int)strlen(msg) < 36)
len = (int)strlen(msg);
else
len = 36;
for ( i = 0; i < len; i++ )
{
MENU_DrawChar(x,y,msg[i],style);
x += ( style ? 16 : 8 );
}
}
/****************************************************************************
* MENU_Draw
****************************************************************************/
int MENU_Draw( int max, int current, int offset )
{
int i;
int ypos = 30;
int xpos = 30;
for ( i = offset; i < max && ( ( i - offset ) < PAGE_SIZE ); i++ )
{
if ( i == current )
{
forecolour = COLOR_BLACK;
backcolour = COLOR_WHITE;
}
else
{
forecolour = COLOR_WHITE;
backcolour = COLOR_BLACK;
}
MENU_DrawString( xpos, ypos, direntries[i], 1);
ypos += 16;
}
}
#ifdef WII_BUILD
#include <math.h>
#include <wiiuse/wpad.h>
extern int isClassicAvailable;
extern int isWiimoteAvailable;
extern void setup_controllers();
#endif
/****************************************************************************
* MENU_GetLoadFile
*
* Returns the filename of the selected file
***************************************************************************/
char *MENU_GetLoadFile( char *whichdir )
{
int count;
char *p = NULL;
int quit = 0;
int redraw = 1;
int current = 0;
int offset = 0;
u16 buttons;
int do_DOWN = 0;
int do_UP = 0;
int do_A = 0;
count = gen_getdir( whichdir );
if ( count == 0 )
{
printf("No ROM files in %s\n", whichdir);
while(1);
}
if ( count == 1 )
return (char*)direntries[0];
/* Do menu */
while ( !quit )
{
if ( redraw )
{
whichfb ^= 1;
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
MENU_Draw( count, current, offset );
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
redraw = 0;
}
#ifdef WII_BUILD
setup_controllers();
WPADData wpad;
WPAD_Read(0, &wpad);
if(isClassicAvailable)
{
int b = wpad.exp.classic.btns;
if (b & CLASSIC_CTRL_BUTTON_DOWN){
do_DOWN = 1;
do{WPAD_Read(0, &wpad); b = wpad.exp.classic.btns;}while(b & CLASSIC_CTRL_BUTTON_DOWN);
}
else if (b & CLASSIC_CTRL_BUTTON_UP){
do_UP = 1;
do{WPAD_Read(0, &wpad); b = wpad.exp.classic.btns;}while(b & CLASSIC_CTRL_BUTTON_UP);
}
else if (b & CLASSIC_CTRL_BUTTON_A){
do_A = 1;
do{WPAD_Read(0, &wpad); b = wpad.exp.classic.btns;}while(b & CLASSIC_CTRL_BUTTON_A);
}
}
if(isWiimoteAvailable)
{
unsigned short b = wpad.btns_d;
if(b & WPAD_BUTTON_LEFT){
do_DOWN = 1;
do{WPAD_Read(0, &wpad); b = wpad.btns_d;}while(b & WPAD_BUTTON_LEFT);
}
else if (b & WPAD_BUTTON_RIGHT){
do_UP = 1;
do{WPAD_Read(0, &wpad); b = wpad.btns_d;}while(b & WPAD_BUTTON_RIGHT);
}
else if (b & WPAD_BUTTON_2){
do_A = 1;
do{WPAD_Read(0, &wpad); b = wpad.btns_d;}while(b & WPAD_BUTTON_2);
}
}
#endif
buttons = PAD_ButtonsDown(0);
if(buttons & PAD_BUTTON_DOWN)
do_DOWN = 1;
else if(buttons & PAD_BUTTON_UP)
do_UP = 1;
else if(buttons & PAD_BUTTON_A)
do_A = 1;
if (do_DOWN)
{
do_DOWN=0;
current++;
if ( current == count )
current = 0;
if ( ( current % PAGE_SIZE ) == 0 )
offset = current;
redraw = 1;
}
else
{
if ( do_UP )
{
do_UP=0;
current--;
if ( current < 0 ) current = count - 1;
offset = ( current / PAGE_SIZE ) * PAGE_SIZE;
redraw = 1;
}
else
{
if ( do_A )
{
do_A=0;
quit = 1;
p = (char*)direntries[current];
}
}
}
}
whichfb ^= 1;
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
forecolour = COLOR_WHITE;
backcolour = COLOR_BLACK;
MENU_DrawString(-1, 240, "Loading ... Wait", 1);
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
return p;
}

73
src/ngc/mixer.cpp Normal file
View File

@ -0,0 +1,73 @@
/****************************************************************************
* VisualBoyAdvance
*
* Head and tail audio mixer
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** Locals **/
static int head = 0;
static int tail = 0;
#define MIXBUFFSIZE 0x10000
static u8 mixerdata[MIXBUFFSIZE];
#define MIXERMASK ((MIXBUFFSIZE >> 2) - 1)
/****************************************************************************
* MIXER_AddSamples
*
* Upsample from 11025 to 48000
* 11025 == 15052
* 22050 == 30106
* 44100 == 60211
*
* Audio officianados should look away now !
****************************************************************************/
void MIXER_AddSamples( u8 *sampledata, int len )
{
u32 *src = (u32 *)sampledata;
u32 *dst = (u32 *)mixerdata;
u32 intlen = (3200 >> 2);
u32 fixofs = 0;
u32 fixinc;
if ( !len )
fixinc = 30106;
else
fixinc = 60211;
do
{
/* Do simple linear interpolate */
dst[head++] = src[fixofs >> 16];
head &= MIXERMASK;
fixofs += fixinc;
}
while( --intlen );
}
/****************************************************************************
* MIXER_GetSamples
****************************************************************************/
int MIXER_GetSamples( u8 *dstbuffer, int maxlen )
{
u32 *src = (u32 *)mixerdata;
u32 *dst = (u32 *)dstbuffer;
u32 intlen = maxlen >> 2;
memset(dstbuffer, 0, maxlen);
while( ( head != tail ) && intlen )
{
*dst++ = src[tail++];
tail &= MIXERMASK;
intlen--;
}
return 3200;
}

13
src/ngc/mixer.h Normal file
View File

@ -0,0 +1,13 @@
/****************************************************************************
* VisualBoyAdvance
*
* Head and tail audio mixer
****************************************************************************/
#ifndef __AUDIOMIXER__
#define __AUDIOMIXER__
void MIXER_AddSamples( u8 *sampledata, int len );
int MIXER_GetSamples( u8 *dstbuffer, int maxlen );
#endif

85
src/ngc/pal60.h Normal file
View File

@ -0,0 +1,85 @@
u32 vpal60[] =
{
0x0e160001,
0x476901ad,
0x02ea5140,
0x00110028,
0x00100029,
0x410c410c,
0x40ed40ed,
0x002f8ee0,
0x00000000,
0x002f93e0,
0x00000000,
0x00e20262,
0x910701ae,
0x90010001,
0x00010001,
0x00010001,
0x00000000,
0x00000000,
0x28500100,
0x1ae771f0,
0x0db4a574,
0x00c1188e,
0xc4c0cbe2,
0xfcecdecf,
0x13130f08,
0x00080c0f,
0x00ff0000,
0x00000000,
0x02800000,
0x000000ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff,
0x00ff00ff
};
/****************************************************************************
* VIDEO60
*
* Differences between Wii/GC and libOGC 60Hz I modes
*
* CC002000 0f06 0e16
* CC00200C 0003 0011
* CC00200E 0018 0028
* CC002010 0002 0010
* CC002012 0019 0029
* CC00201C 0034 61A0 002F 8EE0
* CC002024 0034 66A0 002F 93E0
* CC00202C 00E4 001E 00E2 0262
* CC002030 1107 01AE 9107 01AE
* CC002034 1001 0001 9001 0001
****************************************************************************/

15
src/ngc/tbtime.c Normal file
View File

@ -0,0 +1,15 @@
#include "tbtime.h"
unsigned long
tb_diff_msec (tb_t * end, tb_t * start)
{
unsigned long upper, lower;
upper = end->u - start->u;
if (start->l > end->l)
upper--;
lower = end->l - start->l;
return ((upper * ((unsigned long) 0x80000000 / (TB_CLOCK / 2000))) +
(lower / (TB_CLOCK / 1000)));
}

27
src/ngc/tbtime.h Normal file
View File

@ -0,0 +1,27 @@
/****************************************************************************
* tmbinc msec timer
****************************************************************************/
#ifndef __TMBINCTIMER__
#define __TMBINCTIMER__
#ifdef WII_BUILD
#define TB_CLOCK 60750000 //WII
#endif
#ifdef GC_BUILD
#define TB_CLOCK 40500000
#endif
#define mftb(rval) ({unsigned long u; do { \
asm volatile ("mftbu %0" : "=r" (u)); \
asm volatile ("mftb %0" : "=r" ((rval)->l)); \
asm volatile ("mftbu %0" : "=r" ((rval)->u)); \
} while(u != ((rval)->u)); })
typedef struct
{
unsigned long l, u;
}
tb_t;
unsigned long tb_diff_msec (tb_t * end, tb_t * start);
#endif

790
src/ngc/vba172.cpp Normal file
View File

@ -0,0 +1,790 @@
/****************************************************************************
* VisualBoyAdvance 1.7.2
* Nintendo GameCube Wrapper
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <debug.h>
#ifdef WII_BUILD
extern "C"
{
#include <ogc/conf.h>
#include <math.h>
#include <wiiuse/wpad.h>
extern s32 CONF_Init(void);
}
extern int isClassicAvailable;
extern int isWiimoteAvailable;
void setup_controllers()
{
WPADData wpad;
WPAD_Read(0, &wpad);
// User will have to use a GC controller
if(wpad.err == WPAD_ERR_NO_CONTROLLER)
{
isClassicAvailable = 0;
isWiimoteAvailable = 0;
return;
}
// User can use just wiimote
if(wpad.err == WPAD_ERR_NONE && wpad.exp.type == WPAD_EXP_NONE)
{
isClassicAvailable = 0;
isWiimoteAvailable = 1;
return;
}
// User can use a Classic controller
if(wpad.err == WPAD_ERR_NONE && wpad.exp.type == WPAD_EXP_CLASSIC)
{
isClassicAvailable = 1;
WPAD_SetDataFormat(0, WPAD_FMT_CORE);
return;
}
}
#endif
#include "mixer.h"
#include "gcpad.h"
#include "vmmem.h"
#include "pal60.h"
extern "C"
{
#include "gx_supp.h"
#include "tbtime.h"
}
/** VBA **/
#include "GBA.h"
#include "agbprint.h"
#include "Flash.h"
#include "Port.h"
#include "RTC.h"
#include "Sound.h"
#include "Text.h"
#include "unzip.h"
#include "Util.h"
#include "gb/GB.h"
#include "gb/gbGlobals.h"
/**
* Globals
*/
int RGB_LOW_BITS_MASK=0x821;
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
u16 systemGbPalette[24];
int systemDebug = 0;
int emulating = 0;
int systemFrameSkip = 0;
int systemRedShift = 0;
int systemBlueShift = 0;
int systemGreenShift = 0;
int systemColorDepth = 0;
int sensorX = 2047;
int sensorY = 2047;
u16 systemColorMap16[0x10000];
//u32 systemColorMap32[0x10000];
u32 *systemColorMap32 = (u32 *)&systemColorMap16;
bool systemSoundOn = false;
int systemVerbose = 0;
int cartridgeType = 0;
int srcWidth = 0;
int srcHeight = 0;
int destWidth = 0;
int destHeight = 0;
int srcPitch = 0;
extern int menuCalled;
#define WITHGX 1
#define DEBUGON 0
#if DEBUGON
const char *dbg_local_ip = "192.168.1.32";
const char *dbg_netmask = "255.255.255.0";
const char *dbg_gw = "192.168.1.100";
#endif
/*** 2D Video Globals ***/
GXRModeObj *vmode; /*** Graphics Mode Object ***/
u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
int whichfb = 0; /*** Frame buffer toggle ***/
void debuggerOutput(char *, u32)
{}
void (*dbgOutput)(char *, u32) = debuggerOutput;
/**
* Locals
*/
extern "C"
{
void SDInit( void );
int gen_getdir( char *whichdir );
};
extern char *direntries[1000];
extern char *MENU_GetLoadFile( char *whichdir );
extern void MENU_DrawString( int x, int y, char *msg, int style );
struct EmulatedSystem emulator =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
false,
0
};
static tb_t start, now;
static u8 soundbuffer[3200] ATTRIBUTE_ALIGN(32);
u32 loadtimeradjust;
void doScan(u32 blah)
{
PAD_ScanPads();
}
/****************************************************************************
* Initialise Video
*
* Before doing anything in libogc, it's recommended to configure a video
* output.
****************************************************************************/
static void
Initialise (void)
{
VIDEO_Init (); /*** ALWAYS CALL FIRST IN ANY LIBOGC PROJECT!
Not only does it initialise the video
subsystem, but also sets up the ogc os
***/
#if DEBUGON
DEBUG_Init(2424);
_break();
#endif
PAD_Init (); /*** Initialise pads for input ***/
#ifdef WII_BUILD
CONF_Init();
WPAD_Init();
#endif
vmode = &TVNtsc480IntDf;
/*** Let libogc configure the mode ***/
VIDEO_Configure (vmode);
/*** Now configure the framebuffer.
Really a framebuffer is just a chunk of memory
to hold the display line by line.
***/
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
/*** I prefer also to have a second buffer for double-buffering.
This is not needed for the console demo.
***/
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
/*** Define a console ***/
console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight,
vmode->fbWidth * 2);
/*** Clear framebuffer to black ***/
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
/*** Set the framebuffer to be displayed at next VBlank ***/
VIDEO_SetNextFramebuffer (xfb[0]);
/*** Get the PAD status updated by libogc ***/
VIDEO_SetPreRetraceCallback (doScan);
VIDEO_SetBlack (0);
int i;
u32 *vreg = (u32 *)0xCC002000;
for ( i = 0; i < 64; i++ )
vreg[i] = vpal60[i];
/*** Update the video for next vblank ***/
VIDEO_Flush ();
VIDEO_WaitVSync (); /*** Wait for VBL ***/
if (vmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync ();
}
void systemMessage(int num, const char *msg, ...)
{
/*** For now ... do nothing ***/
}
void systemFrame()
{}
void systemScreenCapture(int a)
{}
void systemShowSpeed(int speed)
{}
static u32 autoFrameSkipLastTime = 0;
static int frameskipadjust = 0;
void system1Frame(int rate)
{
/* if ( cartridgeType == 1 )
return;
u32 time = systemGetClock();
u32 diff = time - autoFrameSkipLastTime;
int speed = 100;
if(diff)
speed = (1000000/rate)/diff;
char temp[512];
sprintf(temp,"Speed: %i",speed);
MENU_DrawString( -1, 450,temp , 1 );
if(speed >= 98)
{
frameskipadjust++;
if(frameskipadjust >= 3)
{
frameskipadjust=0;
if(systemFrameSkip > 0)
systemFrameSkip--;
}
}
else
{
if(speed < 80)
frameskipadjust -= (90 - speed)/5;
else if(systemFrameSkip < 9)
frameskipadjust--;
if(frameskipadjust <= -2)
{
frameskipadjust += 2;
if(systemFrameSkip < 9)
systemFrameSkip++;
}
}
autoFrameSkipLastTime = time;
*/
}
void system10Frames(int rate)
{
if ( cartridgeType == 1 )
return;
u32 time = systemGetClock();
u32 diff = time - autoFrameSkipLastTime;
int speed = 100;
if(diff)
speed = (1000000/rate)/diff;
/* char temp[512];
sprintf(temp,"Speed: %i",speed);
MENU_DrawString( -1, 450,temp , 1 );
*/
if(speed >= 98)
{
frameskipadjust++;
if(frameskipadjust >= 3)
{
frameskipadjust=0;
if(systemFrameSkip > 0)
systemFrameSkip--;
}
}
else
{
if(speed < 80)
frameskipadjust -= (90 - speed)/5;
else if(systemFrameSkip < 9)
frameskipadjust--;
if(frameskipadjust <= -2)
{
frameskipadjust += 2;
if(systemFrameSkip < 9)
systemFrameSkip++;
}
}
autoFrameSkipLastTime = time;
}
void systemUpdateMotionSensor()
{}
void systemGbBorderOn()
{}
void systemWriteDataToSoundBuffer()
{
MIXER_AddSamples((u8 *)soundFinalWave, (cartridgeType == 1));
}
void systemSoundPause()
{}
void systemSoundResume()
{}
void systemSoundReset()
{}
void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
{}
void systemSoundShutdown()
{}
static void AudioPlayer( void )
{
AUDIO_StopDMA();
MIXER_GetSamples(soundbuffer, 3200);
DCFlushRange(soundbuffer,3200);
AUDIO_InitDMA((u32)soundbuffer,3200);
AUDIO_StartDMA();
}
bool systemSoundInit()
{
AUDIO_Init(NULL);
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback(AudioPlayer);
memset(soundbuffer, 0, 3200);
//printf("Audio Inited\n");
return true;
}
static void AudioDeInit()
{
AUDIO_StopDMA();
}
bool systemPauseOnFrame()
{
return false;
}
int systemGetSensorX()
{
return sensorX;
}
int systemGetSensorY()
{
return sensorY;
}
bool systemCanChangeSoundQuality()
{
return true;
}
/****************************************************************************
* systemReadJoypads
****************************************************************************/
bool systemReadJoypads()
{
return true;
}
u32 systemReadJoypad(int which)
{
return NGCPad();
}
/****************************************************************************
* systemGetClock
*
* Returns number of milliseconds since program start
****************************************************************************/
u32 systemGetClock( void )
{
mftb(&now);
return tb_diff_msec(&now, &start) - loadtimeradjust;
}
/****************************************************************************
* systemDrawScreen
****************************************************************************/
void systemDrawScreen()
{
/** GB / GBC Have oodles of time - so sync on VSync **/
#if WITHGX
GX_Render( srcWidth, srcHeight, pix, srcPitch );
#endif
#ifdef WII_BUILD
VIDEO_WaitVSync ();
#endif
#ifdef GC_BUILD
if ( cartridgeType == 1 )
{
VIDEO_WaitVSync();
}
#endif
}
/****************************************************************************
* Showdir
****************************************************************************/
int ShowDir( char *whichdir )
{
int count;
int i;
count = gen_getdir( whichdir );
printf("Found %d files\n",count);
for ( i = 0; i < count; i++ )
printf("%s\n", direntries[i]);
while(1);
}
char filename[1024]; //rom file name
char batfilename[1024]; //battery save file name
/*
Asks user to select a ROM
*/
void chooseRom() {
//char *fname = "Sonic Advance 3.GBA";
char *fname = NULL;
memset(filename,0,1024);
memset(batfilename,0,1024);
fname = MENU_GetLoadFile( "/VBA/ROMS" );
sprintf(filename, "/VBA/ROMS/%s", fname);
// construct battery save file name
strcpy(batfilename, "/VBA/SAVES/");
strncat(batfilename,fname,strlen(fname)-4);
strcat(batfilename,".SAV");
}
void askSound() {
soundOffFlag = false;
soundLowPass = true;
}
/*
Checks to see if a previous SRAM/Flash save exists
If it does, it prompts the user to load it or not
*/
void checkSave() {
}
void GC_Sleep(u32 dwMiliseconds)
{
int nVBlanks = (dwMiliseconds / 16);
while (nVBlanks-- > 0)
{
VIDEO_WaitVSync();
}
}
void write_save()
{
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
MENU_DrawString( -1, 250,"Attempting to Save data ..." , 1 );
whichfb^=1;
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
if(emulator.emuWriteBattery(batfilename) == true)
MENU_DrawString( -1, 250,"Save OK!" , 1 );
else
MENU_DrawString( -1, 250,"Either no data to save yet or error!" , 1 );
VIDEO_WaitVSync ();
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
GC_Sleep(2000);
}
int ingameMenu() {
tb_t start,end;
mftb(&start);
char temp[512];
u16 buttons;
AudioDeInit();
whichfb^=1;
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
MENU_DrawString( 140, 50,"VisualBoyAdvance 1.7.2" , 1 );
#ifdef GC_BUILD
MENU_DrawString( 140, 80,"Nintendo Gamecube Port" , 1 );
MENU_DrawString( -1, 170,"(B) - Resume play" , 1 );
MENU_DrawString( -1, 200,"(L) - Write save" , 1 );
MENU_DrawString( -1, 230,"(R) - Reset game" , 1 );
MENU_DrawString( -1, 320,"(Z) - Return to loader" , 1 );
#endif
#ifdef WII_BUILD
MENU_DrawString( 140, 80,"Nintendo Wii Port" , 1 );
MENU_DrawString( -1, 170,"(B) or (Home) - Resume play" , 1 );
MENU_DrawString( -1, 200,"(L) or (+) - Write save" , 1 );
MENU_DrawString( -1, 230,"(R) or (-) - Reset game" , 1 );
MENU_DrawString( -1, 320,"(Z) or (A+B) - Return to loader" , 1 );
#endif
sprintf(temp,"Frameskip: Auto (Currently %i)",systemFrameSkip);
MENU_DrawString( -1, 450,temp , 1 );
VIDEO_WaitVSync ();
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
//wait for user to let go of menu calling button
do{buttons = PAD_ButtonsHeld(0);}while((buttons & PAD_BUTTON_A)||(buttons & PAD_BUTTON_B));
//wait for user to let go of home button
#ifdef WII_BUILD
WPADData wpad;
int btn;
if(isWiimoteAvailable)
do{WPAD_Read(0, &wpad); btn = wpad.btns_d;}while(btn & WPAD_BUTTON_HOME);
if(isClassicAvailable)
do{WPAD_Read(0, &wpad); btn = wpad.exp.classic.btns;}while(btn & CLASSIC_CTRL_BUTTON_HOME);
#endif
while(1){
#ifdef WII_BUILD
WPADData wpad;
WPAD_Read(0, &wpad);
if(isWiimoteAvailable)
{
unsigned short b = wpad.btns_d;
if(b & WPAD_BUTTON_MINUS){ //Reset game
emulator.emuReset();
break;
}
if(b & WPAD_BUTTON_PLUS) { //Write save
write_save();
break;
}
if((b & WPAD_BUTTON_A) && (b & WPAD_BUTTON_B)) { //Return to loader
void (*reload)() = (void(*)())0x80001800;
reload();
}
if(b & WPAD_BUTTON_HOME) { //Resume play
do{WPAD_Read(0, &wpad); b = wpad.btns_d;}while(b & WPAD_BUTTON_HOME); //wait for home
break;
}
}
if(isClassicAvailable)
{
int b = wpad.exp.classic.btns;
if(b & CLASSIC_CTRL_BUTTON_MINUS){ //Reset game
emulator.emuReset();
break;
}
if(b & CLASSIC_CTRL_BUTTON_PLUS) { //Write save
write_save();
break;
}
if((b & CLASSIC_CTRL_BUTTON_A) && (b & CLASSIC_CTRL_BUTTON_B)) { //Return to loader
void (*reload)() = (void(*)())0x80001800;
reload();
}
if(b & CLASSIC_CTRL_BUTTON_HOME) { //Resume play
do{WPAD_Read(0, &wpad);}while(wpad.exp.classic.btns & CLASSIC_CTRL_BUTTON_HOME); //wait for home button
break;
}
}
#endif
u16 buttons = PAD_ButtonsHeld(0); //grab pad buttons
if(buttons & PAD_TRIGGER_R){ //Reset game
emulator.emuReset();
break;
}
if(buttons & PAD_TRIGGER_L) { //Write save
write_save();
break;
}
if(buttons & PAD_TRIGGER_Z) { //Return to loader
void (*reload)() = (void(*)())0x80001800;
reload();
}
if(buttons & PAD_BUTTON_B) { //Resume play
break;
}
}
AudioPlayer();
mftb(&end);
loadtimeradjust += tb_diff_msec(&end, &start);
return 0;
}
/****************************************************************************
* main
*
* Program entry
****************************************************************************/
int main()
{
int i;
int vAspect = 0;
int hAspect = 0;
Initialise();
printf("\n\n\nVisualBoyAdvance 1.7.2\n");
printf("Nintendo Wii Port\n");
/** Kick off SD Lib **/
SDInit();
/** Build GBPalette **/
for( i = 0; i < 24; )
{
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
systemGbPalette[i++] = 0;
}
/** Set palette etc - Fixed to RGB565 **/
systemColorDepth = 16;
systemRedShift = 11;
systemGreenShift = 6;
systemBlueShift = 0;
for(i = 0; i < 0x10000; i++)
{
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
#ifdef WII_BUILD
setup_controllers();
#endif
//Main loop
while(1) {
cartridgeType = 0;
srcWidth = 0;
srcHeight = 0;
destWidth = 0;
destHeight = 0;
srcPitch = 0;
chooseRom();
//checkSave();
IMAGE_TYPE type = utilFindType(filename);
switch( type )
{
case IMAGE_GBA:
// printf("GameBoy Advance Image\n");
cartridgeType = 2;
emulator = GBASystem;
srcWidth = 240;
srcHeight = 160;
VMCPULoadROM(filename);
/* Actual Visual Aspect is 1.57 */
hAspect = 70;
vAspect = 46;
srcPitch = 484;
soundQuality = 2;
soundBufferLen = 1470;
cpuSaveType = 0;
break;
case IMAGE_GB:
// printf("GameBoy Image\n");
cartridgeType = 1;
emulator = GBSystem;
srcWidth = 160;
srcHeight = 144;
gbLoadRom(filename);
/* Actual physical aspect is 1.0 */
hAspect = 60;
vAspect = 46;
srcPitch = 324;
soundQuality = 1;
soundBufferLen = 1470 * 2;
break;
default:
// printf("Unknown Image\n");
while(1);
break;
}
/** Set defaults **/
flashSetSize(0x10000);
rtcEnable(true);
agbPrintEnable(false);
askSound();
#if WITHGX
/** Set GX **/
GX_Start( srcWidth, srcHeight, hAspect, vAspect );
#endif
if ( cartridgeType == 1 )
{
gbSoundReset();
gbSoundSetQuality(soundQuality);
}
else
{
soundSetQuality(soundQuality);
CPUInit("/VBA/BIOS/BIOS.GBA", 1);
CPUReset();
}
soundVolume = 0;
systemSoundOn = true;
soundInit();
AudioPlayer();
emulating = 1;
/** Start system clock **/
mftb(&start);
emulator.emuReadBattery(batfilename);
while ( emulating )
{
emulator.emuMain(emulator.emuCount);
if(menuCalled) {
if(ingameMenu())
break;
menuCalled = 0;
}
}
}
/** Never **/
while(1);
return 0;
}

595
src/ngc/vmmem.cpp Normal file
View File

@ -0,0 +1,595 @@
#ifdef WII_BUILD
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
* GameBoy Advance Virtual Memory Paging
****************************************************************************/
#include "sdfileio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <fat.h>
#include <sys/dir.h>
#include "GBA.h"
#include "Globals.h"
#include "Util.h"
#include "Port.h"
extern "C" {
#include "tbtime.h"
}
#define MEM_BAD 0xff
#define MEM_VM 0x01
#define MEM_UN 0x80
unsigned int MEM2Storage = 0x91000000;
static char *gbabase = NULL;
static FILE *romfile = NULL;
static u32 GBAROMSize = 0;
static char romfilename[1024];
/**
* GBA Memory
*/
#define WORKRAM 0x40000
#define BIOS 0x4000
#define INTERNALRAM 0x8000
#define PALETTERAM 0x400
#define VRAM 0x20000
#define OAM 0x400
#define PIX (4 * 241 * 162)
#define IOMEM 0x400
#define GBATOTAL (WORKRAM + BIOS + INTERNALRAM + PALETTERAM + \
VRAM + OAM + PIX + IOMEM )
extern void CPUUpdateRenderBuffers(bool force);
extern void MENU_DrawString( int x, int y, char *msg, int style );
/****************************************************************************
* VMAllocGBA
*
* Allocate the memory required for GBA.
****************************************************************************/
static void VMAllocGBA( void )
{
gbabase = (char *)memalign(32, GBATOTAL);
memset(gbabase, 0, GBATOTAL);
/* Assign to internal GBA variables */
workRAM = (u8 *)gbabase;
bios = (u8 *)(gbabase + WORKRAM);
internalRAM = (u8 *)(bios + BIOS);
paletteRAM = (u8 *)(internalRAM + INTERNALRAM);
vram = (u8 *)(paletteRAM + PALETTERAM);
oam = (u8 *)(vram + VRAM);
pix = (u8 *)(oam + OAM);
ioMem = (u8 *)(pix + PIX);
}
/****************************************************************************
* VMClose
****************************************************************************/
static void VMClose( void )
{
/* if ( rombase != NULL )
free(rombase);
*/
if ( gbabase != NULL )
free(gbabase);
if ( romfile != NULL )
gen_fclose(romfile);
gbabase = NULL;
romfile = NULL;
}
/****************************************************************************
* VMCPULoadROM
*
* MEM2 version of GBA CPULoadROM
****************************************************************************/
int VMCPULoadROM( char *filename )
{
int res=0;
char temp[512];
VMClose();
VMAllocGBA();
GBAROMSize = 0;
/*sprintf(temp,"Filename %s\n", filename);
MENU_DrawString( -1, 230,temp , 1 );
*/
romfile = gen_fopen(filename, "rb");
if ( romfile == NULL )
{
MENU_DrawString( -1, 400,"Error opening file!" , 1 );
while(1);
VMClose();
return 0;
}
fseek(romfile, 0, SEEK_END);
GBAROMSize = ftell(romfile);
fseek(romfile, 0, SEEK_SET);
sprintf(temp,"ROM Size %dMb (%dMBit)", GBAROMSize/1024/1024,(GBAROMSize*8)/1024/1024);
MENU_DrawString( -1, 150,temp , 1 );
rom = (u8 *)MEM2Storage;
/* Always use MEM2, regardless of ROM size */
res = gen_fread(rom, 1, GBAROMSize, romfile);
if ( (u32)res != GBAROMSize )
{
MENU_DrawString( -1, 400,"Error reading file!" , 1 );
while(1);
}
strcpy( romfilename, filename );
CPUUpdateRenderBuffers( true );
return 1;
}
/****************************************************************************
* VMRead32
*
* Return a 32bit value
****************************************************************************/
u32 VMRead32( u32 address )
{
u32 badaddress;
if ( address >= GBAROMSize )
{
badaddress = ( ( ( address >> 1 ) & 0xffff ) << 16 ) | ( ( ( address + 2 ) >> 1 ) & 0xffff );
return badaddress;
}
return READ32LE((rom + address));
}
/****************************************************************************
* VMRead16
*
* Return a 16bit value
****************************************************************************/
u16 VMRead16( u32 address )
{
if ( address >= GBAROMSize )
{
return ( address >> 1 ) & 0xffff;
}
return READ16LE((rom + address));
}
/****************************************************************************
* VMRead8
*
* Return 8bit value
****************************************************************************/
u8 VMRead8( u32 address )
{
if ( address >= GBAROMSize )
{
return ( address >> 1 ) & 0xff;
}
return (u8)rom[address];
}
#endif
#ifdef GC_BUILD
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
* GameBoy Advance Virtual Memory Paging
****************************************************************************/
#include "sdfileio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "GBA.h"
#include "Globals.h"
#include "Util.h"
#include "Port.h"
extern "C" {
#include "tbtime.h"
}
/** Globals **/
extern u32 loadtimeradjust;
#define MEM_BAD 0xff
#define MEM_VM 0x01
#define MEM_UN 0x80
/** Setup VM to use small 16kb windows **/
#define VMSHIFTBITS 14
#define VMSHIFTMASK 0x3FFF
#define MAXGBAROM ( 32 * 1024 * 1024 )
#define MAXROM (4 * 1024 * 1024)
#define MAXVMPAGE ( MAXGBAROM >> VMSHIFTBITS )
#define MAXVMMASK ( ( MAXROM >> VMSHIFTBITS ) - 1 )
typedef struct
{
char *pageptr;
int pagetype;
int pageno;
}
VMPAGE;
static VMPAGE vmpage[MAXVMPAGE];
static int vmpageno = 0;
static char *rombase = NULL;
static char *gbabase = NULL;
static FILE* romfile = NULL;
static int useVM = 0;
static u32 GBAROMSize = 0;
static char romfilename[1024];
/**
* GBA Memory
*/
#define WORKRAM 0x40000
#define BIOS 0x4000
#define INTERNALRAM 0x8000
#define PALETTERAM 0x400
#define VRAM 0x20000
#define OAM 0x400
#define PIX (4 * 241 * 162)
#define IOMEM 0x400
#define GBATOTAL (WORKRAM + BIOS + INTERNALRAM + PALETTERAM + \
VRAM + OAM + PIX + IOMEM )
extern void CPUUpdateRenderBuffers(bool force);
/****************************************************************************
* VMAllocGBA
*
* Allocate the memory required for GBA.
****************************************************************************/
static void VMAllocGBA( void )
{
gbabase = (char *)memalign(32, GBATOTAL);
memset(gbabase, 0, GBATOTAL);
/* Assign to internal GBA variables */
workRAM = (u8 *)gbabase;
bios = (u8 *)(gbabase + WORKRAM);
internalRAM = (u8 *)(bios + BIOS);
paletteRAM = (u8 *)(internalRAM + INTERNALRAM);
vram = (u8 *)(paletteRAM + PALETTERAM);
oam = (u8 *)(vram + VRAM);
pix = (u8 *)(oam + OAM);
ioMem = (u8 *)(pix + PIX);
}
/****************************************************************************
* VMFindFree
*
* Look for a free page in the VM block. If none found, do a round-robin
****************************************************************************/
static void VMFindFree( void )
{
int i;
vmpageno++;
vmpageno &= MAXVMMASK;
if ( vmpageno == 0 ) vmpageno++;
for ( i = 1; i < MAXVMPAGE; i++ )
{
/** Remove any other pointer to this vmpage **/
if ( vmpage[i].pageno == vmpageno )
{
vmpage[i].pageptr = NULL;
vmpage[i].pagetype = MEM_UN;
vmpage[i].pageno = -1;
break;
}
}
}
/****************************************************************************
* VMAllocate
*
* Allocate a VM page
****************************************************************************/
static void VMAllocate( int pageid )
{
VMFindFree();
vmpage[pageid].pageptr = rombase + ( vmpageno << VMSHIFTBITS );
vmpage[pageid].pagetype = MEM_VM;
vmpage[pageid].pageno = vmpageno;
}
/****************************************************************************
* VMInit
*
* Set everything to default
****************************************************************************/
static void VMInit( void )
{
int i;
/** Clear down pointers **/
memset(&vmpage, 0, sizeof(VMPAGE) * MAXVMPAGE);
for ( i = 0; i < MAXVMPAGE; i++ )
{
vmpage[i].pageno = -1;
vmpage[i].pagetype = MEM_UN;
}
/** Allocate physical **/
if ( rombase == NULL )
rombase = (char *)memalign(32, MAXROM);
vmpageno = 0;
rom = (u8 *)rombase;
}
/****************************************************************************
* VMClose
****************************************************************************/
static void VMClose( void )
{
if ( rombase != NULL )
free(rombase);
if ( gbabase != NULL )
free(gbabase);
if ( romfile != NULL )
gen_fclose(romfile);
rombase = gbabase = NULL;
romfile = NULL;
}
/****************************************************************************
* VMCPULoadROM
*
* VM version of GBA CPULoadROM
****************************************************************************/
int VMCPULoadROM( char *filename )
{
int res;
/** Fix VM **/
VMClose();
VMInit();
VMAllocGBA();
loadtimeradjust = useVM = GBAROMSize = 0;
printf("Filename %s\n", filename);
romfile = gen_fopen(filename, "rb");
if ( romfile == NULL )
{
printf("Error opening file!\n");
while(1);
VMClose();
return 0;
}
// printf("ROM Size %d\n", romfile->fsize);
/* Always use VM, regardless of ROM size */
res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile);
if ( res != (1 << VMSHIFTBITS ) )
{
printf("Error reading file! %i \n",res);
while(1);
}
fseek(romfile, 0, SEEK_END);
GBAROMSize = ftell(romfile);
fseek(romfile, 0, SEEK_SET);
vmpageno = 0;
vmpage[0].pageptr = rombase;
vmpage[0].pageno = 0;
vmpage[0].pagetype = MEM_VM;
useVM = 1;
strcpy( romfilename, filename );
CPUUpdateRenderBuffers( true );
return 1;
}
/****************************************************************************
* GBA Memory Read Routines
****************************************************************************/
/****************************************************************************
* VMNewPage
****************************************************************************/
static void VMNewPage( int pageid )
{
int res;
tb_t start,end;
mftb(&start);
res = gen_fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET );
if ( ! res )
{
printf("Seek error! - Offset %08x %d\n", pageid << VMSHIFTBITS, res);
while(1);
}
VMAllocate( pageid );
res = gen_fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile );
if ( res != ( 1 << VMSHIFTBITS ) )
{
printf("Error reading! %d bytes only\n", res);
while(1);
}
mftb(&end);
loadtimeradjust += tb_diff_msec(&end, &start);
#if 0
if ( pageid == 0x1FE )
{
vmpage[pageid].pageptr[0x209C] = 0xDF;
vmpage[pageid].pageptr[0x209D] = 0xFA;
vmpage[pageid].pageptr[0x209E] = 0x47;
vmpage[pageid].pageptr[0x209F] = 0x70;
}
printf("VMNP : %02x %04x %08x [%02x%02x%02x%02x] [%02x%02x%02x%02x]\n", vmpageno, pageid,
(u32)(vmpage[pageid].pageptr - rombase), vmpage[pageid].pageptr[0], vmpage[pageid].pageptr[1],
vmpage[pageid].pageptr[2], vmpage[pageid].pageptr[3],
vmpage[pageid].pageptr[0xfffc], vmpage[pageid].pageptr[0xfffd],
vmpage[pageid].pageptr[0xfffe], vmpage[pageid].pageptr[0xffff] );
#endif
}
/****************************************************************************
* VMRead32
*
* Return a 32bit value
****************************************************************************/
u32 VMRead32( u32 address )
{
int pageid;
u32 badaddress;
//printf("VM32 : Request %08x\n", address);
if ( address >= GBAROMSize )
{
badaddress = ( ( ( address >> 1 ) & 0xffff ) << 16 ) | ( ( ( address + 2 ) >> 1 ) & 0xffff );
return badaddress;
}
if ( !useVM )
return READ32LE((rom + address));
/** Use VM **/
pageid = address >> VMSHIFTBITS;
switch( vmpage[pageid].pagetype )
{
case MEM_UN:
VMNewPage(pageid);
case MEM_VM:
return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
default:
printf("VM32 : Unknown page type! (%d) [%d]\n", vmpage[pageid].pagetype, pageid);
while(1);
}
/* Can never get here ... but stops gcc bitchin' */
return 0;
}
/****************************************************************************
* VMRead16
*
* Return a 16bit value
****************************************************************************/
u16 VMRead16( u32 address )
{
int pageid;
//printf("VM16 : Request %08x\n", address);
if ( address >= GBAROMSize )
{
return ( address >> 1 ) & 0xffff;
}
if ( !useVM )
return READ16LE((rom + address));
pageid = address >> VMSHIFTBITS;
switch( vmpage[pageid].pagetype )
{
case MEM_UN:
VMNewPage(pageid);
case MEM_VM:
return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
default:
printf("VM16 : Unknown page type!\n");
while(1);
}
/* Can never get here ... but stops gcc bitchin' */
return 0;
}
/****************************************************************************
* VMRead8
*
* Return 8bit value
****************************************************************************/
u8 VMRead8( u32 address )
{
int pageid;
//printf("VM8 : Request %08x\n", address);
if ( address >= GBAROMSize )
{
return ( address >> 1 ) & 0xff;
}
if ( !useVM )
return (u8)rom[address];
pageid = address >> VMSHIFTBITS;
switch( vmpage[pageid].pagetype )
{
case MEM_UN:
VMNewPage(pageid);
case MEM_VM:
return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ];
default:
printf("VM8 : Unknown page type!\n");
while(1);
}
/* Can never get here ... but stops gcc bitchin' */
return 0;
}
#endif

15
src/ngc/vmmem.h Normal file
View File

@ -0,0 +1,15 @@
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
* GameBoy Advance Virtual Memory Paging
****************************************************************************/
#ifndef __VBAVMHDR__
#define __VBAVMHDR__
int VMCPULoadROM( char *filename );
u32 VMRead32( u32 address );
u16 VMRead16( u32 address );
u8 VMRead8( u32 address );
#endif

157
src/pixel.cpp Normal file
View File

@ -0,0 +1,157 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
extern int RGB_LOW_BITS_MASK;
void Pixelate(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
u32 colorMask = ~(RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 16));
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *xP = (u32 *) deltaPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
u32 currentDelta;
u32 nextDelta;
finish = (u8 *) bP + ((width+2) << 1);
nextPixel = *bP++;
nextDelta = *xP++;
do
{
currentPixel = nextPixel;
currentDelta = nextDelta;
nextPixel = *bP++;
nextDelta = *xP++;
if ((nextPixel != nextDelta) || (currentPixel != currentDelta))
{
u32 colorA, colorB, product;
*(xP - 2) = currentPixel;
#ifdef WORDS_BIGENDIAN
colorA = currentPixel >> 16;
colorB = currentPixel & 0xffff;
#else
colorA = currentPixel & 0xffff;
colorB = currentPixel >> 16;
#endif
product = (((colorA & colorMask) >> 1) & colorMask) >> 1;
#ifdef WORDS_BIGENDIAN
*(nL) = (product << 16) | (product);
*(dP) = (colorA << 16) | product;
#else
*(nL) = product | (product << 16);
*(dP) = colorA | (product << 16);
#endif
#ifdef WORDS_BIGENDIAN
colorA = nextPixel >> 16;
#else
colorA = nextPixel & 0xffff;
#endif
product = (((colorB & colorMask) >> 1) & colorMask) >> 1;
#ifdef WORDS_BIGENDIAN
*(nL + 1) = (product << 16) | (product);
*(dP + 1) = (colorB << 16) | (product);
#else
*(nL + 1) = (product) | (product << 16);
*(dP + 1) = (colorB) | (product << 16);
#endif
}
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
deltaPtr += srcPitch;
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}
void Pixelate32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
u32 colorMask = ~RGB_LOW_BITS_MASK;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
// u32 *xP = (u32 *) deltaPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
finish = (u8 *) bP + ((width+1) << 2);
nextPixel = *bP++;
do
{
currentPixel = nextPixel;
nextPixel = *bP++;
u32 colorA, colorB, product;
colorA = currentPixel;
colorB = nextPixel;
product = (((colorA & colorMask) >> 1) & colorMask) >> 1;
*(nL) = product;
*(nL+1) = product;
*(dP) = colorA;
*(dP+1) = product;
nextPixel = *bP++;
colorA = nextPixel;
product = (((colorB & colorMask) >> 1) & colorMask) >> 1;
*(nL + 2) = product;
*(nL + 3) = product;
*(dP + 2) = colorB;
*(dP + 3) = product;
dP += 4;
nL += 4;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}

242
src/scanline.cpp Normal file
View File

@ -0,0 +1,242 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
extern int RGB_LOW_BITS_MASK;
void Scanlines (u8 *srcPtr, u32 srcPitch, u8 *,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
finish = (u8 *) bP + ((width+2) << 1);
nextPixel = *bP++;
do
{
currentPixel = nextPixel;
nextPixel = *bP++;
u32 colorA, colorB;
#ifdef WORDS_BIGENDIAN
colorA = currentPixel >> 16;
colorB = currentPixel & 0xffff;
#else
colorA = currentPixel & 0xffff;
colorB = currentPixel >> 16;
#endif
*(dP) = colorA | colorA<<16;
*(nL) = 0;
#ifdef WORDS_BIGENDIAN
colorA = nextPixel >> 16;
#else
colorA = nextPixel & 0xffff;
#endif
*(dP + 1) = colorB | (colorB << 16);
*(nL + 1) = 0;
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}
void Scanlines32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
finish = (u8 *) bP + ((width+1) << 2);
nextPixel = *bP++;
do
{
currentPixel = nextPixel;
nextPixel = *bP++;
u32 colorA, colorB;
colorA = currentPixel;
colorB = nextPixel;
*(dP) = colorA;
*(dP+1) = colorA;
*(nL) = 0;
*(nL+1) = 0;
*(dP + 2) = colorB;
*(dP + 3) = colorB;
*(nL+2) = 0;
*(nL+3) = 0;
nextPixel = *bP++;
dP += 4;
nL += 4;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}
void ScanlinesTV(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
u32 colorMask = ~(RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 16));
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
finish = (u8 *) bP + ((width+2) << 1);
nextPixel = *bP++;
do
{
currentPixel = nextPixel;
nextPixel = *bP++;
u32 colorA, colorB;
#ifdef WORDS_BIGENDIAN
colorA = currentPixel >> 16;
colorB = currentPixel & 0xFFFF;
#else
colorA = currentPixel & 0xFFFF;
colorB = currentPixel >> 16;
#endif
*(dP) = colorA = colorA | ((((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1))) << 16;
colorA = ((colorA & colorMask) >> 1);
colorA += ((colorA & colorMask) >> 1);
*(nL) = colorA;
colorA = nextPixel & 0xFFFF;
*(dP + 1) = colorB = colorB | ((((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1))) << 16;
colorB = ((colorB & colorMask) >> 1);
colorB += ((colorB & colorMask) >> 1);
*(nL + 1) = colorB;
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}
void ScanlinesTV32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
u32 colorMask = ~RGB_LOW_BITS_MASK;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
u32 nextPixel;
finish = (u8 *) bP + ((width+1) << 2);
nextPixel = *bP++;
do
{
currentPixel = nextPixel;
nextPixel = *bP++;
u32 colorA, colorB, temp;
colorA = currentPixel;
colorB = nextPixel;
*(dP) = colorA;
*(dP+1) = temp = ((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1);
temp = ((temp & colorMask) >> 1);
temp += ((temp & colorMask) >> 1);
colorA = ((colorA & colorMask) >> 1);
colorA += ((colorA & colorMask) >> 1);
*(nL) = colorA;
*(nL+1) = temp;
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}

112
src/simple2x.cpp Normal file
View File

@ -0,0 +1,112 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "System.h"
void Simple2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
finish = (u8 *) bP + ((width+2) << 1);
currentPixel = *bP++;
do
{
#ifdef WORDS_BIGENDIAN
u32 color = currentPixel >> 16;
#else
u32 color = currentPixel & 0xffff;
#endif
color = color | (color << 16);
*(dP) = color;
*(nL) = color;
#ifdef WORDS_BIGENDIAN
color = currentPixel & 0xffff;
#else
color = currentPixel >> 16;
#endif
color = color| (color << 16);
*(dP + 1) = color;
*(nL + 1) = color;
currentPixel = *bP++;
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}
void Simple2x32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
u8 *dstPtr, u32 dstPitch, int width, int height)
{
u8 *nextLine, *finish;
nextLine = dstPtr + dstPitch;
do
{
u32 *bP = (u32 *) srcPtr;
u32 *dP = (u32 *) dstPtr;
u32 *nL = (u32 *) nextLine;
u32 currentPixel;
finish = (u8 *) bP + ((width+1) << 2);
currentPixel = *bP++;
do
{
u32 color = currentPixel;
*(dP) = color;
*(dP+1) = color;
*(nL) = color;
*(nL + 1) = color;
currentPixel = *bP++;
dP += 2;
nL += 2;
}
while ((u8 *) bP < finish);
srcPtr += srcPitch;
dstPtr += dstPitch << 1;
nextLine += dstPitch << 1;
}
while (--height);
}

2474
src/thumb.h Normal file

File diff suppressed because it is too large Load Diff

1277
src/unzip.cpp Normal file

File diff suppressed because it is too large Load Diff

302
src/unzip.h Normal file
View File

@ -0,0 +1,302 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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 2, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/* unzip.h -- IO for uncompress .zip files using zlib
Version 0.15 beta, Mar 19th, 1998,
Copyright (C) 1998 Gilles Vollant
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported.
Old compressions used by old PKZip 1.x are not supported
THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
CAN CHANGE IN FUTURE VERSION !!
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip */
#ifndef _unz_H
#define _unz_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__
{
int unused;
}
unzFile__;
typedef unzFile__ *unzFile;
#else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
}
tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info_s
{
uLong number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
}
unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
uLong compressed_size; /* compressed size 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
}
unz_file_info;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
"zlib/zlib111.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
*/
extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
unz_global_info *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of byte copied if somes bytes are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern z_off_t ZEXPORT unztell OF((unzFile file));
/*
Give the current position in uncompressed data
*/
extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf, or (if <0)
the error code
*/
#ifdef __cplusplus
}
#endif
#endif /* _unz_H */

220
src/zutil.h Normal file
View File

@ -0,0 +1,220 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id: zutil.h,v 1.2 2004/01/17 23:07:32 kxu Exp $ */
#ifndef _Z_UTIL_H
#define _Z_UTIL_H
#include <zlib.h>
#ifdef STDC
# include <stddef.h>
# include <string.h>
# include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
extern int errno;
#else
# include <errno.h>
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#ifdef MSDOS
# define OS_CODE 0x00
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
#endif
#ifdef OS2
# define OS_CODE 0x06
#endif
#ifdef WIN32 /* Window 95 & Windows NT */
# define OS_CODE 0x0b
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 0x02
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#ifdef AMIGA
# define OS_CODE 0x01
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 0x05
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define OS_CODE 0x0F
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER > 600))
# define fdopen(fd,type) _fdopen(fd,type)
#endif
/* Common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#ifdef HAVE_STRERROR
extern char *strerror OF((int));
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
#if defined(pyr)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
extern void zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
#ifdef DEBUG
# include <stdio.h>
extern int z_verbose;
extern void z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
uInt len));
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
void zcfree OF((voidpf opaque, voidpf ptr));
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
#endif /* _Z_UTIL_H */