Bringing back the proprietary Z80 interpreter. Eighty one is still available but it can't run some games like Dizzy and some SG-1000 games

This commit is contained in:
gameblabla 2018-12-07 12:49:12 +01:00
parent aac90ffd91
commit 7a2b7ba3d9
No known key found for this signature in database
GPG Key ID: B24EFBB23B5F76CB
20 changed files with 7619 additions and 9 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ include/
source/nonfree/
sms_sdl
*.out
log.txt

View File

@ -9,14 +9,14 @@ LD = gcc
# add SDL dependencies
CFLAGS = -O2 -std=gnu99 -DINLINE=inline -DLSB_FIRST
CFLAGS += -I/usr/include/SDL -Isource -Isource/eighty -Isource/generic -I./source/sound -Isource/unzip -Isource/sdl -Isource/sound/crabemu_sn76489
CFLAGS = -O2 -pg -std=gnu99 -DINLINE=inline -DLSB_FIRST
CFLAGS += -I/usr/include/SDL -Isource -Isource/z80 -Isource/generic -I./source/sound -Isource/unzip -Isource/sdl -Isource/sound/crabemu_sn76489
CXXFLAGS = $(CFLAGS)
LDFLAGS = -lSDL -lm -flto -lz -lportaudio
# Files to be r
SRCDIR = ./source ./source/unzip ./source/eighty ./source/sound ./source/generic ./source/amini ./source/sound/crabemu_sn76489
SRCDIR = ./source ./source/unzip ./source/z80 ./source/sound ./source/generic ./source/k3s ./source/sound/crabemu_sn76489
VPATH = $(SRCDIR)
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))

View File

@ -12,7 +12,7 @@ LD = /opt/rs97-toolchain/bin/mipsel-linux-gcc
CFLAGS = -fno-pic -fno-pie -Ofast -msym32 -mlong-calls -mno-abicalls -fdata-sections -ffunction-sections -mips32 -mno-shared -mno-mips16
CFLAGS += -std=gnu99 -DLSB_FIRST -DMAXIM_PSG
CFLAGS += -Isource -Isource/eighty -Isource/generic -I./source/sound -Isource/unzip -Isource/rs97 -Isource/sound/maxim_sn76489 -Iinclude
CFLAGS += -Isource -Isource/z80 -Isource/generic -I./source/sound -Isource/unzip -Isource/rs97 -Isource/sound/maxim_sn76489 -Iinclude
CFLAGS += -funsafe-math-optimizations -fassociative-math -ffinite-math-only -fsingle-precision-constant -fsection-anchors -falign-functions=2 -mno-check-zero-division
#CFLAGS += -fprofile-generate -fprofile-dir=/mnt/int_sd/profile
CFLAGS += -fprofile-use
@ -21,7 +21,7 @@ CXXFLAGS = $(CFLAGS)
LDFLAGS = -lSDL -lm -flto -lz -Wl,--as-needed -Wl,--gc-sections -flto -s ./libportaudio.a
# Files to be r
SRCDIR = ./source ./source/unzip ./source/eighty ./source/sound ./source/generic ./source/amini ./source/sound/maxim_sn76489
SRCDIR = ./source ./source/unzip ./source/z80 ./source/sound ./source/generic ./source/amini ./source/sound/maxim_sn76489
VPATH = $(SRCDIR)
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))

42
Makefile.papk3s Normal file
View File

@ -0,0 +1,42 @@
PRGNAME = sms_sdl
# define regarding OS, which compiler to use
EXESUFFIX =
TOOLCHAIN =
CC = /opt/rs97-toolchain/bin/mipsel-linux-gcc
CCP = /opt/rs97-toolchain/bin/mipsel-linux-g++
LD = /opt/rs97-toolchain/bin/mipsel-linux-gcc
# add SDL dependencies
#-msym32 -mlong-calls
CFLAGS = -Ofast -fno-pic -fno-pie -mno-abicalls -fdata-sections -ffunction-sections -mips32 -mno-shared -mno-mips16
CFLAGS += -std=gnu99 -DLSB_FIRST -DMAXIM_PSG
CFLAGS += -Isource -Isource/z80 -Isource/generic -I./source/sound -Isource/unzip -Isource/rs97 -Isource/sound/maxim_sn76489 -Iinclude
CFLAGS += -fprofile-generate -fprofile-dir=/mnt/int_sd/profile -funsafe-math-optimizations -fassociative-math -ffinite-math-only -fsingle-precision-constant -fsection-anchors -falign-functions=2 -mno-check-zero-division
#CFLAGS += -fprofile-use -msym32 -mlong-calls -fno-math-errno -funsafe-math-optimizations -fassociative-math -ffinite-math-only -fsingle-precision-constant -fsection-anchors -falign-functions=2 -mno-check-zero-division
CXXFLAGS = $(CFLAGS)
LDFLAGS = -lSDL -lm -flto -lz -Wl,--as-needed -Wl,--gc-sections -flto -s ./libportaudio.a
# Files to be r
SRCDIR = ./source ./source/unzip ./source/z80 ./source/sound ./source/generic ./source/k3s ./source/sound/maxim_sn76489
VPATH = $(SRCDIR)
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))
OBJ_C = $(notdir $(patsubst %.c, %.o, $(SRC_C)))
OBJ_CP = $(notdir $(patsubst %.cpp, %.o, $(SRC_CP)))
OBJS = $(OBJ_C) $(OBJ_CP)
# Rules to make executable
$(PRGNAME)$(EXESUFFIX): $(OBJS)
$(LD) $(CFLAGS) -o $(PRGNAME)$(EXESUFFIX) $^ $(LDFLAGS)
$(OBJ_C) : %.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(OBJ_CP) : %.o : %.cpp
$(CCP) $(CXXFLAGS) -c -o $@ $<
clean:
rm -f $(PRGNAME)$(EXESUFFIX) *.o

View File

@ -12,7 +12,7 @@ LD = /opt/rs97-toolchain/bin/mipsel-linux-gcc
#-msym32 -mlong-calls
CFLAGS = -Ofast -fno-pic -fno-pie -mno-abicalls -fdata-sections -ffunction-sections -mips32 -mno-shared -mno-mips16
CFLAGS += -std=gnu99 -DLSB_FIRST -DMAXIM_PSG
CFLAGS += -Isource -Isource/eighty -Isource/generic -I./source/sound -Isource/unzip -Isource/rs97 -Isource/sound/maxim_sn76489 -Iinclude
CFLAGS += -Isource -Isource/z80 -Isource/generic -I./source/sound -Isource/unzip -Isource/rs97 -Isource/sound/maxim_sn76489 -Iinclude
#CFLAGS += -fprofile-generate -fprofile-dir=/mnt/int_sd/profile -funsafe-math-optimizations -fassociative-math -ffinite-math-only -fsingle-precision-constant -fsection-anchors -falign-functions=2 -mno-check-zero-division
CFLAGS += -fprofile-use -msym32 -mlong-calls -fno-math-errno -funsafe-math-optimizations -fassociative-math -ffinite-math-only -fsingle-precision-constant -fsection-anchors -falign-functions=2 -mno-check-zero-division
@ -20,7 +20,7 @@ CXXFLAGS = $(CFLAGS)
LDFLAGS = -lSDL -lm -flto -lz -Wl,--as-needed -Wl,--gc-sections -flto -s ./libportaudio.a
# Files to be r
SRCDIR = ./source ./source/unzip ./source/eighty ./source/sound ./source/generic ./source/rs97 ./source/sound/maxim_sn76489
SRCDIR = ./source ./source/unzip ./source/z80 ./source/sound ./source/generic ./source/rs97 ./source/sound/maxim_sn76489
VPATH = $(SRCDIR)
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))

