Arcade Mini port, fixed some bugs, boosted audio volume

This commit is contained in:
gameblabla 2018-10-12 03:08:32 -04:00
parent 2f062b4810
commit a5a515da4d
No known key found for this signature in database
GPG Key ID: B24EFBB23B5F76CB
17 changed files with 1145 additions and 89 deletions

5
.gitignore vendored
View File

@ -4,6 +4,11 @@
*.gg
*.sg
*.o
*.gcda
*.zip
*.bin
core
include/
source/nonfree/
sms_sdl
*.out

View File

@ -16,7 +16,7 @@ CXXFLAGS = $(CFLAGS)
LDFLAGS = -lSDL -lm -flto -lz -lportaudio
# Files to be r
SRCDIR = ./source ./source/unzip ./source/eighty ./source/sound ./source/generic ./source/sdl ./source/sound/crabemu_sn76489
SRCDIR = ./source ./source/unzip ./source/eighty ./source/sound ./source/generic ./source/amini ./source/sound/crabemu_sn76489
VPATH = $(SRCDIR)
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))

43
Makefile.amini Normal file
View File

@ -0,0 +1,43 @@
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 = -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 += -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
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
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

@ -9,9 +9,12 @@ LD = /opt/rs97-toolchain/bin/mipsel-linux-gcc
# add SDL dependencies
CFLAGS = -msym32 -mlong-calls -fno-pic -fno-pie -O2 -mno-abicalls -fdata-sections -ffunction-sections -mips32 -mno-shared -mno-mips16
#-msym32 -mlong-calls
CFLAGS = -Ofast -msym32 -mlong-calls -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 += -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 -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

BIN
background.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

757
source/amini/smsplus.c Normal file
View File

