mirror of
https://github.com/dborth/vbagx.git
synced 2024-11-25 12:06:53 +01:00
May 30, 2008 version by emu_kidid
This commit is contained in:
commit
64546f8550
183
Makefile
Normal file
183
Makefile
Normal 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
183
Makefile.gc
Normal 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
362
src/CheatSearch.cpp
Normal 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
75
src/CheatSearch.h
Normal 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
1836
src/Cheats.cpp
Normal file
File diff suppressed because it is too large
Load Diff
55
src/Cheats.h
Normal file
55
src/Cheats.h
Normal 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
214
src/EEprom.cpp
Normal 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
38
src/EEprom.h
Normal 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
288
src/Flash.cpp
Normal 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
33
src/Flash.h
Normal 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
4360
src/GBA.cpp
Normal file
File diff suppressed because it is too large
Load Diff
153
src/GBA.h
Normal file
153
src/GBA.h
Normal 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
556
src/GBAinline.h
Normal 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
47
src/Gfx.cpp
Normal 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;
|
135
src/Globals.cpp
Normal file
135
src/Globals.cpp
Normal 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
149
src/Globals.h
Normal 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
652
src/Mode0.cpp
Normal 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
599
src/Mode1.cpp
Normal 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
550
src/Mode2.cpp
Normal 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
463
src/Mode3.cpp
Normal 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
460
src/Mode4.cpp
Normal 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
463
src/Mode5.cpp
Normal 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
62
src/NLS.h
Normal 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
77
src/Port.h
Normal 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
245
src/RTC.cpp
Normal 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
31
src/RTC.h
Normal 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
1463
src/Sound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
82
src/Sound.h
Normal file
82
src/Sound.h
Normal 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
32
src/Sram.cpp
Normal 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
26
src/Sram.h
Normal 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
127
src/System.h
Normal 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
180
src/Text.cpp
Normal 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
21
src/Text.h
Normal 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
1196
src/Util.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
src/Util.h
Normal file
66
src/Util.h
Normal 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
1033
src/admame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
106
src/agbprint.cpp
Normal file
106
src/agbprint.cpp
Normal 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
27
src/agbprint.h
Normal 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
7472
src/arm-new.h
Normal file
File diff suppressed because it is too large
Load Diff
809
src/armdis.cpp
Normal file
809
src/armdis.cpp
Normal 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
33
src/armdis.h
Normal 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
432
src/bilinear.cpp
Normal 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
1293
src/bios.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
src/bios.h
Normal file
46
src/bios.h
Normal 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
3248
src/elf.cpp
Normal file
File diff suppressed because it is too large
Load Diff
311
src/elf.h
Normal file
311
src/elf.h
Normal 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
69
src/exprNode.h
Normal 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
110
src/fileio/sdfileio.c
Normal 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
33
src/fileio/sdfileio.h
Normal 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
3468
src/gb/GB.cpp
Normal file
File diff suppressed because it is too large
Load Diff
62
src/gb/GB.h
Normal file
62
src/gb/GB.h
Normal 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
498
src/gb/gbCheats.cpp
Normal 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
60
src/gb/gbCheats.h
Normal 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
1445
src/gb/gbCodes.h
Normal file
File diff suppressed because it is too large
Load Diff
1336
src/gb/gbCodesCB.h
Normal file
1336
src/gb/gbCodesCB.h
Normal file
File diff suppressed because it is too large
Load Diff
260
src/gb/gbDis.cpp
Normal file
260
src/gb/gbDis.cpp
Normal 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
563
src/gb/gbGfx.cpp
Normal 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
54
src/gb/gbGlobals.cpp
Normal 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
68
src/gb/gbGlobals.h
Normal 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
1074
src/gb/gbMemory.cpp
Normal file
File diff suppressed because it is too large
Load Diff
156
src/gb/gbMemory.h
Normal file
156
src/gb/gbMemory.h
Normal 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
249
src/gb/gbPrinter.cpp
Normal 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
20
src/gb/gbPrinter.h
Normal 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
1014
src/gb/gbSGB.cpp
Normal file
File diff suppressed because it is too large
Load Diff
39
src/gb/gbSGB.h
Normal file
39
src/gb/gbSGB.h
Normal 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
1065
src/gb/gbSound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
59
src/gb/gbSound.h
Normal file
59
src/gb/gbSound.h
Normal 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
1061
src/getopt.c
Normal file
File diff suppressed because it is too large
Load Diff
142
src/getopt.h
Normal file
142
src/getopt.h
Normal 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
191
src/getopt1.c
Normal 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
643
src/interframe.cpp
Normal 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
298
src/interp.h
Normal 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
750
src/memgzio.c
Normal 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
21
src/memgzio.h
Normal 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
289
src/ngc/gcpad.cpp
Normal 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
11
src/ngc/gcpad.h
Normal 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
264
src/ngc/gx_supp.c
Normal 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
29
src/ngc/gx_supp.h
Normal 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
1
src/ngc/main.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
260
src/ngc/menu.cpp
Normal file
260
src/ngc/menu.cpp
Normal 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
73
src/ngc/mixer.cpp
Normal 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
13
src/ngc/mixer.h
Normal 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
85
src/ngc/pal60.h
Normal 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
15
src/ngc/tbtime.c
Normal 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
27
src/ngc/tbtime.h
Normal 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
790
src/ngc/vba172.cpp
Normal 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
595
src/ngc/vmmem.cpp
Normal 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
15
src/ngc/vmmem.h
Normal 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
157
src/pixel.cpp
Normal 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
242
src/scanline.cpp
Normal 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
112
src/simple2x.cpp
Normal 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
2474
src/thumb.h
Normal file
File diff suppressed because it is too large
Load Diff
1277
src/unzip.cpp
Normal file
1277
src/unzip.cpp
Normal file
File diff suppressed because it is too large
Load Diff
302
src/unzip.h
Normal file
302
src/unzip.h
Normal 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
220
src/zutil.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user