BIN
background_papk3s.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -245,6 +245,51 @@ void upscale_SMS_to_320x240(uint32_t *dst, uint32_t *src, uint32_t height_scale)
}
}
void upscale_SMS_to_800x480(uint32_t *dst, uint32_t *src, uint32_t height_scale)
{
int midh = 480 >> 1;
int Eh = 0;
int source = 0, target = 0;
int dh = 0;
int i, j;
uint32_t a, b;
for (i = 0; i < 480; i++)
{
//Ew = 0;
source = dh * height_scale;
for (j = 0; j < 800/2; j++)
{
__builtin_prefetch(dst + 4, 1);
__builtin_prefetch(src + source + 4, 0);
a = src[source] & 0xF7DEF7DE;
#define AVERAGE(z, x) ((((z) & 0xF7DEF7DE) >> 1) + (((x) & 0xF7DEF7DE) >> 1))
if(Eh >= midh) { // average + 320
a = AVERAGE(a, src[source+160]);
}
#undef AVERAGE
b = a & 0xFFFF0000;
b |= (b >> 16);
a &= 0xFFFF;
a |= (a << 16);
*dst++ = a;
*dst++ = b;
source += 4;
}
Eh += height_scale; if(Eh >= 480) { Eh -= 480; dh++; } // 160 - real gba y size
}
}
/* Retro Arcade Mini scalers. Boo, ugly */
@ -297,6 +342,55 @@ void upscale_160x144_to_320x272_for_480x272(uint32_t *dst, uint32_t *src)
}
}
void upscale_160x144_to_320x272_for_800x480(uint32_t *dst, uint32_t *src)
{
int midh = 480 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int i, j;
dst += (800-320)/4; // center correction for 800x480 mode
for (i = 0; i < 480; i++)
{
source = dh * 256 / 2;
for (j = 0; j < 800/8; j++)
{
uint32_t a, b, c, d, ab, cd;
__builtin_prefetch(dst + 4, 1);
__builtin_prefetch(src + source + 4, 0);
ab = src[source] & 0xF7DEF7DE;
cd = src[source + 1] & 0xF7DEF7DE;
/*if(Eh >= midh) {
ab = AVERAGE(ab, src[source+256/2]);
cd = AVERAGE(cd, src[source+256/2+1]);
}*/
a = (ab & 0xFFFF) | (ab << 16);
b = (ab & 0xFFFF0000) | (ab >> 16);
c = (cd & 0xFFFF) | (cd << 16);
d = (cd & 0xFFFF0000) | (cd >> 16);
*dst++ = a;
*dst++ = b;
*dst++ = c;
*dst++ = d;
source += 2;
}
dst += (800-320)/2; // pitch correction for 800x480 mode
Eh += 144; if(Eh >= 480) { Eh -= 480; dh++; }
}
}
void upscale_160x144_to_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
@ -345,6 +439,55 @@ void upscale_160x144_to_480x272(uint32_t *dst, uint32_t *src)
}
}
void upscale_160x144_to_800x480(uint32_t *dst, uint32_t *src)
{
int midh = 480 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int i, j;
for (i = 0; i < 480; i++)
{
source = dh * 256 / 2;
for (j = 0; j < 800/12; j++)
{
uint32_t a, b, c, d, e, f, ab, cd;
__builtin_prefetch(dst + 4, 1);
__builtin_prefetch(src + source + 4, 0);
ab = src[source] & 0xF7DEF7DE;
cd = src[source + 1] & 0xF7DEF7DE;
/*if(Eh >= midh) {
ab = AVERAGE(ab, src[source+256/2]);
cd = AVERAGE(cd, src[source+256/2+1]);
}*/
a = (ab & 0xFFFF) | (ab << 16);
b = ab;
c = (ab & 0xFFFF0000) | (ab >> 16);
d = (cd & 0xFFFF) | (cd << 16);
e = cd;
f = (cd & 0xFFFF0000) | (cd >> 16);
*dst++ = a;
*dst++ = b;
*dst++ = c;
*dst++ = d;
*dst++ = e;
*dst++ = f;
source += 2;
}
Eh += 144; if(Eh >= 272) { Eh -= 272; dh++; }
}
}
void upscale_256x192_to_384x272_for_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
@ -386,6 +529,48 @@ void upscale_256x192_to_384x272_for_480x272(uint32_t *dst, uint32_t *src)
}
}
void upscale_256x192_to_384x272_for_800x480(uint32_t *dst, uint32_t *src)
{
int midh = 480 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int y, x;
dst += (800 - 384) / 4;
for (y = 0; y < 480; y++)
{
source = dh * 256 / 2;
for (x = 0; x < 384/6; x++)
{
register uint32_t ab, cd;
__builtin_prefetch(dst + 4, 1);
__builtin_prefetch(src + source + 4, 0);
ab = src[source] & 0xF7DEF7DE;
cd = src[source + 1] & 0xF7DEF7DE;
/*if(Eh >= midh) {
ab = AVERAGE(ab, src[source + 256/2]) & 0xF7DEF7DE; // to prevent overflow
cd = AVERAGE(cd, src[source + 256/2 + 1]) & 0xF7DEF7DE; // to prevent overflow
}*/
*dst++ = (ab & 0xFFFF) + AVERAGEHI(ab);
*dst++ = (ab >> 16) + ((cd & 0xFFFF) << 16);
*dst++ = (cd & 0xFFFF0000) + AVERAGELO(cd);
source += 2;
}
dst += (800 - 384) / 2;
Eh += 192; if(Eh >= 480) { Eh -= 480; dh++; }
}
}
void upscale_256x192_to_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
@ -446,3 +631,49 @@ void upscale_256x192_to_480x272(uint32_t *dst, uint32_t *src)
Eh += 192; if(Eh >= 272) { Eh -= 272; dh++; }
}
}
/*
void upscale_256x192_to_800x480(uint32_t *dst, uint32_t *src, uint32_t height_scale)
{
int midh = 480 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int y, x;
for (y = 0; y < 480; y++)
{
source = dh * 256 / 2;
for (x = 0; x < 800/12; x++)
{
register uint32_t ab, cd, ef, gh;
__builtin_prefetch(dst + 4, 1);
__builtin_prefetch(src + source + 4, 0);
ab = src[source] & 0xF7DEF7DE;
cd = src[source + 1] & 0xF7DEF7DE;
ef = src[source + 2] & 0xF7DEF7DE;
gh = src[source + 3] & 0xF7DEF7DE;
if(Eh >= midh) {
ab = AVERAGE(ab, src[source + 256/2]) & 0xF7DEF7DE; // to prevent overflow
cd = AVERAGE(cd, src[source + 256/2 + 1]) & 0xF7DEF7DE; // to prevent overflow
ef = AVERAGE(ef, src[source + 256/2 + 2]) & 0xF7DEF7DE; // to prevent overflow
gh = AVERAGE(gh, src[source + 256/2 + 3]) & 0xF7DEF7DE; // to prevent overflow
}
*dst++ = ab;
*dst++ = ((ab >> 17) + ((cd & 0xFFFF) >> 1)) + (cd << 16);
*dst++ = (cd >> 16) + (ef << 16);
*dst++ = (ef >> 16) + (((ef & 0xFFFF0000) >> 1) + ((gh & 0xFFFF) << 15));
*dst++ = gh;
source += 4;
}
Eh += height_scale; if(Eh >= 480) { Eh -= 480; dh++; }
}
}
*/