@ -0,0 +1,757 @@
#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;
uint8_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_LockSurface(sdl_screen);
switch(fullscreen)
{
case 1:
case 2: // aspect ratio
if(sms.console == CONSOLE_GG)
upscale_160x144_to_320x272_for_480x272((uint32_t*)sdl_screen->pixels, (uint32_t*)sms_bitmap->pixels+24);
else
upscale_256x192_to_384x272_for_480x272((uint32_t*)sdl_screen->pixels, (uint32_t*)sms_bitmap->pixels, vdp.height);
break;
default: // native res
if(sms.console == CONSOLE_GG)
bitmap_scale(48,0,160,144,160,144,256,sdl_screen->w-160,(uint16_t*)sms_bitmap->pixels,(uint16_t*)sdl_screen->pixels+(sdl_screen->w-160)/2+(sdl_screen->h-144)/2*sdl_screen->w);
else
bitmap_scale(0,0,256,vdp.height,256,vdp.height,256,sdl_screen->w-256,(uint16_t*)sms_bitmap->pixels,(uint16_t*)sdl_screen->pixels+(sdl_screen->w-256)/2+(sdl_screen->h-vdp.height)/2*sdl_screen->w);
break;
}
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)
{
if (fullscreen == 1)
gfx_font_print(final_screen,5,105,bigfontred,"Stretched");
else
gfx_font_print(final_screen,5,105,bigfontred,"Native");
}
else
{
if (fullscreen == 1)
gfx_font_print(final_screen,5,105,bigfontwhite,"Stretched");
else
gfx_font_print(final_screen,5,105,bigfontwhite,"Native");
}
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-50-gfx_font_height(font),font,"SMS_SDL for the RS-97");
gfx_font_print_center(final_screen,sdl_screen->h-40-gfx_font_height(font),font,"RS-97 port by gameblabla");
gfx_font_print_center(final_screen,sdl_screen->h-30-gfx_font_height(font),font,"See full credits on github:");
gfx_font_print_center(final_screen,sdl_screen->h-20-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 = 1;
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 > 1)
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 = 1;
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 > 1)
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 > 1)
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(480, 272, 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/amini/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

@ -244,3 +244,205 @@ void upscale_SMS_to_320x240(uint32_t *dst, uint32_t *src, uint32_t height_scale)
Eh += height_scale; if(Eh >= 240) { Eh -= 240; dh++; }
}
}
/* Retro Arcade Mini scalers. Boo, ugly */
/* Game Gear*/
void upscale_160x144_to_320x272_for_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int i, j;
dst += (480-320)/4; // center correction for 480x272 mode
for (i = 0; i < 272; i++)
{
source = dh * 256 / 2;
for (j = 0; j < 320/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 += (480-320)/2; // pitch correction for 480x272 mode
Eh += 144; if(Eh >= 272) { Eh -= 272; dh++; }
}
}
void upscale_160x144_to_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int i, j;
for (i = 0; i < 272; i++)
{
source = dh * 256 / 2;
for (j = 0; j < 480/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;
int Eh = 0;
int source = 0;
int dh = 0;
int y, x;
dst += (480 - 384) / 4;
for (y = 0; y < 272; 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 += (480 - 384) / 2;
Eh += 192; if(Eh >= 272) { Eh -= 272; dh++; }
}
}
void upscale_256x192_to_480x272(uint32_t *dst, uint32_t *src)
{
int midh = 272 / 2;
int Eh = 0;
int source = 0;
int dh = 0;
int y, x;
for (y = 0; y < 272; y++)
{
source = dh * 256 / 2;
for (x = 0; x < 480/30; x++)
{
register uint32_t ab, cd, ef, gh, ij, kl, mn, op;
__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;
ij = src[source + 4] & 0xF7DEF7DE;
kl = src[source + 5] & 0xF7DEF7DE;
mn = src[source + 6] & 0xF7DEF7DE;
op = src[source + 7] & 0xF7DEF7DE;
/*if(Eh >= midh) {
ab = AVERAGE(ab, src[source + 256/2]) & 0xF7DEF7DE;
cd = AVERAGE(cd, src[source + 256/2 + 1]) & 0xF7DEF7DE;
ef = AVERAGE(ef, src[source + 256/2 + 2]) & 0xF7DEF7DE;
gh = AVERAGE(gh, src[source + 256/2 + 3]) & 0xF7DEF7DE;
ij = AVERAGE(ij, src[source + 256/2 + 4]) & 0xF7DEF7DE;
kl = AVERAGE(kl, src[source + 256/2 + 5]) & 0xF7DEF7DE;
mn = AVERAGE(mn, src[source + 256/2 + 6]) & 0xF7DEF7DE;
op = AVERAGE(op, src[source + 256/2 + 7]) & 0xF7DEF7DE;
}*/
*dst++ = (ab & 0xFFFF) + (ab << 16); // [aa]
*dst++ = (ab >> 16) + (ab & 0xFFFF0000); // [bb]
*dst++ = (cd & 0xFFFF) + (cd << 16); // [cc]
*dst++ = (cd >> 16) + (((cd & 0xF7DE0000) >> 1) + ((ef & 0xF7DE) << 15)); // [d(de)]
*dst++ = ef; // [ef]
*dst++ = (ef >> 16) + (gh << 16); // [fg]
*dst++ = gh; // [gh]
*dst++ = (gh >> 16) + (ij << 16); // [hi]
*dst++ = ij; // [ij]
*dst++ = (ij >> 16) + (kl << 16); // [jk]
*dst++ = kl; // [kl]
*dst++ = (((kl & 0xF7DE0000) >> 17) + ((mn & 0xF7DE) >> 1)) + (mn << 16); // [(lm)m]
*dst++ = (mn >> 16) + (mn & 0xFFFF0000); // [nn]
*dst++ = (op & 0xFFFF) + (op << 16); // [oo]
*dst++ = (op >> 16) + (op & 0xFFFF0000); // [pp]
source += 8;
}
Eh += 192; if(Eh >= 272) { Eh -= 272; dh++; }
}
}

View File

@ -10,29 +10,27 @@ SDL_Surface *bigfontwhite = NULL;
extern SDL_Surface* sdl_screen;
uint16_t gfx_font_width(SDL_Surface* inFont, char* inString)
{
if((inFont == NULL) || (inString == NULL))
return 0;
uintptr_t i, tempCur, tempMax;
for(i = 0, tempCur = 0, tempMax = 0; inString[i] != '\0'; i++) {
if(inString[i] == '\t')
tempCur += 4;
else if((inString[i] == '\r') || (inString[i] == '\n'))
tempCur = 0;
else
tempCur++;
if(tempCur > tempMax) tempMax = tempCur;
}
tempMax *= (inFont->w >> 4);
return tempMax;
uint16_t gfx_font_width(SDL_Surface* inFont, char* inString) {
if((inFont == NULL) || (inString == NULL))
return 0;
uintptr_t i, tempCur, tempMax;
for(i = 0, tempCur = 0, tempMax = 0; inString[i] != '\0'; i++) {
if(inString[i] == '\t')
tempCur += 4;
else if((inString[i] == '\r') || (inString[i] == '\n'))
tempCur = 0;
else
tempCur++;
if(tempCur > tempMax) tempMax = tempCur;
}
tempMax *= (inFont->w >> 4);
return tempMax;
}
uint16_t gfx_font_height(SDL_Surface* inFont)
{
if(inFont == NULL)
return 0;
return (inFont->h >> 4);
uint16_t gfx_font_height(SDL_Surface* inFont) {
if(inFont == NULL)
return 0;
return (inFont->h >> 4);
}
void gfx_font_print(SDL_Surface* dest,int16_t inX, int16_t inY, SDL_Surface* inFont, char* inString)

View File

@ -22,7 +22,7 @@
#include "shared.h"
#define GAME_DATABASE_CNT 94
#define GAME_DATABASE_CNT 96
typedef struct
{
@ -244,8 +244,14 @@ rominfo_t game_list[GAME_DATABASE_CNT] =
{0xE42E4998, 0, DEVICE_SPORTSPAD, MAPPER_SEGA, DISPLAY_NTSC, TERRITORY_EXPORT, CONSOLE_SMS2,
"Sports Pad Football"},
{0x41C948BF, 0, DEVICE_SPORTSPAD, MAPPER_SEGA, DISPLAY_NTSC, TERRITORY_EXPORT, CONSOLE_SMS2,
"Sports Pad Soccer"}
"Sports Pad Soccer"},
/* Games using FM sound only when a certain region is set. Not required for the games to be playable
* but most people prefer the FM soundtrack anyway. */
{0x679E1676, 0, DEVICE_PAD2B, MAPPER_SEGA, DISPLAY_NTSC, TERRITORY_DOMESTIC, CONSOLE_SMS2,
"Wonder Boy III - The dragon's Trap"},
{0x22CCA9BB, 0, DEVICE_PAD2B, MAPPER_SEGA, DISPLAY_NTSC, TERRITORY_DOMESTIC, CONSOLE_SMS2,
"Turma da Monica em O Resgate"}
};
void set_config()

View File

@ -4,8 +4,6 @@
#include "shared.h"
#define SMSSDL_CORE_VER "1"
#define SMSSDL_RELEASE "7"
#define SMSSDL_TITLE "SMS Plus/SDL v" SMSSDL_CORE_VER "R" SMSSDL_RELEASE
@ -17,8 +15,10 @@
#define FILTER_MARGIN_HEIGHT 3
#define SOUND_FREQUENCY 48000
#define SOUND_SAMPLES_SIZE 2048
/*#define SOUND_FREQUENCY 48000
#define SOUND_SAMPLES_SIZE 2048*/
#define SOUND_FREQUENCY 22050
#define SOUND_SAMPLES_SIZE 1024
#define MACHINE_FPS 60

View File

@ -324,49 +324,51 @@ void render_init(void)
/* Reset the rendering data */
void render_reset(void)
{
int32_t i;
int32_t i;
/* Clear display bitmap */
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
/* Clear display bitmap */
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
/* Clear palette */
for(i = 0; i < PALETTE_SIZE; i++)
{
palette_sync(i);
}
/* Clear palette */
for(i = 0; i < PALETTE_SIZE; i++)
{
palette_sync(i);
}
/* Invalidate pattern cache */
memset(bg_name_dirty, 0, sizeof(bg_name_dirty));
memset(bg_name_list, 0, sizeof(bg_name_list));
bg_list_index = 0;
memset(bg_pattern_cache, 0, sizeof(bg_pattern_cache));
/* Invalidate pattern cache */
memset(bg_name_dirty, 0, sizeof(bg_name_dirty));
memset(bg_name_list, 0, sizeof(bg_name_list));
bg_list_index = 0;
memset(bg_pattern_cache, 0, sizeof(bg_pattern_cache));
/* Pick default render routine */
if (vdp.reg[0] & 4)
{
render_bg = render_bg_sms;
render_obj = render_obj_sms;
}
else
{
render_bg = render_bg_tms;
render_obj = render_obj_tms;
}
/* Pick default render routine */
if (vdp.reg[0] & 4)
{
render_bg = render_bg_sms;
render_obj = render_obj_sms;
}
else
{
render_bg = render_bg_tms;
render_obj = render_obj_tms;
}
}
static int prev_line = -1;
static int32_t prev_line = -1;
/* Draw a line of the display */
void render_line(int32_t line)
{
int32_t view = 1;
/* ensure we have not already rendered this line */
/* Ensure we have not already rendered this line */
if (prev_line == line) return;
prev_line = line;
/* Ensure we're within the VDP active area (incl. overscan) */
int32_t top_border = active_border[sms.display][vdp.extended];
int32_t top_border = active_border[sms.display][vdp.extended];
int32_t vline = (line + top_border) % vdp.lpf;
if (vline >= active_range[sms.display]) return;
/* adjust for Game Gear screen */
@ -452,7 +454,7 @@ void render_line(int32_t line)
}
/* Draw the Master System background */
void render_bg_sms(int line)
void render_bg_sms(int32_t line)
{
int32_t locked = 0;
int32_t yscroll_mask = (vdp.extended) ? 256 : 224;
@ -707,7 +709,6 @@ void palette_sync(int32_t index)
pixel[index] = MAKE_PIXEL(r, g, b);
}
static void parse_satb(int32_t line)
{
/* Pointer to sprite attribute table */

View File

@ -31,8 +31,8 @@
/* Used for blanking a line in whole or in part */
#define BACKDROP_COLOR (0x10 | (vdp.reg[7] & 0x0F))
extern void (*render_bg)(int line);
extern void (*render_obj)(int line);
extern void (*render_bg)(int32_t line);
extern void (*render_obj)(int32_t line);
extern uint8 *linebuf;
extern uint8 sms_cram_expand_table[4];
extern uint8 gg_cram_expand_table[16];
@ -43,9 +43,9 @@ extern uint16 bg_list_index;
extern void render_shutdown(void);
extern void render_init(void);
extern void render_reset(void);
extern void render_line(int line);
extern void render_bg_sms(int line);
extern void render_obj_sms(int line);
extern void palette_sync(int index);
extern void render_line(int32_t line);
extern void render_bg_sms(int32_t line);
extern void render_obj_sms(int32_t line);
extern void palette_sync(int32_t index);
#endif /* _RENDER_H_ */

View File

@ -37,8 +37,8 @@ uint8_t save_slot = 0;
uint8_t showfps = 0;
uint8_t quit = 0;
#define SOUND_FREQUENCY 48000
#define SOUND_SAMPLES_SIZE 2048
#define SOUND_FREQUENCY 22050
#define SOUND_SAMPLES_SIZE 1024
static int16_t buffer_snd[SOUND_FREQUENCY * 2];
/* Sound */
@ -74,10 +74,11 @@ static uint32_t Sound_Init()
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];
buffer_snd[i * 2 + 1] = snd.output[0][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 );
}

View File

@ -7,8 +7,14 @@
FM_Context fm_context;
YM2413 *fmm;
/* Only the 1st Master System supports FM sound. Because it is still processed even though it's not used,
* don't process FM sound if it can't be used in any way.
*/
static uint32_t isfm_used = 0;
void FM_Init(void)
{
isfm_used = 0;
fmm = ym2413_init(snd.fm_clock, snd.sample_rate);
ym2413_reset(fmm);
}
@ -16,19 +22,21 @@ void FM_Init(void)
void FM_Shutdown(void)
{
isfm_used = 0;
ym2413_shutdown(fmm);
}
void FM_Reset(void)
{
isfm_used = 0;
ym2413_reset(fmm);
}
void FM_Update(int16_t **buffer, uint32_t length)
{
ym2413_update(fmm, buffer, length);
if (isfm_used) ym2413_update(fmm, buffer, length);
}
void FM_WriteReg(uint32_t reg, uint32_t data)
@ -45,6 +53,7 @@ void FM_Write(uint32_t offset, uint32_t data)
fm_context.latch = data;
ym2413_write(fmm, offset & 1, data);
isfm_used = 1;
}

