Commit 9643226d authored by LLeny's avatar LLeny
Browse files

Initial commit

parents
ifeq ($(platform),osx)
fpic := -fPIC
TARGET := libretro.dylib
else ifeq ($(platform),win)
fpic :=
TARGET := libretro.dll
CC = gcc
CXX = g++
else
fpic := -fPIC
TARGET := libretro.so
endif
lynx = lynx
retro = libretro
handy_objs = Cart Memmap Mikie Ram Rom Susie System
retro_objs = libretro
libs = -lz
objects += $(handy_objs) $(retro_objs)
liblynx_objects := $(patsubst %,obj/%.o,$(objects))
includes = -I$(lynx)/ -I$(retro)/
c := $(CC) -std=gnu99
cpp := $(CXX) -std=gnu++0x
flags := -O3 -fomit-frame-pointer -fno-tree-vectorize -I. $(fpic) $(libs) $(includes)
compile = \
$(strip \
$(if $(filter %.c,$<), \
$(c) $(flags) $1 -c $< -o $@, \
$(if $(filter %.cpp,$<), \
$(cpp) $(flags) $1 -c $< -o $@ \
) \
) \
)
obj/Cart.o: $(lynx)/Cart.cpp
obj/Memmap.o: $(lynx)/Memmap.cpp
obj/Mikie.o: $(lynx)/Mikie.cpp
obj/Ram.o: $(lynx)/Ram.cpp
obj/Rom.o: $(lynx)/Rom.cpp
obj/Susie.o: $(lynx)/Susie.cpp
obj/System.o: $(lynx)/System.cpp
obj/libretro.o: $(retro)/libretro.cpp
%.o: $<; $(call compile)
$(TARGET): $(liblynx_objects)
ifeq ($(platform),x)
$(cpp) -o $@ -shared $(liblynx_objects) -Wl,--no-undefined -Wl,--version-script=link.T $(libs)
else ifeq ($(platform),win)
$(cpp) -o $@ -shared $(liblynx_objects) -Wl,--no-undefined -static-libgcc -static-libstdc++ -Wl,--version-script=link.T $(libs)
else
$(cpp) -o $@ -shared $(liblynx_objects) -Wl,--no-undefined $(libs)
endif
all: $(TARGET)
.PHONY: clean all
clean:
rm -f $(liblynx_objects) $(TARGET)
#include <stdlib.h>
#include <stdio.h>
#include "system.h"
#include "lynxdef.h"
#define HANDYVER "0.95"
#define ROM_FILE "lynxboot.img"
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifeq ($(TARGET_ARCH),arm)
LOCAL_CFLAGS += -DANDROID_ARM
LOCAL_ARM_MODE := arm
endif
ifeq ($(TARGET_ARCH),x86)
LOCAL_CFLAGS += -DANDROID_X86
endif
ifeq ($(TARGET_ARCH),mips)
LOCAL_CFLAGS += -DANDROID_MIPS
endif
LOCAL_MODULE := libretro
LOCAL_LDLIBS += -lz
LOCAL_SRC_FILES = ../../lynx/Cart.cpp ../../lynx/Memmap.cpp ../../lynx/Mikie.cpp ../../lynx/Ram.cpp ../../lynx/Rom.cpp ../../lynx/Susie.cpp ../../lynx/System.cpp ../../libretro/libretro.cpp
LOCAL_CXXFLAGS = -DANDROID -DARM -D__LIBRETRO__ -DHAVE_STRINGS_H -DHAVE_STDINT_H -DRIGHTSHIFT_IS_SAR
LOCAL_C_INCLUDES = ../../ ../../lynx/ ../../libretro/
include $(BUILD_SHARED_LIBRARY)
APP_STL := stlport_static
APP_ABI := all
#include "libretro.h"
#include "handy.h"
static retro_video_refresh_t video_cb;
static retro_audio_sample_t audio_cb;
static retro_audio_sample_batch_t audio_batch_cb;
static retro_environment_t environ_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
static CSystem *lynx = NULL;
static unsigned char *snd_buffer8;
static unsigned short soundBuffer[4096 * 8];
static uint16_t framebuffer[160*102*2];
static bool newFrame = false;
static bool initialized = false;
struct map { unsigned retro; unsigned lynx; };
static const map btn_map[] = {
{ RETRO_DEVICE_ID_JOYPAD_A, BUTTON_A },
{ RETRO_DEVICE_ID_JOYPAD_B, BUTTON_B },
{ RETRO_DEVICE_ID_JOYPAD_RIGHT, BUTTON_RIGHT },
{ RETRO_DEVICE_ID_JOYPAD_LEFT, BUTTON_LEFT },
{ RETRO_DEVICE_ID_JOYPAD_UP, BUTTON_UP },
{ RETRO_DEVICE_ID_JOYPAD_DOWN, BUTTON_DOWN },
{ RETRO_DEVICE_ID_JOYPAD_L, BUTTON_OPT1 },
{ RETRO_DEVICE_ID_JOYPAD_R, BUTTON_OPT2 },
};
void lynx_input();
void lynx_initialize_system(const char*);
void lynx_initialize_sound();
unsigned retro_api_version()
{
return RETRO_API_VERSION;
}
void retro_init(void)
{
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
{
fprintf(stderr, "[could not set RGB565]\n");
}
}
void retro_reset(void)
{
if(NULL != lynx)
{
lynx->Reset();
}
}
void retro_deinit(void)
{
retro_reset();
initialized = false;
if(NULL != lynx)
{
delete lynx;
}
}
void retro_set_environment(retro_environment_t cb)
{
environ_cb = cb;
}
void retro_set_audio_sample(retro_audio_sample_t cb)
{
audio_cb = cb;
}
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
{
audio_batch_cb = cb;
}
void retro_set_input_poll(retro_input_poll_t cb)
{
input_poll_cb = cb;
}
void retro_set_input_state(retro_input_state_t cb)
{
input_state_cb = cb;
}
void retro_set_video_refresh(retro_video_refresh_t cb)
{
video_cb = cb;
}
unsigned get_lynx_input()
{
unsigned res = 0;
for (unsigned i = 0; i < sizeof(btn_map) / sizeof(map); i++)
{
res |= input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, btn_map[i].retro) ? btn_map[i].lynx : 0;
}
return res;
}
void retro_set_controller_port_device(unsigned, unsigned)
{
}
void retro_get_system_info(struct retro_system_info *info)
{
memset(info, 0, sizeof(*info));
info->library_name = "handy";
info->library_version = HANDYVER;
info->need_fullpath = true;
info->valid_extensions = "lnx";
info->block_extract = 0;
}
void retro_get_system_av_info(struct retro_system_av_info *info)
{
struct retro_game_geometry geom = { 160, 102, 160, 102 };
struct retro_system_timing timing = { 75.0, 44100.0 };
info->geometry = geom;
info->timing = timing;
}
void retro_run(void)
{
lynx_input();
while(!newFrame)
{
lynx->Update();
}
newFrame = false;
}
size_t retro_serialize_size(void)
{
if(NULL == lynx)
{
return 0;
}
return lynx->MemoryContextSave(NULL);
}
bool retro_serialize(void *data, size_t size)
{
if(NULL == lynx)
{
return false;
}
return lynx->MemoryContextSave((char*)data) > 0;
}
bool retro_unserialize(const void *data, size_t size)
{
if(NULL == lynx)
{
return false;
}
return lynx->MemoryContextLoad((const char*)data, size);
}
bool retro_load_game(const struct retro_game_info *info)
{
lynx_initialize_system(info->path);
lynx_initialize_sound();
initialized = true;
return true;
}
bool retro_load_game_special(unsigned, const struct retro_game_info*, size_t)
{
return false;
}
void retro_unload_game(void)
{
}
void retro_cheat_reset(void)
{
}
void retro_cheat_set(unsigned index, bool enabled, const char *code)
{
}
unsigned retro_get_region()
{
return RETRO_REGION_NTSC;
}
void* retro_get_memory_data(unsigned type)
{
if(NULL != lynx)
{
return lynx->GetRamPointer();
}
}
size_t retro_get_memory_size(unsigned type)
{
return 1024*64;
}
void lynx_sound_stream_update(unsigned short *buffer, int buf_length)
{
uint16_t left;
for (int i = 0; i < buf_length; i++)
{
left = (snd_buffer8[i] << 8) - 32768;
*buffer = left;
++buffer;
*buffer = left;
++buffer;
*buffer = left;
++buffer;
*buffer = left;
++buffer;
}
gAudioBufferPointer = 0;
}
void lynx_input()
{
input_poll_cb();
lynx->SetButtonData(get_lynx_input());
}
UBYTE* lynx_display_callback(ULONG objref)
{
if(!initialized)
{
return (UBYTE*)framebuffer;
}
video_cb(framebuffer, 160, 102, 160*2);
if(gAudioBufferPointer > 0)
{
int f = gAudioBufferPointer;
lynx_sound_stream_update(soundBuffer, gAudioBufferPointer);
audio_batch_cb((const int16_t*)soundBuffer, f * 2);
}
newFrame = true;
return (UBYTE*)framebuffer;
}
std::string lynx_romfilename()
{
const char *dir = 0;
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir);
std::string str(dir);
str += ROM_FILE;
std::ifstream ifile(str.c_str(), std::ifstream::in);
if(!ifile)
{
fprintf(stderr, "[handy]rom not found %s\n", str.c_str());
}
return str;
}
void lynx_initialize_sound()
{
gAudioEnabled = true;
snd_buffer8 = (unsigned char *) (&gAudioBuffer);
}
void lynx_initialize_system(const char* gamepath)
{
if(lynx != NULL)
{
delete(lynx);
}
lynx = new CSystem(gamepath, lynx_romfilename().c_str());
lynx->DisplaySetAttributes(MIKIE_NO_ROTATE, MIKIE_PIXEL_FORMAT_16BPP_565, 320, lynx_display_callback, (ULONG)0);
}
This diff is collapsed.
//
// Copyright (c) 2004 K. Wilkins
//
// 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.
//
//////////////////////////////////////////////////////////////////////////////
// Handy - An Atari Lynx Emulator //
// Copyright (c) 1996,1997 //
// K. Wilkins //
//////////////////////////////////////////////////////////////////////////////
// Lynx Cartridge Class //
//////////////////////////////////////////////////////////////////////////////
// //
// This class emulates the Lynx cartridge interface, given a filename it //
// will contstruct a cartridge object via the constructor. //
// //
// K. Wilkins //
// August 1997 //
// //
//////////////////////////////////////////////////////////////////////////////
// Revision History: //
// ----------------- //
// //
// 01Aug1997 KW Document header added & class documented. //
// //
//////////////////////////////////////////////////////////////////////////////
#define CART_CPP
//#include <crtdbg.h>
//#define TRACE_CART
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "system.h"
#include "cart.h"
#include "zlib.h"
CCart::CCart(UBYTE *gamedata,ULONG gamesize)
{
TRACE_CART1("CCart() called with %s",gamefile);
LYNX_HEADER header;
mWriteEnableBank0=FALSE;
mWriteEnableBank1=FALSE;
mCartRAM=FALSE;
mHeaderLess=FALSE;
mCRC32=0;
mCRC32=crc32(mCRC32,gamedata,gamesize);
// Open up the file
if(gamesize)
{
// Checkout the header bytes
memcpy(&header,gamedata,sizeof(LYNX_HEADER));
#ifdef MSB_FIRST
header.page_size_bank0 = ((header.page_size_bank0>>8) | (header.page_size_bank0<<8));
header.page_size_bank1 = ((header.page_size_bank1>>8) | (header.page_size_bank1<<8));
header.version = ((header.version>>8) | (header.version<<8));
#endif
// Sanity checks on the header
if(header.magic[0]!='L' || header.magic[1]!='Y' || header.magic[2]!='N' || header.magic[3]!='X' || header.version!=1)
{
fprintf(stderr, "Invalid cart.\n");
}
// Setup name & manufacturer
strncpy(mName,(char*)&header.cartname,32);;
strncpy(mManufacturer,(char*)&header.manufname,16);
// Setup rotation
mRotation=header.rotation;
if(mRotation!=CART_NO_ROTATE && mRotation!=CART_ROTATE_LEFT && mRotation!=CART_ROTATE_RIGHT) mRotation=CART_NO_ROTATE;
}
else
{
header.page_size_bank0=0x000;
header.page_size_bank1=0x000;
// Setup name & manufacturer
strcpy(mName,"<No cart loaded>");
strcpy(mManufacturer,"<No cart loaded>");
// Setup rotation
mRotation=CART_NO_ROTATE;
}
// Set the filetypes
CTYPE banktype0,banktype1;
switch(header.page_size_bank0)
{
case 0x000:
banktype0=UNUSED;
mMaskBank0=0;
mShiftCount0=0;
mCountMask0=0;
break;
case 0x100:
banktype0=C64K;
mMaskBank0=0x00ffff;
mShiftCount0=8;
mCountMask0=0x0ff;
break;
case 0x200:
banktype0=C128K;
mMaskBank0=0x01ffff;
mShiftCount0=9;
mCountMask0=0x1ff;
break;
case 0x400:
banktype0=C256K;
mMaskBank0=0x03ffff;
mShiftCount0=10;
mCountMask0=0x3ff;
break;
case 0x800:
banktype0=C512K;
mMaskBank0=0x07ffff;
mShiftCount0=11;
mCountMask0=0x7ff;
break;
default:
fprintf(stderr, "Invalid cart.\n");
break;
}
TRACE_CART1("CCart() - Bank0 = $%06x",mMaskBank0);
switch(header.page_size_bank1)
{
case 0x000:
banktype1=UNUSED;
mMaskBank1=0;
mShiftCount1=0;
mCountMask1=0;
break;
case 0x100:
banktype1=C64K;
mMaskBank1=0x00ffff;
mShiftCount1=8;
mCountMask1=0x0ff;
break;
case 0x200:
banktype1=C128K;
mMaskBank1=0x01ffff;
mShiftCount1=9;
mCountMask1=0x1ff;
break;
case 0x400:
banktype1=C256K;
mMaskBank1=0x03ffff;
mShiftCount1=10;
mCountMask1=0x3ff;
break;
case 0x800:
banktype1=C512K;
mMaskBank1=0x07ffff;
mShiftCount1=11;
mCountMask1=0x7ff;
break;
default:
fprintf(stderr, "Invalid cart.\n");
break;
}
TRACE_CART1("CCart() - Bank1 = $%06x",mMaskBank1);
// Make some space for the new carts
mCartBank0 = (UBYTE*) new UBYTE[mMaskBank0+1];
mCartBank1 = (UBYTE*) new UBYTE[mMaskBank1+1];
// Set default bank
mBank=bank0;
// Initialiase
int cartsize = __max(0, int(gamesize - sizeof(LYNX_HEADER)));
int bank0size = __min(cartsize, (int)(mMaskBank0+1));
int bank1size = __min(cartsize, (int)(mMaskBank1+1));
memcpy(
mCartBank0,
gamedata+(sizeof(LYNX_HEADER)),
bank0size);
memset(
mCartBank0 + bank0size,
DEFAULT_CART_CONTENTS,
mMaskBank0+1 - bank0size);
memcpy(
mCartBank1,
gamedata+(sizeof(LYNX_HEADER)),
bank1size);
memset(
mCartBank1 + bank0size,
DEFAULT_CART_CONTENTS,