View File

@ -9,8 +9,15 @@ void upscale_160x144_to_320x480(uint32_t *dst, uint32_t *src);
void upscale_SMS_to_320x240(uint32_t *dst, uint32_t *src, uint32_t height_scale);
void upscale_SMS_to_320x480(uint32_t *dst, uint32_t *src, uint32_t height_scale);
void upscale_SMS_to_800x480(uint32_t *dst, uint32_t *src, uint32_t height_scale);
void upscale_160x144_to_800x480(uint32_t *dst, uint32_t *src);
//void upscale_256x192_to_800x480(uint32_t *dst, uint32_t *src, uint32_t height_scale);
void upscale_160x144_to_320x272_for_800x480(uint32_t *dst, uint32_t *src);
void bitmap_scale(uint32_t startx, uint32_t starty, uint32_t viswidth, uint32_t visheight, uint32_t newwidth, uint32_t newheight,uint32_t pitchsrc,uint32_t pitchdest, uint16_t *src, uint16_t *dst);
#endif

872
source/k3s/smsplus.c Normal file
View File

@ -0,0 +1,872 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libgen.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <SDL/SDL.h>
#include "shared.h"
#include "scaler.h"
#include "smsplus.h"
#include "text_gui.h"
#include "bigfontwhite.h"
#include "bigfontred.h"
#include "font.h"
#include <portaudio.h>
static t_sdl_sound sdl_sound;
static t_sdl_sync sdl_sync;
uint32_t frames_rendered = 0;
gamedata_t gdata;
t_config option;
SDL_Surface* sdl_screen, *sms_bitmap;
static SDL_Surface* img_background;
uint32_t countedFrames = 0;
uint32_t start;
static SDL_Joystick* joystick[2];
extern SDL_Surface *font;
extern SDL_Surface *bigfontred;
extern SDL_Surface *bigfontwhite;
int8_t fullscreen = 1;
uint8_t selectpressed = 0;
uint8_t save_slot = 0;
uint8_t showfps = 0;
uint8_t quit = 0;
#define SOUND_FREQUENCY 48000
#define SOUND_SAMPLES_SIZE 2048
static int16_t buffer_snd[SOUND_FREQUENCY * 2];
/* Sound */
PaStream *apu_stream;
static uint32_t Sound_Init()
{
int32_t err;
err = Pa_Initialize();
PaStreamParameters outputParameters;
outputParameters.device = Pa_GetDefaultOutputDevice();
if (outputParameters.device == paNoDevice) {
return EXIT_FAILURE;
}
outputParameters.channelCount = 2;
outputParameters.sampleFormat = paInt16;
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &apu_stream, NULL, &outputParameters, SOUND_FREQUENCY, SOUND_SAMPLES_SIZE, paNoFlag, NULL, NULL);
err = Pa_StartStream( apu_stream );
option.sndrate = SOUND_FREQUENCY;
return 1;
}
static void Sound_Update()
{
uint32_t i;
const float volumeMultiplier = 6.0f;
for (i = 0; i < (4 * (SOUND_FREQUENCY / snd.fps)); i++)
{
buffer_snd[i * 2] = snd.output[1][i] * volumeMultiplier;
buffer_snd[i * 2 + 1] = snd.output[0][i] * volumeMultiplier;
}
Pa_WriteStream( apu_stream, buffer_snd, SOUND_FREQUENCY / snd.fps );
}
static void Sound_Close()
{
int32_t err;
err = Pa_CloseStream( apu_stream );
err = Pa_Terminate();
}
static void video_update()
{
SDL_Rect dst, dstT;
SDL_LockSurface(sdl_screen);
switch(fullscreen)
{
case 3: // FullScreen (No cropping)
if (sms.console == CONSOLE_GG)
{
dst.x = 0;
dst.y = 0;
dst.w = sdl_screen->w;
dst.h = sdl_screen->h;
dstT.x = 0;
dstT.y = 0;
dstT.w = 160;
dstT.h = 144;
}
else
{
dst.x = 0;
dst.y = 0;
dst.w = sdl_screen->w;
dst.h = sdl_screen->h;
dstT.x = 0;
dstT.y = 0;
dstT.w = VIDEO_WIDTH_SMS-dstT.x;
dstT.h = vdp.height;
}
break;
case 2: // Fullscreen (cropped)
if (sms.console == CONSOLE_GG)
{
dst.x = 0;
dst.y = 0;
dst.w = sdl_screen->w;
dst.h = sdl_screen->h;
dstT.x = 0;
dstT.y = 0;
dstT.w = 160;
dstT.h = 144;
}
else
{
dst.x = 0;
dst.y = 0;
dst.w = sdl_screen->w;
dst.h = sdl_screen->h;
if ((bitmap.data[0] == bitmap.data[4]))
{
dstT.x = 8;
}
else
{
dstT.x = 0;
}
dstT.y = 0;
dstT.w = VIDEO_WIDTH_SMS-dstT.x;
dstT.h = vdp.height;
}
break;
case 1: // Stretch (keep aspect ratio)
if (sms.console == CONSOLE_GG)
{
dst.x = 80;
dst.y = 0;
dst.w = 320;
dst.h = 144*2;
dstT.x = 0;
dstT.y = 0;
dstT.w = 160;
dstT.h = 144;
}
else
{
dst.x = 80;
dst.y = 0;
dst.w = 640;
dst.h = sdl_screen->h;
dstT.x = 0;
dstT.y = 0;
dstT.w = VIDEO_WIDTH_SMS;
dstT.h = vdp.height;
}
break;
case 0: // native res
if (sms.console == CONSOLE_GG)
{
dst.x = 0;
dst.y = 0;
dst.w = 160*3;
dst.h = 144*3;
dstT.x = 0;
dstT.y = 0;
dstT.w = 160;
dstT.h = 144;
}
else
{
dst.x = 148;
dst.y = (480-(vdp.height*2))/2;
dst.w = 512;
dst.h = vdp.height*2;
dstT.x = 0;
dstT.y = 0;
dstT.w = VIDEO_WIDTH_SMS;
dstT.h = vdp.height;
}
break;
}
SDL_SoftStretch(sms_bitmap, &dstT, sdl_screen, &dst);
SDL_UnlockSurface(sdl_screen);
}
void smsp_state(uint8_t slot, uint8_t mode)
{
// Save and Load States
int8_t stpath[PATH_MAX];
snprintf(stpath, sizeof(stpath), "%s%s.st%d", gdata.stdir, gdata.gamename, slot);
printf("Path state %s\n", stpath);
FILE *fd;
switch(mode) {
case 0:
fd = fopen(stpath, "wb");
if (fd) {
system_save_state(fd);
fclose(fd);
}
break;
case 1:
fd = fopen(stpath, "rb");
if (fd) {
system_load_state(fd);
fclose(fd);
}
break;
}
}
void system_manage_sram(uint8_t *sram, uint8_t slot, uint8_t mode)
{
// Set up save file name
FILE *fd;
switch(mode)
{
case SRAM_SAVE:
if(sms.save)
{
fd = fopen(gdata.sramfile, "wb");
if (fd)
{
fwrite(sram, 0x8000, 1, fd);
fclose(fd);
}
}
break;
case SRAM_LOAD:
fd = fopen(gdata.sramfile, "rb");
if (fd)
{
sms.save = 1;
fread(sram, 0x8000, 1, fd);
fclose(fd);
}
else
memset(sram, 0x00, 0x8000);
break;
}
}
static int sdl_controls_update_input(SDLKey k, int32_t p)
{
if (sms.console == CONSOLE_COLECO)
{
input.system = 0;
coleco.keypad[0] = 0xff;
coleco.keypad[1] = 0xff;
}
switch(k)
{
case SDLK_ESCAPE:
if(p)
selectpressed = 1;
break;
case SDLK_RETURN:
if(p)
input.system |= (sms.console == CONSOLE_GG) ? INPUT_START : INPUT_PAUSE;
break;
case SDLK_UP:
if(p)
input.pad[0] |= INPUT_UP;
break;
case SDLK_DOWN:
if(p)
input.pad[0] |= INPUT_DOWN;
break;
case SDLK_LEFT:
if(p)
input.pad[0] |= INPUT_LEFT;
break;
case SDLK_RIGHT:
if(p)
input.pad[0] |= INPUT_RIGHT;
break;
case SDLK_LCTRL:
if(p)
input.pad[0] |= INPUT_BUTTON1;
break;
case SDLK_LALT:
if(p)
input.pad[0] |= INPUT_BUTTON2;
break;
}
return 1;
}
static void bios_init()
{
FILE *fd;
int8_t bios_path[256];
bios.rom = malloc(0x100000);
bios.enabled = 0;
snprintf(bios_path, sizeof(bios_path), "%s%s", gdata.biosdir, "BIOS.sms");
fd = fopen("bios.sms", "rb");
if(fd)
{
/* Seek to end of file, and get size */
fseek(fd, 0, SEEK_END);
uint32_t size = ftell(fd);
fseek(fd, 0, SEEK_SET);
if (size < 0x4000) size = 0x4000;
fread(bios.rom, size, 1, fd);
bios.enabled = 2;
bios.pages = size / 0x4000;
fclose(fd);
}
snprintf(bios_path, sizeof(bios_path), "%s%s", gdata.biosdir, "BIOS.col");
fd = fopen("bios.col", "rb");
if(fd)
{
/* Seek to end of file, and get size */
fread(coleco.rom, 0x2000, 1, fd);
fclose(fd);
}
}
static void smsp_gamedata_set(int8_t *filename)
{
// Set paths, create directories
int8_t home_path[256];
snprintf(home_path, sizeof(home_path), "%s/.smsplus/", getenv("HOME"));
if (mkdir(home_path, 0755) && errno != EEXIST) {
fprintf(stderr, "Failed to create %s: %d\n", home_path, errno);
}
// Set the game name
snprintf(gdata.gamename, sizeof(gdata.gamename), "%s", basename(filename));
// Strip the file extension off
for (int i = strlen(gdata.gamename) - 1; i > 0; i--) {
if (gdata.gamename[i] == '.') {
gdata.gamename[i] = '\0';
break;
}
}
// Set up the sram directory
snprintf(gdata.sramdir, sizeof(gdata.sramdir), "%ssram/", home_path);
if (mkdir(gdata.sramdir, 0755) && errno != EEXIST) {
fprintf(stderr, "Failed to create %s: %d\n", gdata.sramdir, errno);
}
// Set up the sram file
snprintf(gdata.sramfile, sizeof(gdata.sramfile), "%s%s%s.sav", home_path, gdata.sramdir, gdata.gamename);
// Set up the state directory
snprintf(gdata.stdir, sizeof(gdata.stdir), "%sstate/", home_path);
if (mkdir(gdata.stdir, 0755) && errno != EEXIST) {
fprintf(stderr, "Failed to create %s: %d\n", gdata.stdir, errno);
}
// Set up the screenshot directory
snprintf(gdata.scrdir, sizeof(gdata.scrdir), "%sscreenshots/", home_path);
if (mkdir(gdata.scrdir, 0755) && errno != EEXIST) {
fprintf(stderr, "Failed to create %s: %d\n", gdata.scrdir, errno);
}
// Set up the sram directory
snprintf(gdata.biosdir, sizeof(gdata.biosdir), "%sbios/", home_path);
if (mkdir(gdata.biosdir, 0755) && errno != EEXIST) {
fprintf(stderr, "Failed to create %s: %d\n", gdata.sramdir, errno);
}
}
void Menu()
{
int16_t pressed = 0;
int16_t currentselection = 1;
uint16_t miniscreenwidth = 140;
uint16_t miniscreenheight = 135;
SDL_Rect dstRect;
int8_t *cmd = NULL;
SDL_Event Event;
/* Seriously, we need that mess due to crappy framebuffer drivers on the RS-07... */
SDL_Surface* miniscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, miniscreenwidth, miniscreenheight, 16, sdl_screen->format->Rmask, sdl_screen->format->Gmask, sdl_screen->format->Bmask, sdl_screen->format->Amask);
SDL_Surface* black_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, sdl_screen->w, sdl_screen->h, 16, sdl_screen->format->Rmask, sdl_screen->format->Gmask, sdl_screen->format->Bmask, sdl_screen->format->Amask);
SDL_Surface* final_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, sdl_screen->w, sdl_screen->h, 16, sdl_screen->format->Rmask, sdl_screen->format->Gmask, sdl_screen->format->Bmask, sdl_screen->format->Amask);
SDL_FillRect( black_screen, NULL, 0 );
SDL_LockSurface(miniscreen);
if(IS_GG)
bitmap_scale(48,0,160,144,miniscreenwidth,miniscreenheight,256,0,(uint16_t*)sms_bitmap->pixels,(uint16_t*)miniscreen->pixels);
else
bitmap_scale(0,0,256,192,miniscreenwidth,miniscreenheight,256,0,(uint16_t*)sms_bitmap->pixels,(uint16_t*)miniscreen->pixels);
SDL_UnlockSurface(miniscreen);
char text[50];
SDL_PollEvent(&Event);
while (((currentselection != 1) && (currentselection != 5)) || (!pressed))
{
pressed = 0;
dstRect.x = sdl_screen->w-5-miniscreenwidth;
dstRect.y = 30;
if (!img_background) SDL_BlitSurface(black_screen,NULL,final_screen,NULL);
else SDL_BlitSurface(img_background,NULL,final_screen,NULL);
SDL_BlitSurface(miniscreen,NULL,final_screen,&dstRect);
gfx_font_print_center(final_screen,22,bigfontwhite,"SMSPlus-GX");
if (currentselection == 1)
gfx_font_print(final_screen,5,25,bigfontred,"Continue");
else
gfx_font_print(final_screen,5,25,bigfontwhite,"Continue");
sprintf(text,"Save State %d",save_slot);
if (currentselection == 2)
gfx_font_print(final_screen,5,65,bigfontred,text);
else
gfx_font_print(final_screen,5,65,bigfontwhite,text);
sprintf(text,"Load State %d",save_slot);
if (currentselection == 3)
gfx_font_print(final_screen,5,85,bigfontred,text);
else
gfx_font_print(final_screen,5,85,bigfontwhite,text);
if (currentselection == 4)
{
switch (fullscreen)
{
case 0:
gfx_font_print(final_screen,5,105,bigfontred,"Native resolution");
break;
case 1:
gfx_font_print(final_screen,5,105,bigfontred,"Keep Aspect Ratio");
break;
case 2:
gfx_font_print(final_screen,5,105,bigfontred,"Fullscreen (Auto-Crop)");
break;
case 3:
gfx_font_print(final_screen,5,105,bigfontred,"Fullscreen (No Crop)");
break;
}
}
else
{
switch (fullscreen)
{
case 0:
gfx_font_print(final_screen,5,105,bigfontwhite,"Native resolution");
break;
case 1:
gfx_font_print(final_screen,5,105,bigfontwhite,"Keep Aspect Ratio");
break;
case 2:
gfx_font_print(final_screen,5,105,bigfontwhite,"Fullscreen (Auto-Crop)");
break;
case 3:
gfx_font_print(final_screen,5,105,bigfontwhite,"Fullscreen (No Crop)");
break;
}
}
if (currentselection == 5)
gfx_font_print(final_screen,5,125,bigfontred,"Quit");
else
gfx_font_print(final_screen,5,125,bigfontwhite,"Quit");
gfx_font_print_center(final_screen,sdl_screen->h-80-gfx_font_height(font),font,"SMS_SDL for the RS-97");
gfx_font_print_center(final_screen,sdl_screen->h-70-gfx_font_height(font),font,"RS-97 port by gameblabla");
gfx_font_print_center(final_screen,sdl_screen->h-60-gfx_font_height(font),font,"See full credits on github:");
gfx_font_print_center(final_screen,sdl_screen->h-50-gfx_font_height(font),font,"https://github.com/gameblabla/sms_sdl");
for(uint8_t i = 0; i < 2; i++)
{
if (joystick[i] == NULL) joystick[i] = SDL_JoystickOpen(i);
}
while (SDL_PollEvent(&Event))
{
switch(Event.type)
{
case SDL_KEYDOWN:
{
switch(Event.key.keysym.sym)
{
case SDLK_UP:
currentselection--;
if (currentselection == 0)
currentselection = 5;
break;
case SDLK_DOWN:
currentselection++;
if (currentselection == 6)
currentselection = 1;
break;
case SDLK_LCTRL:
case SDLK_LALT:
case SDLK_RETURN:
pressed = 1;
break;
case SDLK_LEFT:
switch(currentselection)
{
case 2:
case 3:
if (save_slot > 0) save_slot--;
break;
case 4:
fullscreen--;
if (fullscreen < 0)
fullscreen = 3;
break;
}
break;
case SDLK_RIGHT:
switch(currentselection)
{
case 2:
case 3:
save_slot++;
if (save_slot == 10)
save_slot = 9;
break;
case 4:
fullscreen++;
if (fullscreen > 3)
fullscreen = 0;
break;
}
break;
}
break;
}
case SDL_JOYAXISMOTION:
if (Event.jaxis.axis == 0)
{
if (Event.jaxis.value < -500)
{
switch(currentselection)
{
case 2:
case 3:
if (save_slot > 0) save_slot--;
break;
case 4:
fullscreen--;
if (fullscreen < 0)
fullscreen = 3;
break;
}
}
else if (Event.jaxis.value > 500)
{
switch(currentselection)
{
case 2:
case 3:
save_slot++;
if (save_slot == 10)
save_slot = 9;
break;
case 4:
fullscreen++;
if (fullscreen > 3)
fullscreen = 0;
break;
}
}
}
else if (Event.jaxis.axis == 1)
{
if (Event.jaxis.value < -500)
{
currentselection--;
if (currentselection == 0)
currentselection = 5;
}
else if (Event.jaxis.value > 500)
{
currentselection++;
if (currentselection == 6)
currentselection = 1;
}
}
break;
case SDL_JOYBUTTONDOWN:
switch(Event.jbutton.button)
{
case 1:
case 2:
pressed = 1;
break;
}
break;
}
}
SDL_JoystickUpdate();
if (pressed)
{
switch(currentselection)
{
case 4 :
fullscreen++;
if (fullscreen > 3)
fullscreen = 0;
break;
case 2 :
smsp_state(save_slot, 0);
currentselection = 1;
break;
case 3 :
smsp_state(save_slot, 1);
currentselection = 1;
break;
}
}
SDL_BlitSurface(final_screen, NULL, sdl_screen, NULL);
SDL_Flip(sdl_screen);
//++sdl_video.frames_rendered;
}
if (currentselection == 5)
quit = 1;
if (quit)
{
SDL_FreeSurface(miniscreen);
SDL_FreeSurface(black_screen);
SDL_FreeSurface(final_screen);
}
}
int main (int argc, char *argv[])
{
int16_t x_move = 0, y_move = 0;
Uint8 *keystate;
SDL_Event event;
// Print Header
fprintf(stdout, "%s %s\n", APP_NAME, APP_VERSION);
if(argc < 2)
{
fprintf(stderr, "Usage: ./smsplus [FILE]\n");
exit(1);
}
memset(&option, 0, sizeof(option));
option.fm = 1;
option.spritelimit = 0;
option.filter = -1;
option.country = 0;
option.overscan = 0;
option.tms_pal = 2;
option.console = 0;
option.nosound = 0;
strcpy(option.game_name, argv[1]);
smsp_gamedata_set(argv[1]);
// Check the type of ROM
sms.console = strcmp(strrchr(argv[1], '.'), ".gg") ? CONSOLE_SMS : CONSOLE_GG;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
SDL_JoystickEventState(SDL_ENABLE);
sdl_screen = SDL_SetVideoMode(800, 480, 16, SDL_HWSURFACE);
SDL_SetCursor(0);
// Needed in order to clear the cursor
SDL_FillRect( sdl_screen, NULL, 0 );
SDL_Flip(sdl_screen);
sms_bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEO_WIDTH_SMS, 240, 16, 0, 0, 0, 0);
img_background = SDL_LoadBMP("background.bmp");
font = gfx_tex_load_tga_from_array(fontarray);
bigfontwhite = gfx_tex_load_tga_from_array(bigfontwhitearray);
bigfontred = gfx_tex_load_tga_from_array(bigfontredarray);
// Load ROM
if(!load_rom(argv[1])) {
fprintf(stderr, "Error: Failed to load %s.\n", argv[1]);
exit(1);
}
fprintf(stdout, "CRC : %08X\n", cart.crc);
// Set parameters for internal bitmap
bitmap.width = VIDEO_WIDTH_SMS;
bitmap.height = VIDEO_HEIGHT_SMS;
bitmap.depth = 16;
bitmap.granularity = 2;
bitmap.data = (uint8_t *)sms_bitmap->pixels;
bitmap.pitch = sms_bitmap->pitch;
bitmap.viewport.w = VIDEO_WIDTH_SMS;
bitmap.viewport.h = VIDEO_HEIGHT_SMS;
bitmap.viewport.x = 0x00;
bitmap.viewport.y = 0x00;
//sms.territory = settings.misc_region;
if (sms.console == CONSOLE_SMS || sms.console == CONSOLE_SMS2)
{
sms.use_fm = 1;
}
bios_init();
Sound_Init();
// Initialize all systems and power on
system_poweron();
frames_rendered = 0;
// Loop until the user closes the window
while (!quit)
{
// Refresh video data
video_update();
// Output audio
Sound_Update();
// Execute frame(s)
system_frame(0);
++frames_rendered;
if (sms.console == CONSOLE_COLECO)
{
input.system = 0;
coleco.keypad[0] = 0xff;
coleco.keypad[1] = 0xff;
}
if (selectpressed == 1)
{
Menu();
SDL_FillRect(sdl_screen, NULL, 0);
input.system &= (IS_GG) ? ~INPUT_START : ~INPUT_PAUSE;
selectpressed = 0;
}
keystate = SDL_GetKeyState(NULL);
for(uint8_t i=0;i<2;i++)
{
if (joystick[i] == NULL) joystick[i] = SDL_JoystickOpen(i);
x_move = SDL_JoystickGetAxis(joystick[i], 0);
y_move = SDL_JoystickGetAxis(joystick[i], 1);
if (x_move > 500 || (i == 0 && keystate[SDLK_RIGHT]))
input.pad[i] |= INPUT_RIGHT;
else
input.pad[i] &= ~INPUT_RIGHT;
if (x_move < -500 || (i == 0 && keystate[SDLK_LEFT]))
input.pad[i] |= INPUT_LEFT;
else
input.pad[i] &= ~INPUT_LEFT;
if (y_move > 500 || (i == 0 && keystate[SDLK_DOWN]))
input.pad[i] |= INPUT_DOWN;
else
input.pad[i] &= ~INPUT_DOWN;
if(y_move < -500 || (i == 0 && keystate[SDLK_UP]))
input.pad[i] |= INPUT_UP;
else
input.pad[i] &= ~INPUT_UP;
if(SDL_JoystickGetButton(joystick[i], 2) == SDL_PRESSED || (i == 0 && keystate[SDLK_LCTRL]))
input.pad[i] |= INPUT_BUTTON1;
else
input.pad[i] &= ~INPUT_BUTTON1;
if(SDL_JoystickGetButton(joystick[i], 1) == SDL_PRESSED || (i == 0 && keystate[SDLK_LALT]))
input.pad[i] |= INPUT_BUTTON2;
else
input.pad[i] &= ~INPUT_BUTTON2;
if(i == 0 && SDL_JoystickGetButton(joystick[i], 9) == SDL_PRESSED || keystate[SDLK_RETURN])
input.system |= (sms.console == CONSOLE_GG) ? INPUT_START : INPUT_PAUSE;
else
input.system &= ~(sms.console == CONSOLE_GG) ? INPUT_START : INPUT_PAUSE;
if(SDL_JoystickGetButton(joystick[i], 8) == SDL_PRESSED || keystate[SDLK_ESCAPE])
selectpressed = 1;
}
SDL_JoystickUpdate();
if(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
quit = 1;
return;
}
}
SDL_Flip(sdl_screen);
}
if (sdl_screen) SDL_FreeSurface(sdl_screen);
if (sms_bitmap) SDL_FreeSurface(sms_bitmap);
if (font) SDL_FreeSurface(font);
if (bigfontwhite) SDL_FreeSurface(bigfontwhite);
if (bigfontred) SDL_FreeSurface(bigfontred);
for(uint8_t i=0;i<2;i++)
{
if (joystick[i]) SDL_JoystickClose(joystick[i]);
}
// Deinitialize audio and video output
Sound_Close();
SDL_Quit();
// Shut down
system_poweroff();
system_shutdown();
return 0;
}