View File

@ -215,7 +215,7 @@ void sound_reset(void)
}
void sound_update(int line)
void sound_update(uint32_t line)
{
int16_t *fm[2], *psg[2];
@ -272,7 +272,7 @@ void sound_update(int line)
}
/* Generic FM+PSG stereo mixer callback */
void sound_mixer_callback(int16 **stream, int16 **output, int length)
void sound_mixer_callback(int16_t **stream, int16_t **output, uint32_t length)
{
uint32_t i;
for(i = 0; i < length; i++)
@ -287,7 +287,7 @@ void sound_mixer_callback(int16 **stream, int16 **output, int length)
/* Sound chip access handlers */
/*--------------------------------------------------------------------------*/
void psg_stereo_w(int data)
void psg_stereo_w(uint32_t data)
{
if(!snd.enabled) return;
#ifdef MAXIM_PSG
@ -297,12 +297,12 @@ void psg_stereo_w(int data)
#endif
}
void stream_update(int which, int position)
void stream_update(uint32_t which, uint32_t position)
{
}
void psg_write(int data)
void psg_write(uint32_t data)
{
if(!snd.enabled) return;
#ifdef MAXIM_PSG
@ -321,13 +321,13 @@ int fmunit_detect_r(void)
return sms.fm_detect;
}
void fmunit_detect_w(int data)
void fmunit_detect_w(uint32_t data)
{
if(!snd.enabled || !sms.use_fm) return;
sms.fm_detect = data;
}
void fmunit_write(int offset, int data)
void fmunit_write(uint32_t offset, uint32_t data)
{
if(!snd.enabled || !sms.use_fm) return;
FM_Write(offset, data);

View File

@ -36,9 +36,9 @@ enum {
/* Sound emulation structure */
typedef struct
{
void (*mixer_callback)(int16 **stream, int16 **output, int length);
int16 *output[2];
int16 *stream[STREAM_MAX];
void (*mixer_callback)(int16_t **stream, int16_t **output, uint32_t length);
int16_t *output[2];
int16_t *stream[STREAM_MAX];
int fm_which;
int enabled;
int fps;
@ -46,8 +46,8 @@ typedef struct
int sample_count;
int sample_rate;
int done_so_far;
uint32 fm_clock;
uint32 psg_clock;
uint32_t fm_clock;
uint32_t psg_clock;
} snd_t;
@ -55,15 +55,15 @@ typedef struct
extern snd_t snd;
/* Function prototypes */
void psg_write(int data);
void psg_stereo_w(int data);
void psg_write(uint32_t data);
void psg_stereo_w(uint32_t data);
int fmunit_detect_r(void);
void fmunit_detect_w(int data);
void fmunit_write(int offset, int data);
void fmunit_detect_w(uint32_t data);
void fmunit_write(uint32_t offset, uint32_t data);
int sound_init(void);
void sound_shutdown(void);
void sound_reset(void);
void sound_update(int line);
void sound_mixer_callback(int16 **stream, int16 **output, int length);
void sound_update(uint32_t line);
void sound_mixer_callback(int16_t **stream, int16_t **output, uint32_t length);
#endif /* _SOUND_H_ */