31
source/k3s/smsplus.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _SMSPLUS_H
#define _SMSPLUS_H
#define VIDEO_WIDTH_SMS 256
#define VIDEO_HEIGHT_SMS 192
#define VIDEO_WIDTH_GG 160
#define VIDEO_HEIGHT_GG 144
typedef struct {
int8_t gamename[256];
int8_t sramdir[256];
int8_t sramfile[516];
int8_t stdir[256];
int8_t scrdir[256];
int8_t biosdir[256];
} gamedata_t;
typedef struct {
int8_t* current_pos;
int8_t* buffer;
uint32_t current_emulated_samples;
} t_sdl_sound;
typedef struct {
uint32_t ticks_starting;
SDL_sem* sem_sync;
} t_sdl_sync;
void smsp_state(uint8_t slot, uint8_t mode);
#endif

View File

@ -411,11 +411,11 @@ void render_line(int32_t line)
/* Blank leftmost column of display */
if((vdp.reg[0] & 0x20) && (IS_SMS || IS_MD))
memset(linebuf, BACKDROP_COLOR, 8);
memset(linebuf, BACKDROP_COLOR, 8);
}
else
{
/* Background color */
/* Background color */
memset(linebuf, BACKDROP_COLOR, bitmap.viewport.w + 2*bitmap.viewport.x);
}
}
@ -427,6 +427,8 @@ void render_line(int32_t line)
parse_line(line);
/* LightGun mark */
#ifdef LIGHTGUN_ENABLED
/* Putting this in an ifdef because the condition loop is executed every render_line */
if (sms.device[0] == DEVICE_LIGHTGUN)
{
int dy = vdp.line - input.analog[0][1];
@ -443,6 +445,7 @@ void render_line(int32_t line)
}
}
}
#endif
/* Only draw lines within the video output range ! */
if (view)

70
source/z80/cpuintrf.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef CPUINTRF_H
#define CPUINTRF_H
#include "osd_cpu.h"
#define CPU_16BIT_PORT 0x4000
#define CPU_FLAGS_MASK 0xff00
enum
{
MAX_REGS = 128, /* maximum number of register of any CPU */
/* This value is passed to activecpu_get_reg to retrieve the previous
* program counter value, ie. before a CPU emulation started
* to fetch opcodes and arguments for the current instrution. */
REG_PREVIOUSPC = -1,
/* This value is passed to activecpu_get_reg to retrieve the current
* program counter value. */
REG_PC = -2,
/* This value is passed to activecpu_get_reg to retrieve the current
* stack pointer value. */
REG_SP = -3,
/* This value is passed to activecpu_get_reg/activecpu_set_reg, instead of one of
* the names from the enum a CPU core defines for it's registers,
* to get or set the contents of the memory pointed to by a stack pointer.
* You can specify the n'th element on the stack by (REG_SP_CONTENTS-n),
* ie. lower negative values. The actual element size (UINT16 or UINT32)
* depends on the CPU core. */
REG_SP_CONTENTS = -4
};
enum
{
/* line states */
CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */
ASSERT_LINE, /* assert an interrupt immediately */
HOLD_LINE, /* hold interrupt line until acknowledged */
PULSE_LINE, /* pulse interrupt line for one instruction */
/* internal flags (not for use by drivers!) */
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
/* interrupt parameters */
MAX_IRQ_LINES = 16, /* maximum number of IRQ lines per CPU */
IRQ_LINE_NMI = 127 /* IRQ line for NMIs */
};
/* daisy-chain link */
typedef struct {
void (*reset)(int); /* reset callback */
int (*interrupt_entry)(int); /* entry callback */
void (*interrupt_reti)(int); /* reti callback */
int irq_param; /* callback paramater */
} Z80_DaisyChain;
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
#define Z80_INT_REQ 0x01 /* interrupt request mask */
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
#endif /* CPUINTRF_H */

69
source/z80/osd_cpu.h Normal file
View File

@ -0,0 +1,69 @@
/*******************************************************************************
* *
* Define size independent data types and operations. *
* *
* The following types must be supported by all platforms: *
* *
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
* *
* *
* The macro names for the artithmatic operations are composed as follows: *
* *
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
* R - The type of the result *
* A - The type of operand 1 *
* B - The type of operand 2 (if binary operation) *
* *
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
* *
*******************************************************************************/
#ifndef OSD_CPU_H
#define OSD_CPU_H
#include <stdint.h>
/* Combine two 32-bit integers into a 64-bit integer */
#define COMBINE_64_32_32(A,B) ((((uint64_t)(A))<<32) | (uint32_t)(B))
#define COMBINE_U64_U32_U32(A,B) COMBINE_64_32_32(A,B)
/* Return upper 32 bits of a 64-bit integer */
#define HI32_32_64(A) (((uint64_t)(A)) >> 32)
#define HI32_U32_U64(A) HI32_32_64(A)
/* Return lower 32 bits of a 64-bit integer */
#define LO32_32_64(A) ((A) & 0xffffffff)
#define LO32_U32_U64(A) LO32_32_64(A)
#define DIV_64_64_32(A,B) ((A)/(B))
#define DIV_U64_U64_U32(A,B) ((A)/(uint32_t)(B))
#define MOD_32_64_32(A,B) ((A)%(B))
#define MOD_U32_U64_U32(A,B) ((A)%(uint32_t)(B))
#define MUL_64_32_32(A,B) ((A)*(INT64)(B))
#define MUL_U64_U32_U32(A,B) ((A)*(uint64_t)(uint32_t)(B))
/******************************************************************************
* Union of UINT8, UINT16 and UINT32 in native endianess of the target
* This is used to access bytes and words in a machine independent manner.
* The upper bytes h2 and h3 normally contain zero (16 bit CPU cores)
* thus PAIR.d can be used to pass arguments to the memory system
* which expects 'int' really.
******************************************************************************/
typedef union {
#ifdef LSB_FIRST
struct { uint8_t l,h,h2,h3; } b;
struct { uint16_t l,h; } w;
#else
struct { uint8_t h3,h2,h,l; } b;
struct { uint16_t h,l; } w;
#endif
uint32_t d;
} PAIR;
#endif /* defined OSD_CPU_H */

121
source/z80/state.c Normal file
View File

@ -0,0 +1,121 @@
/*
state.c --
Save state management.
*/
#include "shared.h"
void system_save_state(void *fd)
{
char *id = STATE_HEADER;
uint16_t version = STATE_VERSION;
/* Write header */
fwrite(id, sizeof(id), 1, fd);
fwrite(&version, sizeof(version), 1, fd);
/* Save VDP context */
fwrite(&vdp, sizeof(vdp_t), 1, fd);
/* Save SMS context */
fwrite(&sms, sizeof(sms_t), 1, fd);
fputc(cart.fcr[0], fd);
fputc(cart.fcr[1], fd);
fputc(cart.fcr[2], fd);
fputc(cart.fcr[3], fd);
fwrite(cart.sram, 0x8000, 1, fd);
/* Save Z80 context */
fwrite(Z80_Context, sizeof(Z80_Regs), 1, fd);
fwrite(&after_EI, sizeof(int), 1, fd);
/* Save YM2413 context */
fwrite(FM_GetContextPtr(), FM_GetContextSize(), 1, fd);
/* Save SN76489 context */
fwrite(SN76489_GetContextPtr(0), SN76489_GetContextSize(), 1, fd);
}
void system_load_state(void *fd)
{
int i;
uint8_t *buf;
char id[4];
uint16_t version;
/* Initialize everything */
z80_reset(0);
z80_set_irq_callback(sms_irq_callback);
system_reset();
if(snd.enabled)
sound_reset();
/* Read header */
fread(id, 4, 1, fd);
fread(&version, 2, 1, fd);
/* Load VDP context */
fread(&vdp, sizeof(vdp_t), 1, fd);
/* Load SMS context */
fread(&sms, sizeof(sms_t), 1, fd);
cart.fcr[0] = fgetc(fd);
cart.fcr[1] = fgetc(fd);
cart.fcr[2] = fgetc(fd);
cart.fcr[3] = fgetc(fd);
fread(cart.sram, 0x8000, 1, fd);
/* Load Z80 context */
fread(Z80_Context, sizeof(Z80_Regs), 1, fd);
fread(&after_EI, sizeof(int), 1, fd);
/* Load YM2413 context */
buf = malloc(FM_GetContextSize());
fread(buf, FM_GetContextSize(), 1, fd);
FM_SetContext(buf);
free(buf);
/* Load SN76489 context */
buf = malloc(SN76489_GetContextSize());
fread(buf, SN76489_GetContextSize(), 1, fd);
SN76489_SetContext(0, buf);
free(buf);
/* Restore callbacks */
z80_set_irq_callback(sms_irq_callback);
for(i = 0x00; i <= 0x2F; i++)
{
cpu_readmap[i] = &cart.rom[(i & 0x1F) << 10];
cpu_writemap[i] = dummy_write;
}
for(i = 0x30; i <= 0x3F; i++)
{
cpu_readmap[i] = &sms.wram[(i & 0x07) << 10];
cpu_writemap[i] = &sms.wram[(i & 0x07) << 10];
}
sms_mapper_w(3, cart.fcr[3]);
sms_mapper_w(2, cart.fcr[2]);
sms_mapper_w(1, cart.fcr[1]);
sms_mapper_w(0, cart.fcr[0]);
/* Force full pattern cache update */
bg_list_index = 0x200;
for(i = 0; i < 0x200; i++)
{
bg_name_list[i] = i;
bg_name_dirty[i] = -1;
}
/* Restore palette */
for(i = 0; i < PALETTE_SIZE; i++)
palette_sync(i, 1);
viewport_check();
}

14
source/z80/state.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _STATE_H_
#define _STATE_H_
#define STATE_VERSION 0x0101 /* Version 1.1 (BCD) */
#define STATE_HEADER "SST\0" /* State file header */
/* Function prototypes */
void system_save_state(void *fd);
void system_load_state(void *fd);
#endif /* _STATE_H_ */

3965
source/z80/z80.c Normal file

File diff suppressed because it is too large Load Diff

76
source/z80/z80.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef Z80_H
#define Z80_H
#include "cpuintrf.h"
#include "osd_cpu.h"
/* Hack in order to make the save states work - gameblabla */
#define z80_t Z80_Regs
enum {
Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
};
enum {
Z80_TABLE_op,
Z80_TABLE_cb,
Z80_TABLE_ed,
Z80_TABLE_xy,
Z80_TABLE_xycb,
Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
};
/****************************************************************************/
/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */
/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */
/****************************************************************************/
typedef struct {
/* 00 */ PAIR PREPC,PC,SP,AF,BC,DE,HL,IX,IY;
/* 24 */ PAIR AF2,BC2,DE2,HL2;
/* 34 */ uint8_t R,R2,IFF1,IFF2,HALT,IM,I;
/* 3B */ uint8_t irq_max; /* number of daisy chain devices */
/* 3C */ int8_t request_irq; /* daisy chain next request device */
/* 3D */ int8_t service_irq; /* daisy chain next reti handling device */
/* 3E */ uint8_t nmi_state; /* nmi line state */
/* 3F */ uint8_t irq_state; /* irq line state */
/* 40 */ uint8_t int_state[Z80_MAXDAISY];
/* 44 */ Z80_DaisyChain irq[Z80_MAXDAISY];
/* 84 */ int (*irq_callback)(int irqline);
/* 88 */ int extra_cycles; /* extra cycles for interrupts */
} Z80_Regs;
extern int z80_ICount; /* T-state count */
extern void z80_init(void);
extern void z80_reset (void *param);
extern void z80_exit (void);
extern int z80_execute(int cycles);
extern void z80_burn(int cycles);
extern unsigned z80_get_context (void *dst);
extern void z80_set_context (void *src);
extern const void *z80_get_cycle_table (int which);
extern void z80_set_cycle_table (int which, void *new_tbl);
extern unsigned z80_get_reg (int regnum);
extern void z80_set_reg (int regnum, unsigned val);
extern void z80_set_irq_line(int irqline, int state);
extern void z80_set_irq_callback(int (*irq_callback)(int));
extern unsigned z80_dasm(char *buffer, unsigned pc);
extern Z80_Regs *Z80_Context;
extern int after_EI;
extern uint8_t *cpu_readmap[64];
extern uint8_t *cpu_writemap[64];
extern void (*cpu_writemem16)(uint16_t address, uint8_t data);
extern void (*cpu_writeport16)(uint16_t port, uint8_t data);
extern uint8_t (*cpu_readport16)(uint16_t port);
void z80_reset_cycle_count(void);
int z80_get_elapsed_cycles(void);
#endif

31
source/z80/z80_wrap.c Normal file
View File

@ -0,0 +1,31 @@
#include <stdint.h>
#include "z80.h"
#include "shared.h"
int32_t z80_ICount = 0;
int32_t z80_nmipending = 0;
int32_t z80_nmi_state = 0;
int32_t extra_cycles = 0;
void (*cpu_writemem16)(uint16_t address, uint8_t data);
void (*cpu_writeport16)(uint16_t port, uint8_t data);
uint8_t (*cpu_readport16)(uint16_t port);
extern int32_t z80_get_elapsed_cycles();
void CPUZ80_Init()
{
z80_init();
}
void CPUZ80_Reset()
{
z80_reset(NULL);
z80_set_irq_callback(sms_irq_callback);
}
void CPUIRQ_Pause()
{
z80_set_irq_line(IRQ_LINE_NMI, ASSERT_LINE);
z80_set_irq_line(IRQ_LINE_NMI, CLEAR_LINE);
}

25
source/z80/z80_wrap.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef WRAP_H
#define WRAP_H
#define ASSERT_LINE 1
#define CLEAR_LINE 0
#define IRQ_LINE_NMI 127
#define INPUT_LINE_NMI 32
#define INPUT_LINE_IRQ0 0
extern void CPUZ80_Init();
extern void CPUZ80_Reset();
extern void CPUIRQ_Pause();
extern int32_t z80_ICount;
extern int32_t extra_cycles;
extern int32_t z80_nmipending;
extern int32_t z80_nmi_state;
extern void z80_set_irq_line(int irqline, int state);
extern int32_t z80_get_elapsed_cycles();
extern uint8_t *cpu_readmap[64];
extern uint8_t *cpu_writemap[64];
#endif

2052
source/z80/z80daa.h Normal file

File diff suppressed because it is too large Load Diff