From c2248f784661252349717a996b5049ca7a7cc582 Mon Sep 17 00:00:00 2001 From: clobber Date: Fri, 29 Aug 2014 14:40:54 -0500 Subject: [PATCH] Initial port --- English.lproj/InfoPlist.strings | Bin 0 -> 92 bytes Info.plist | 38 + O2EM.xcodeproj/TemplateIcon.icns | Bin 0 -> 52318 bytes O2EM.xcodeproj/project.pbxproj | 596 +++++++++++ OdysseyGameCore.h | 35 + OdysseyGameCore.m | 630 ++++++++++++ allegrowrapper/libretro.h | 1476 +++++++++++++++++++++++++++ allegrowrapper/wrapalleg.c | 207 ++++ allegrowrapper/wrapalleg.h | 56 ++ clean/src/CHANGELOG | 316 ++++++ clean/src/COPYING | 138 +++ clean/src/Makefile | 81 ++ clean/src/Makefile.djgpp | 71 ++ clean/src/Makefile.freebsd | 68 ++ clean/src/Makefile.mingw | 72 ++ clean/src/Makefile.win | 35 + clean/src/O2EM.ICO | Bin 0 -> 5694 bytes clean/src/O2EM116_private.h | 23 + clean/src/O2EM116_private.rc | 5 + clean/src/README | 341 +++++++ clean/src/audio.c | 188 ++++ clean/src/audio.h | 17 + clean/src/config.h | 14 + clean/src/cpu.c | 1572 +++++++++++++++++++++++++++++ clean/src/cpu.h | 65 ++ clean/src/crc32.c | 116 +++ clean/src/crc32.h | 8 + clean/src/cset.c | 86 ++ clean/src/cset.h | 6 + clean/src/debug.c | 1052 ++++++++++++++++++++ clean/src/debug.h | 14 + clean/src/dis48.c | 144 +++ clean/src/keyboard.c | 374 +++++++ clean/src/keyboard.h | 96 ++ clean/src/main.c | 922 +++++++++++++++++ clean/src/o2em.png | Bin 0 -> 364 bytes clean/src/o2em.rc | 3 + clean/src/o2em.res | Bin 0 -> 5982 bytes clean/src/score.c | 144 +++ clean/src/score.h | 10 + clean/src/table.c | 341 +++++++ clean/src/table.h | 10 + clean/src/timefunc.c | 100 ++ clean/src/timefunc.h | 8 + clean/src/types.h | 8 + clean/src/vdc.c | 830 ++++++++++++++++ clean/src/vdc.h | 35 + clean/src/vmachine.c | 908 +++++++++++++++++ clean/src/vmachine.h | 101 ++ clean/src/voice.c | 158 +++ clean/src/voice.h | 14 + clean/src/vpp.c | 549 +++++++++++ clean/src/vpp.h | 12 + clean/src/vpp_cset.c | 285 ++++++ clean/src/vpp_cset.h | 6 + clean/stubs/allegro.c | 207 ++++ clean/stubs/allegro.h | 81 ++ src/Makefile | 72 ++ src/Makefile.djgpp | 71 ++ src/Makefile.freebsd | 68 ++ src/Makefile.linux | 68 ++ src/Makefile.mingw | 69 ++ src/Makefile.win | 35 + src/O2EM.ICO | Bin 0 -> 5694 bytes src/O2EM.RC | 3 + src/O2EM.RES | Bin 0 -> 5982 bytes src/O2EM116_private.h | 23 + src/O2EM116_private.rc | 5 + src/O2em118.dev | 378 +++++++ src/O2em118.layout | 267 +++++ src/audio.c | 219 +++++ src/audio.h | 17 + src/config.h | 14 + src/cpu.c | 1586 ++++++++++++++++++++++++++++++ src/cpu.h | 65 ++ src/crc32.c | 110 +++ src/crc32.h | 7 + src/cset.c | 86 ++ src/cset.h | 6 + src/debug.c | 1056 ++++++++++++++++++++ src/debug.h | 14 + src/dis48.c | 151 +++ src/keyboard.c | 583 +++++++++++ src/keyboard.h | 29 + src/main.c | 962 ++++++++++++++++++ src/o2em.png | Bin 0 -> 364 bytes src/score.c | 152 +++ src/score.h | 10 + src/system.c | 501 ++++++++++ src/table.c | 341 +++++++ src/table.h | 10 + src/timefunc.c | 124 +++ src/timefunc.h | 8 + src/types.h | 8 + src/vdc.c | 882 +++++++++++++++++ src/vdc.h | 40 + src/vmachine.c | 827 ++++++++++++++++ src/vmachine.h | 101 ++ src/voice.c | 175 ++++ src/voice.h | 14 + src/vpp.c | 521 ++++++++++ src/vpp.h | 12 + src/vpp_cset.c | 285 ++++++ src/vpp_cset.h | 6 + 104 files changed, 22653 insertions(+) create mode 100644 English.lproj/InfoPlist.strings create mode 100644 Info.plist create mode 100644 O2EM.xcodeproj/TemplateIcon.icns create mode 100644 O2EM.xcodeproj/project.pbxproj create mode 100644 OdysseyGameCore.h create mode 100644 OdysseyGameCore.m create mode 100755 allegrowrapper/libretro.h create mode 100755 allegrowrapper/wrapalleg.c create mode 100755 allegrowrapper/wrapalleg.h create mode 100755 clean/src/CHANGELOG create mode 100755 clean/src/COPYING create mode 100755 clean/src/Makefile create mode 100755 clean/src/Makefile.djgpp create mode 100755 clean/src/Makefile.freebsd create mode 100755 clean/src/Makefile.mingw create mode 100755 clean/src/Makefile.win create mode 100755 clean/src/O2EM.ICO create mode 100755 clean/src/O2EM116_private.h create mode 100755 clean/src/O2EM116_private.rc create mode 100755 clean/src/README create mode 100755 clean/src/audio.c create mode 100755 clean/src/audio.h create mode 100755 clean/src/config.h create mode 100755 clean/src/cpu.c create mode 100755 clean/src/cpu.h create mode 100755 clean/src/crc32.c create mode 100755 clean/src/crc32.h create mode 100755 clean/src/cset.c create mode 100755 clean/src/cset.h create mode 100755 clean/src/debug.c create mode 100755 clean/src/debug.h create mode 100755 clean/src/dis48.c create mode 100755 clean/src/keyboard.c create mode 100755 clean/src/keyboard.h create mode 100755 clean/src/main.c create mode 100755 clean/src/o2em.png create mode 100755 clean/src/o2em.rc create mode 100755 clean/src/o2em.res create mode 100755 clean/src/score.c create mode 100755 clean/src/score.h create mode 100755 clean/src/table.c create mode 100755 clean/src/table.h create mode 100755 clean/src/timefunc.c create mode 100755 clean/src/timefunc.h create mode 100755 clean/src/types.h create mode 100755 clean/src/vdc.c create mode 100755 clean/src/vdc.h create mode 100755 clean/src/vmachine.c create mode 100755 clean/src/vmachine.h create mode 100755 clean/src/voice.c create mode 100755 clean/src/voice.h create mode 100755 clean/src/vpp.c create mode 100755 clean/src/vpp.h create mode 100755 clean/src/vpp_cset.c create mode 100755 clean/src/vpp_cset.h create mode 100755 clean/stubs/allegro.c create mode 100755 clean/stubs/allegro.h create mode 100755 src/Makefile create mode 100755 src/Makefile.djgpp create mode 100755 src/Makefile.freebsd create mode 100755 src/Makefile.linux create mode 100755 src/Makefile.mingw create mode 100755 src/Makefile.win create mode 100755 src/O2EM.ICO create mode 100755 src/O2EM.RC create mode 100755 src/O2EM.RES create mode 100755 src/O2EM116_private.h create mode 100755 src/O2EM116_private.rc create mode 100755 src/O2em118.dev create mode 100755 src/O2em118.layout create mode 100755 src/audio.c create mode 100755 src/audio.h create mode 100755 src/config.h create mode 100755 src/cpu.c create mode 100755 src/cpu.h create mode 100755 src/crc32.c create mode 100755 src/crc32.h create mode 100755 src/cset.c create mode 100755 src/cset.h create mode 100755 src/debug.c create mode 100755 src/debug.h create mode 100755 src/dis48.c create mode 100755 src/keyboard.c create mode 100755 src/keyboard.h create mode 100755 src/main.c create mode 100755 src/o2em.png create mode 100755 src/score.c create mode 100755 src/score.h create mode 100755 src/system.c create mode 100755 src/table.c create mode 100755 src/table.h create mode 100755 src/timefunc.c create mode 100755 src/timefunc.h create mode 100755 src/types.h create mode 100755 src/vdc.c create mode 100755 src/vdc.h create mode 100755 src/vmachine.c create mode 100755 src/vmachine.h create mode 100755 src/voice.c create mode 100755 src/voice.h create mode 100755 src/vpp.c create mode 100755 src/vpp.h create mode 100755 src/vpp_cset.c create mode 100755 src/vpp_cset.h diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..5e45963c382ba690b781b953a00585212b898ac5 GIT binary patch literal 92 zcmW-XQ3`+{5C!MkQ~2$No+IcIkqMDxWCV8j>LCj|yTg2Mz+o9F%uHlf9u}h9EuK`F a!Y*1dX%G66ZqL#C$|bw0ZoP5@jOGW1ArT7z literal 0 HcmV?d00001 diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..1dedf8f --- /dev/null +++ b/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + org.openemu.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.18 + NSPrincipalClass + OEGameCoreController + OEGameCoreClass + OdysseyGameCore + OEGameCorePlayerCount + 1 + OEProjectURL + http://sourceforge.net/projects/o2em/ + OESystemIdentifiers + + openemu.system.odyssey2 + + SUEnableAutomaticChecks + 1 + SUFeedURL + https://raw.github.com/OpenEmu/OpenEmu-Update/master/vecxgl_appcast.xml + + diff --git a/O2EM.xcodeproj/TemplateIcon.icns b/O2EM.xcodeproj/TemplateIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..62cb7015e09d6ea3e65d7f7949c4c07f9246a908 GIT binary patch literal 52318 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 WhsmLR^b3` +#import + +@class OERingBuffer; + +OE_EXPORTED_CLASS +@interface OdysseyGameCore : OEGameCore +@end diff --git a/OdysseyGameCore.m b/OdysseyGameCore.m new file mode 100644 index 0000000..21bd071 --- /dev/null +++ b/OdysseyGameCore.m @@ -0,0 +1,630 @@ +/* + Copyright (c) 2014, OpenEmu Team + + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the OpenEmu Team nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "OdysseyGameCore.h" +#import "OEOdyssey2SystemResponderClient.h" + +#import +#import +#include + +#include "crc32.h" +#include "audio.h" +#include "vmachine.h" +#include "config.h" +#include "vdc.h" +#include "cpu.h" +#include "debug.h" +#include "keyboard.h" +#include "voice.h" +#include "vpp.h" + +#include "wrapalleg.h" + +#include "score.h" + +#include "libretro.h" + +@interface OdysseyGameCore () +{ + NSDictionary *virtualPhysicalKeyMap; +} +@end + +//uint16_t mbmp[EMUWIDTH * EMUHEIGHT]; +//unsigned short int mbmp[TEX_WIDTH * TEX_HEIGHT]; +uint16_t mbmp[TEX_WIDTH * TEX_HEIGHT]; +//short signed int SNDBUF[1024*2]; +uint8_t soundBuffer[1056]; +int SND; +int RLOOP=0; +int joystick_data[2][5]={{0,0,0,0,0},{0,0,0,0,0}}; + +void update_joy(void){ +} + +int contax, o2flag, g74flag, c52flag, jopflag, helpflag; + +unsigned long crcx = ~0; + +static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC], +biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC], +odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC], bios_l[MAXC], +file_v[MAXC],scorefile[MAXC], statefile[MAXC], path2[MAXC]; + +static long filesize(FILE *stream){ + long curpos, length; + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + fseek(stream, curpos, SEEK_SET); + return length; +} + +static void load_bios(const char *biosname){ + FILE *fn; + static char s[MAXC+10]; + unsigned long crc; + int i; + + if ((biosname[strlen(biosname)-1]=='/') || + (biosname[strlen(biosname)-1]=='\\') || + (biosname[strlen(biosname)-1]==':')) { + strcpy(s,biosname); + strcat(s,odyssey2); + fn = fopen(s,"rb"); + + if (!fn) { + strcpy(s,biosname); + strcat(s,odyssey2); + fn = fopen(s,"rb"); + } + } else { + + strcpy(s,biosname); + fn = fopen(biosname,"rb"); + } + + if (!fn) { + fprintf(stderr,"Error loading bios ROM (%s)\n",s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0],1024,1,fn) != 1) { + fprintf(stderr,"Error loading bios ROM %s\n",odyssey2); + exit(EXIT_FAILURE); + } + + strcpy(s,biosname); + fn = fopen(biosname,"rb"); + if (!fn) { + fprintf(stderr,"Error loading bios ROM (%s)\n",s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0],1024,1,fn) != 1) { + fprintf(stderr,"Error loading bios ROM %s\n",odyssey2); + exit(EXIT_FAILURE); + } + fclose(fn); + for (i=1; i<8; i++) memcpy(rom_table[i],rom_table[0],1024); + crc = crc32_buf(rom_table[0],1024); + if (crc==0x8016A315) { + printf("Odyssey2 bios ROM loaded\n"); + app_data.vpp = 0; + app_data.bios = ROM_O2; + } else if (crc==0xE20A9F41) { + printf("Videopac+ G7400 bios ROM loaded\n"); + app_data.vpp = 1; + app_data.bios = ROM_G7400; + } else if (crc==0xA318E8D6) { + if (!((!o2flag)&&(c52flag))) printf("C52 bios ROM loaded\n"); else printf("Ok\n"); + app_data.vpp = 0; + app_data.bios = ROM_C52; + + } else if (crc==0x11647CA5) { + if (g74flag) printf("Jopac bios ROM loaded\n"); else printf(" Ok\n"); + app_data.vpp = 1; + app_data.bios = ROM_JOPAC; + } else { + printf("Bios ROM loaded (unknown version)\n"); + app_data.vpp = 0; + app_data.bios = ROM_UNKNOWN; + } +} + +static void load_cart(const char *file){ + FILE *fn; + long l; + int i, nb; + + app_data.crc = crc32_file(file); + if (app_data.crc == 0xAFB23F89) app_data.exrom = 1; /* Musician */ + if (app_data.crc == 0x3BFEF56B) app_data.exrom = 1; /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) app_data.exrom = 1; /* Four in 1 Row! (french) */ + + if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) && (!app_data.debug)) { + fprintf(stderr,"Error: file %s is an incomplete ROM dump\n",file_v); + exit(EXIT_FAILURE); + } + + fn=fopen(file,"rb"); + if (!fn) { + fprintf(stderr,"Error loading %s\n",file_v); + exit(EXIT_FAILURE); + } + printf("Loading: \"%s\" Size: ",file_v); + l = filesize(fn); + + if ((l % 1024) != 0) { + fprintf(stderr,"Error: file %s is an invalid ROM dump\n",file_v); + exit(EXIT_FAILURE); + } + + /* special MegaCART design by Soeren Gust */ + if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144) || (l == 524288) || (l == 1048576)) { + app_data.megaxrom = 1; + app_data.bank = 1; + megarom = malloc(1048576); + if (megarom == NULL) { + fprintf(stderr, "Out of memory loading %s\n", file); + exit(EXIT_FAILURE); + } + if (fread(megarom, l, 1, fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + + /* mirror shorter files into full megabyte */ + if (l < 65536) memcpy(megarom+32768,megarom,32768); + if (l < 131072) memcpy(megarom+65536,megarom,65536); + if (l < 262144) memcpy(megarom+131072,megarom,131072); + if (l < 524288) memcpy(megarom+262144,megarom,262144); + if (l < 1048576) memcpy(megarom+524288,megarom,524288); + /* start in bank 0xff */ + memcpy(&rom_table[0][1024], megarom + 4096*255 + 1024, 3072); + printf("MegaCart %ldK", l / 1024); + nb = 1; + } else if (((l % 3072) == 0)) + { + app_data.three_k = 1; + nb = l/3072; + + for (i=nb-1; i>=0; i--) { + if (fread(&rom_table[i][1024],3072,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + } + printf("%dK",nb*3); + + } else { + + nb = l/2048; + + if ((nb == 2) && (app_data.exrom)) { + + if (fread(&extROM[0], 1024,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + if (fread(&rom_table[0][1024],3072,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + printf("3K EXROM"); + + } else { + + for (i=nb-1; i>=0; i--) { + if (fread(&rom_table[i][1024],2048,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + memcpy(&rom_table[i][3072],&rom_table[i][2048],1024); /* simulate missing A10 */ + } + printf("%dK",nb*2); + + } + } + fclose(fn); + rom = rom_table[0]; + if (nb==1) + app_data.bank = 1; + else if (nb==2) + app_data.bank = app_data.exrom ? 1 : 2; + else if (nb==4) + app_data.bank = 3; + else + app_data.bank = 4; + + if ((rom_table[nb-1][1024+12]=='O') && (rom_table[nb-1][1024+13]=='P') && (rom_table[nb-1][1024+14]=='N') && (rom_table[nb-1][1024+15]=='B')) app_data.openb=1; + + printf(" CRC: %08lX\n",app_data.crc); +} + +//int suck_bios() +//{ +// int i; +// for (i=0; i +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */ +#define bool unsigned char +#define true 1 +#define false 0 +#else +#include +#endif +#endif + +// Used for checking API/ABI mismatches that can break libretro implementations. +// It is not incremented for compatible changes to the API. +#define RETRO_API_VERSION 1 + +// +// Libretros fundamental device abstractions. +///////// +// +// Libretros input system consists of some standardized device types such as a joypad (with/without analog), +// mouse, keyboard, lightgun and a pointer. The functionality of these devices are fixed, and individual cores map +// their own concept of a controller to libretros abstractions. +// This makes it possible for frontends to map the abstract types to a real input device, +// and not having to worry about binding input correctly to arbitrary controller layouts. + + +#define RETRO_DEVICE_TYPE_SHIFT 8 +#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) +#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) + +// Input disabled. +#define RETRO_DEVICE_NONE 0 + +// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller, +// but with additional L2/R2/L3/R3 buttons, similar to a PS1 DualShock. +#define RETRO_DEVICE_JOYPAD 1 + +// The mouse is a simple mouse, similar to Super Nintendo's mouse. +// X and Y coordinates are reported relatively to last poll (poll callback). +// It is up to the libretro implementation to keep track of where the mouse pointer is supposed to be on the screen. +// The frontend must make sure not to interfere with its own hardware mouse pointer. +#define RETRO_DEVICE_MOUSE 2 + +// KEYBOARD device lets one poll for raw key pressed. +// It is poll based, so input callback will return with the current pressed state. +// For event/text based keyboard input, see RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. +#define RETRO_DEVICE_KEYBOARD 3 + +// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse. +#define RETRO_DEVICE_LIGHTGUN 4 + +// The ANALOG device is an extension to JOYPAD (RetroPad). +// Similar to DualShock it adds two analog sticks. +// This is treated as a separate device type as it returns values in the full analog range +// of [-0x8000, 0x7fff]. Positive X axis is right. Positive Y axis is down. +// Only use ANALOG type when polling for analog values of the axes. +#define RETRO_DEVICE_ANALOG 5 + +// Abstracts the concept of a pointing mechanism, e.g. touch. +// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed. +// For a touch centric device, coordinates reported are the coordinates of the press. +// +// Coordinates in X and Y are reported as: +// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, +// and 0x7fff corresponds to the far right/bottom of the screen. +// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor. +// The frontend is free to scale/resize this screen as it sees fit, however, +// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc. +// +// To check if the pointer coordinates are valid (e.g. a touch display actually being touched), +// PRESSED returns 1 or 0. +// If using a mouse on a desktop, PRESSED will usually correspond to the left mouse button, but this is a frontend decision. +// PRESSED will only return 1 if the pointer is inside the game screen. +// +// For multi-touch, the index variable can be used to successively query more presses. +// If index = 0 returns true for _PRESSED, coordinates can be extracted +// with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with index = 1, and so on. +// Eventually _PRESSED will return false for an index. No further presses are registered at this point. +#define RETRO_DEVICE_POINTER 6 + +// Buttons for the RetroPad (JOYPAD). +// The placement of these is equivalent to placements on the Super Nintendo controller. +// L2/R2/L3/R3 buttons correspond to the PS1 DualShock. +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 +#define RETRO_DEVICE_ID_JOYPAD_L2 12 +#define RETRO_DEVICE_ID_JOYPAD_R2 13 +#define RETRO_DEVICE_ID_JOYPAD_L3 14 +#define RETRO_DEVICE_ID_JOYPAD_R3 15 + +// Index / Id values for ANALOG device. +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 + +// Id values for MOUSE. +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 +#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 +#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 + +// Id values for LIGHTGUN types. +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +// Id values for POINTER. +#define RETRO_DEVICE_ID_POINTER_X 0 +#define RETRO_DEVICE_ID_POINTER_Y 1 +#define RETRO_DEVICE_ID_POINTER_PRESSED 2 + +// Returned from retro_get_region(). +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +// Id values for LANGUAGE +enum retro_language +{ + RETRO_LANGUAGE_ENGLISH = 0, + RETRO_LANGUAGE_JAPANESE = 1, + RETRO_LANGUAGE_FRENCH = 2, + RETRO_LANGUAGE_SPANISH = 3, + RETRO_LANGUAGE_GERMAN = 4, + RETRO_LANGUAGE_ITALIAN = 5, + RETRO_LANGUAGE_DUTCH = 6, + RETRO_LANGUAGE_PORTUGUESE = 7, + RETRO_LANGUAGE_RUSSIAN = 8, + RETRO_LANGUAGE_KOREAN = 9, + RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, + RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, + RETRO_LANGUAGE_LAST, + + RETRO_LANGUAGE_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) +}; + +// Passed to retro_get_memory_data/size(). +// If the memory type doesn't apply to the implementation NULL/0 can be returned. +#define RETRO_MEMORY_MASK 0xff + +// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery. +// If save game data is too complex for a single memory buffer, +// the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment callback can be used. +#define RETRO_MEMORY_SAVE_RAM 0 + +// Some games have a built-in clock to keep track of time. +// This memory is usually just a couple of bytes to keep track of time. +#define RETRO_MEMORY_RTC 1 + +// System ram lets a frontend peek into a game systems main RAM. +#define RETRO_MEMORY_SYSTEM_RAM 2 + +// Video ram lets a frontend peek into a game systems video RAM (VRAM). +#define RETRO_MEMORY_VIDEO_RAM 3 + +// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. +enum retro_key +{ + RETROK_UNKNOWN = 0, + RETROK_FIRST = 0, + RETROK_BACKSPACE = 8, + RETROK_TAB = 9, + RETROK_CLEAR = 12, + RETROK_RETURN = 13, + RETROK_PAUSE = 19, + RETROK_ESCAPE = 27, + RETROK_SPACE = 32, + RETROK_EXCLAIM = 33, + RETROK_QUOTEDBL = 34, + RETROK_HASH = 35, + RETROK_DOLLAR = 36, + RETROK_AMPERSAND = 38, + RETROK_QUOTE = 39, + RETROK_LEFTPAREN = 40, + RETROK_RIGHTPAREN = 41, + RETROK_ASTERISK = 42, + RETROK_PLUS = 43, + RETROK_COMMA = 44, + RETROK_MINUS = 45, + RETROK_PERIOD = 46, + RETROK_SLASH = 47, + RETROK_0 = 48, + RETROK_1 = 49, + RETROK_2 = 50, + RETROK_3 = 51, + RETROK_4 = 52, + RETROK_5 = 53, + RETROK_6 = 54, + RETROK_7 = 55, + RETROK_8 = 56, + RETROK_9 = 57, + RETROK_COLON = 58, + RETROK_SEMICOLON = 59, + RETROK_LESS = 60, + RETROK_EQUALS = 61, + RETROK_GREATER = 62, + RETROK_QUESTION = 63, + RETROK_AT = 64, + RETROK_LEFTBRACKET = 91, + RETROK_BACKSLASH = 92, + RETROK_RIGHTBRACKET = 93, + RETROK_CARET = 94, + RETROK_UNDERSCORE = 95, + RETROK_BACKQUOTE = 96, + RETROK_a = 97, + RETROK_b = 98, + RETROK_c = 99, + RETROK_d = 100, + RETROK_e = 101, + RETROK_f = 102, + RETROK_g = 103, + RETROK_h = 104, + RETROK_i = 105, + RETROK_j = 106, + RETROK_k = 107, + RETROK_l = 108, + RETROK_m = 109, + RETROK_n = 110, + RETROK_o = 111, + RETROK_p = 112, + RETROK_q = 113, + RETROK_r = 114, + RETROK_s = 115, + RETROK_t = 116, + RETROK_u = 117, + RETROK_v = 118, + RETROK_w = 119, + RETROK_x = 120, + RETROK_y = 121, + RETROK_z = 122, + RETROK_DELETE = 127, + + RETROK_KP0 = 256, + RETROK_KP1 = 257, + RETROK_KP2 = 258, + RETROK_KP3 = 259, + RETROK_KP4 = 260, + RETROK_KP5 = 261, + RETROK_KP6 = 262, + RETROK_KP7 = 263, + RETROK_KP8 = 264, + RETROK_KP9 = 265, + RETROK_KP_PERIOD = 266, + RETROK_KP_DIVIDE = 267, + RETROK_KP_MULTIPLY = 268, + RETROK_KP_MINUS = 269, + RETROK_KP_PLUS = 270, + RETROK_KP_ENTER = 271, + RETROK_KP_EQUALS = 272, + + RETROK_UP = 273, + RETROK_DOWN = 274, + RETROK_RIGHT = 275, + RETROK_LEFT = 276, + RETROK_INSERT = 277, + RETROK_HOME = 278, + RETROK_END = 279, + RETROK_PAGEUP = 280, + RETROK_PAGEDOWN = 281, + + RETROK_F1 = 282, + RETROK_F2 = 283, + RETROK_F3 = 284, + RETROK_F4 = 285, + RETROK_F5 = 286, + RETROK_F6 = 287, + RETROK_F7 = 288, + RETROK_F8 = 289, + RETROK_F9 = 290, + RETROK_F10 = 291, + RETROK_F11 = 292, + RETROK_F12 = 293, + RETROK_F13 = 294, + RETROK_F14 = 295, + RETROK_F15 = 296, + + RETROK_NUMLOCK = 300, + RETROK_CAPSLOCK = 301, + RETROK_SCROLLOCK = 302, + RETROK_RSHIFT = 303, + RETROK_LSHIFT = 304, + RETROK_RCTRL = 305, + RETROK_LCTRL = 306, + RETROK_RALT = 307, + RETROK_LALT = 308, + RETROK_RMETA = 309, + RETROK_LMETA = 310, + RETROK_LSUPER = 311, + RETROK_RSUPER = 312, + RETROK_MODE = 313, + RETROK_COMPOSE = 314, + + RETROK_HELP = 315, + RETROK_PRINT = 316, + RETROK_SYSREQ = 317, + RETROK_BREAK = 318, + RETROK_MENU = 319, + RETROK_POWER = 320, + RETROK_EURO = 321, + RETROK_UNDO = 322, + + RETROK_LAST, + + RETROK_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) +}; + +enum retro_mod +{ + RETROKMOD_NONE = 0x0000, + + RETROKMOD_SHIFT = 0x01, + RETROKMOD_CTRL = 0x02, + RETROKMOD_ALT = 0x04, + RETROKMOD_META = 0x08, + + RETROKMOD_NUMLOCK = 0x10, + RETROKMOD_CAPSLOCK = 0x20, + RETROKMOD_SCROLLOCK = 0x40, + + RETROKMOD_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) +}; + +// If set, this call is not part of the public libretro API yet. It can change or be removed at any time. +#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 +// Environment callback to be used internally in frontend. +#define RETRO_ENVIRONMENT_PRIVATE 0x20000 + +// Environment commands. +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- + // Sets screen rotation of graphics. + // Is only implemented if rotation can be accelerated by hardware. + // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees + // counter-clockwise respectively. + // +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. + // +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- + // Boolean value whether or not frontend supports frame duping, + // passing NULL to video frame callback. + // +// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash. +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- + // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + // Should not be used for trivial messages, which should simply be logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a fallback, stderr). +#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) -- + // Requests the frontend to shutdown. + // Should only be used if game has a specific + // way to shutdown the game from a menu item or similar. + // +#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 + // const unsigned * -- + // Gives a hint to the frontend how demanding this implementation + // is on a system. E.g. reporting a level of 2 means + // this implementation should run decently on all frontends + // of level 2 and up. + // + // It can be used by the frontend to potentially warn + // about too demanding implementations. + // + // The levels are "floating". + // + // This function can be called on a per-game basis, + // as certain games an implementation can play might be + // particularly demanding. + // If called, it should be called in retro_load_game(). + // +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + // const char ** -- + // Returns the "system" directory of the frontend. + // This directory can be used to store system specific content such as BIOSes, configuration data, etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + // + // NOTE: Some cores used this folder also for "save" data such as memory cards, etc, for lack of a better place to put it. + // This is now discouraged, and if possible, cores should try to use the new GET_SAVE_DIRECTORY. + // +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + // const enum retro_pixel_format * -- + // Sets the internal pixel format used by the implementation. + // The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. + // This pixel format however, is deprecated (see enum retro_pixel_format). + // If the call returns false, the frontend does not support this pixel format. + // This function should be called inside retro_load_game() or retro_get_system_av_info(). + // +#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 + // const struct retro_input_descriptor * -- + // Sets an array of retro_input_descriptors. + // It is up to the frontend to present this in a usable way. + // The array is terminated by retro_input_descriptor::description being set to NULL. + // This function can be called at any time, but it is recommended to call it as early as possible. +#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 + // const struct retro_keyboard_callback * -- + // Sets a callback function used to notify core about keyboard events. + // +#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 + // const struct retro_disk_control_callback * -- + // Sets an interface which frontend can use to eject and insert disk images. + // This is used for games which consist of multiple images and must be manually + // swapped out by the user (e.g. PSX). +#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 + // struct retro_hw_render_callback * -- + // Sets an interface to let a libretro core render with hardware acceleration. + // Should be called in retro_load_game(). + // If successful, libretro cores will be able to render to a frontend-provided framebuffer. + // The size of this framebuffer will be at least as large as max_width/max_height provided in get_av_info(). + // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t. +#define RETRO_ENVIRONMENT_GET_VARIABLE 15 + // struct retro_variable * -- + // Interface to acquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // 'key' should be set to a key which has already been set by SET_VARIABLES. + // 'data' will be set to a value or NULL. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 16 + // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // This allows the frontend to present these variables to a user dynamically. + // This should be called as early as possible (ideally in retro_set_environment). + // + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::key should be namespaced to not collide with other implementations' keys. E.g. A core called 'foo' should use keys named as 'foo_option'. + // retro_variable::value should contain a human readable description of the key as well as a '|' delimited list of expected values. + // The number of possible options should be very limited, i.e. it should be feasible to cycle through options without a keyboard. + // First entry should be treated as a default. + // + // Example entry: + // { "foo_option", "Speed hack coprocessor X; false|true" } + // + // Text before first ';' is description. This ';' must be followed by a space, and followed by a list of possible values split up with '|'. + // Only strings are operated on. The possible values will generally be displayed and stored as-is by the frontend. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 + // bool * -- + // Result is set to true if some variables are updated by + // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + // Variables should be queried with GET_VARIABLE. + // +#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 + // const bool * -- + // If true, the libretro implementation supports calls to retro_load_game() with NULL as argument. + // Used by cores which can run without particular game data. + // This should be called within retro_set_environment() only. + // +#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 + // const char ** -- + // Retrieves the absolute path from where this libretro implementation was loaded. + // NULL is returned if the libretro was loaded statically (i.e. linked statically to frontend), or if the path cannot be determined. + // Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can be loaded without ugly hacks. + // + // +// Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. It was not used by any known core at the time, +// and was removed from the API. +#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 + // const struct retro_audio_callback * -- + // Sets an interface which is used to notify a libretro core about audio being available for writing. + // The callback can be called from any thread, so a core using this must have a thread safe audio implementation. + // It is intended for games where audio and video are completely asynchronous and audio can be generated on the fly. + // This interface is not recommended for use with emulators which have highly synchronous audio. + // + // The callback only notifies about writability; the libretro core still has to call the normal audio callbacks + // to write audio. The audio callbacks must be called from within the notification callback. + // The amount of audio data to write is up to the implementation. + // Generally, the audio callback will be called continously in a loop. + // + // Due to thread safety guarantees and lack of sync between audio and video, a frontend + // can selectively disallow this interface based on internal configuration. A core using + // this interface must also implement the "normal" audio interface. + // + // A libretro core using SET_AUDIO_CALLBACK should also make use of SET_FRAME_TIME_CALLBACK. +#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 + // const struct retro_frame_time_callback * -- + // Lets the core know how much time has passed since last invocation of retro_run(). + // The frontend can tamper with the timing to fake fast-forward, slow-motion, frame stepping, etc. + // In this case the delta time will use the reference value in frame_time_callback.. + // +#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 + // struct retro_rumble_interface * -- + // Gets an interface which is used by a libretro core to set state of rumble motors in controllers. + // A strong and weak motor is supported, and they can be controlled indepedently. + // +#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 + // uint64_t * -- + // Gets a bitmask telling which device type are expected to be handled properly in a call to retro_input_state_t. + // Devices which are not handled or recognized always return 0 in retro_input_state_t. + // Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). + // Should only be called in retro_run(). + // +#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_sensor_interface * -- + // Gets access to the sensor interface. + // The purpose of this interface is to allow + // setting state related to sensors such as polling rate, enabling/disable it entirely, etc. + // Reading sensor state is done via the normal input_state_callback API. + // +#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_camera_callback * -- + // Gets an interface to a video camera driver. + // A libretro core can use this interface to get access to a video camera. + // New video frames are delivered in a callback in same thread as retro_run(). + // + // GET_CAMERA_INTERFACE should be called in retro_load_game(). + // + // Depending on the camera implementation used, camera frames will be delivered as a raw framebuffer, + // or as an OpenGL texture directly. + // + // The core has to tell the frontend here which types of buffers can be handled properly. + // An OpenGL texture can only be handled when using a libretro GL core (SET_HW_RENDER). + // It is recommended to use a libretro GL core when using camera interface. + // + // The camera is not started automatically. The retrieved start/stop functions must be used to explicitly + // start and stop the camera driver. + // +#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 + // struct retro_log_callback * -- + // Gets an interface for logging. This is useful for logging in a cross-platform way + // as certain platforms cannot use use stderr for logging. It also allows the frontend to + // show logging information in a more suitable way. + // If this interface is not used, libretro cores should log to stderr as desired. +#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 + // struct retro_perf_callback * -- + // Gets an interface for performance counters. This is useful for performance logging in a + // cross-platform way and for detecting architecture-specific features, such as SIMD support. +#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 + // struct retro_location_callback * -- + // Gets access to the location interface. + // The purpose of this interface is to be able to retrieve location-based information from the host device, + // such as current latitude / longitude. + // +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 + // const char ** -- + // Returns the "content" directory of the frontend. + // This directory can be used to store specific assets that the core relies upon, such as art assets, + // input data, etc etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + // +#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 + // const char ** -- + // Returns the "save" directory of the frontend. + // This directory can be used to store SRAM, memory cards, high scores, etc, if the libretro core + // cannot use the regular memory interface (retro_get_memory_data()). + // + // NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before. + // They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible. + // The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path. + // +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + // const struct retro_system_av_info * -- + // Sets a new av_info structure. This can only be called from within retro_run(). + // This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, sampling rate, etc. + // Calling this can require a full reinitialization of video/audio drivers in the frontend, + // so it is important to call it very sparingly, and usually only with the users explicit consent. + // An eventual driver reinitialize will happen so that video and audio callbacks + // happening after this call within the same retro_run() call will target the newly initialized driver. + // + // This callback makes it possible to support configurable resolutions in games, which can be useful to + // avoid setting the "worst case" in max_width/max_height. + // + // ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's + // expected to be a temporary change, for the reasons of possible driver reinitialization. + // This call is not a free pass for not trying to provide correct values in retro_get_system_av_info(). If you need to change things like aspect ratio or nominal width/height, use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant of SET_SYSTEM_AV_INFO. + // + // If this returns false, the frontend does not acknowledge a changed av_info struct. +#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 + // const struct retro_get_proc_address_interface * -- + // Allows a libretro core to announce support for the get_proc_address() interface. + // This interface allows for a standard way to extend libretro where use of environment calls are too indirect, + // e.g. for cases where the frontend wants to call directly into the core. + // + // If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK **MUST** be called from within retro_set_environment(). + // +#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 + // const struct retro_subsystem_info * -- + // This environment call introduces the concept of libretro "subsystems". + // A subsystem is a variant of a libretro core which supports different kinds of games. + // The purpose of this is to support e.g. emulators which might have special needs, e.g. Super Nintendos Super GameBoy, Sufami Turbo. + // It can also be used to pick among subsystems in an explicit way if the libretro implementation is a multi-system emulator itself. + // + // Loading a game via a subsystem is done with retro_load_game_special(), + // and this environment call allows a libretro core to expose which subsystems are supported for use with retro_load_game_special(). + // A core passes an array of retro_game_special_info which is terminated with a zeroed out retro_game_special_info struct. + // + // If a core wants to use this functionality, SET_SUBSYSTEM_INFO **MUST** be called from within retro_set_environment(). + // +#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 + // const struct retro_controller_info * -- + // This environment call lets a libretro core tell the frontend which + // controller types are recognized in calls to retro_set_controller_port_device(). + // + // Some emulators such as Super Nintendo + // support multiple lightgun types which must be specifically selected from. + // It is therefore sometimes necessary for a frontend to be able to tell + // the core about a special kind of input device which is not covered by the + // libretro input API. + // + // In order for a frontend to understand the workings of an input device, + // it must be a specialized type + // of the generic device types already defined in the libretro API. + // + // Which devices are supported can vary per input port. + // The core must pass an array of const struct retro_controller_info which is terminated with + // a blanked out struct. Each element of the struct corresponds to an ascending port index to retro_set_controller_port_device(). + // Even if special device types are set in the libretro core, libretro should only poll input based on the base input device types. +#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // const struct retro_memory_map * -- + // This environment call lets a libretro core tell the frontend about the memory maps this + // core emulates. This can be used to implement, for example, cheats in a core-agnostic way. + // + // Should only be used by emulators; it doesn't make much sense for anything else. + // It is recommended to expose all relevant pointers through retro_get_memory_* as well. + // + // Can be called from retro_init and retro_load_game. + // +#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 + // const struct retro_game_geometry * -- + // This environment call is similar to SET_SYSTEM_AV_INFO for changing video parameters, + // but provides a guarantee that drivers will not be reinitialized. + // This can only be called from within retro_run(). + // + // The purpose of this call is to allow a core to alter nominal width/heights as well as aspect ratios on-the-fly, + // which can be useful for some emulators to change in run-time. + // + // max_width/max_height arguments are ignored and cannot be changed + // with this call as this could potentially require a reinitialization or a non-constant time operation. + // If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. + // + // A frontend must guarantee that this environment call completes in constant time. + +#define RETRO_ENVIRONMENT_GET_USERNAME 38 + // const char ** + // Returns the specified username of the frontend, if specified by the user. + // This username can be used as a nickname for a core that has online facilities or any other mode where personalization // of the user is desirable. + // The returned value can be NULL. + // If this environ callback is used by a core that requires a valid username, a default username should be specified + // by the core. + // + // +#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 + // const unsigned * -- + // Returns the specified language of the frontend, if specified by the user. + // It can be used by the core for localization purposes. + // + +#define RETRO_MEMDESC_CONST (1 << 0) // The frontend will never change this memory area once retro_load_game has returned. +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) // The memory area contains big endian data. Default is little endian. +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) // All memory access in this area is aligned to their own size, or 2, whichever is smaller. +#define RETRO_MEMDESC_ALIGN_4 (2 << 16) +#define RETRO_MEMDESC_ALIGN_8 (3 << 16) +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) // All memory in this region is accessed at least 2 bytes at the time. +#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) +#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) +struct retro_memory_descriptor +{ + uint64_t flags; + + // Pointer to the start of the relevant ROM or RAM chip. + // It's strongly recommended to use 'offset' if possible, rather than doing math on the pointer. + // If the same byte is mapped my multiple descriptors, their descriptors must have the same pointer. + // If 'start' does not point to the first byte in the pointer, put the difference in 'offset' instead. + // May be NULL if there's nothing usable here (e.g. hardware registers and open bus). No flags should be set if the pointer is NULL. + // It's recommended to minimize the number of descriptors if possible, but not mandatory. + void *ptr; + size_t offset; + + // This is the location in the emulated address space where the mapping starts. + size_t start; + + // Which bits must be same as in 'start' for this mapping to apply. + // The first memory descriptor to claim a certain byte is the one that applies. + // A bit which is set in 'start' must also be set in this. + // Can be zero, in which case each byte is assumed mapped exactly once. In this case, 'len' must be a power of two. + size_t select; + + // If this is nonzero, the set bits are assumed not connected to the memory chip's address pins. + size_t disconnect; + + // This one tells the size of the current memory area. + // If, after start+disconnect are applied, the address is higher than this, the highest bit of the address is cleared. + // If the address is still too high, the next highest bit is cleared. + // Can be zero, in which case it's assumed to be infinite (as limited by 'select' and 'disconnect'). + size_t len; + + // To go from emulated address to physical address, the following order applies: + // Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. + + // The address space name must consist of only a-zA-Z0-9_-, should be as short as feasible (maximum length is 8 plus the NUL), + // and may not be any other address space plus one or more 0-9A-F at the end. + // However, multiple memory descriptors for the same address space is allowed, and the address + // space name can be empty. NULL is treated as empty. + // Address space names are case sensitive, but avoid lowercase if possible. + // The same pointer may exist in multiple address spaces. + // Examples: + // blank+blank - valid (multiple things may be mapped in the same namespace) + // 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) + // 'A'+'B' - valid (neither is a prefix of each other) + // 'S'+blank - valid ('S' is not in 0-9A-F) + // 'a'+blank - valid ('a' is not in 0-9A-F) + // 'a'+'A' - valid (neither is a prefix of each other) + // 'AR'+blank - valid ('R' is not in 0-9A-F) + // 'ARB'+blank - valid (the B can't be part of the address either, because there is no namespace 'AR') + // blank+'B' - not valid, because it's ambigous which address space B1234 would refer to. + // The length can't be used for that purpose; the frontend may want to append arbitrary data to an address, without a separator. + const char *addrspace; +}; +// The frontend may use the largest value of 'start'+'select' in a certain namespace to infer the size of the address space. +// If the address space is larger than that, a mapping with .ptr=NULL should be at the end of the array, with .select set to all ones for as long as the address space is big. +// Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): +// SNES WRAM: +// .start=0x7E0000, .len=0x20000 +// (Note that this must be mapped before the ROM in most cases; some of the ROM mappers try to claim $7E0000, or at least $7E8000.) +// SNES SPC700 RAM: +// .addrspace="S", .len=0x10000 +// SNES WRAM mirrors: +// .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 +// .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 +// SNES WRAM mirrors, alternate equivalent descriptor: +// .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF +// (Various similar constructions can be created by combining parts of the above two.) +// SNES LoROM (512KB, mirrored a couple of times): +// .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 +// .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 +// SNES HiROM (4MB): +// .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 +// .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 +// SNES ExHiROM (8MB): +// .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 +// .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 +// .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 +// .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 +// Clarify the size of the address space: +// .ptr=NULL, .select=0xFFFFFF +// .len can be implied by .select in many of them, but was included for clarity. + +struct retro_memory_map +{ + const struct retro_memory_descriptor *descriptors; + unsigned num_descriptors; +}; + +struct retro_controller_description +{ + // Human-readable description of the controller. Even if using a generic input device type, this can be + // set to the particular device type the core uses. + const char *desc; + + // Device type passed to retro_set_controller_port_device(). If the device type is a sub-class of a generic input device type, + // use the RETRO_DEVICE_SUBCLASS macro to create an ID. E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). + unsigned id; +}; + +struct retro_controller_info +{ + const struct retro_controller_description *types; + unsigned num_types; +}; + +struct retro_subsystem_memory_info +{ + const char *extension; // The extension associated with a memory type, e.g. "psram". + unsigned type; // The memory type for retro_get_memory(). This should be at least 0x100 to avoid conflict with standardized libretro memory types. +}; + +struct retro_subsystem_rom_info +{ + const char *desc; // Describes what the content is (SGB bios, GB rom, etc). + const char *valid_extensions; // Same definition as retro_get_system_info(). + bool need_fullpath; // Same definition as retro_get_system_info(). + bool block_extract; // Same definition as retro_get_system_info(). + bool required; // This is set if the content is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed. + + // Content can have multiple associated persistent memory types (retro_get_memory()). + const struct retro_subsystem_memory_info *memory; + unsigned num_memory; +}; + +struct retro_subsystem_info +{ + const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy" + // A computer friendly short string identifier for the subsystem type. + // This name must be [a-z]. + // E.g. if desc is "Super GameBoy", this can be "sgb". + // This identifier can be used for command-line interfaces, etc. + const char *ident; + + // Infos for each content file. The first entry is assumed to be the "most significant" content for frontend purposes. + // E.g. with Super GameBoy, the first content should be the GameBoy ROM, as it is the most "significant" content to a user. + // If a frontend creates new file paths based on the content used (e.g. savestates), it should use the path for the first ROM to do so. + const struct retro_subsystem_rom_info *roms; + + unsigned num_roms; // Number of content files associated with a subsystem. + unsigned id; // The type passed to retro_load_game_special(). +}; + +typedef void (*retro_proc_address_t)(void); +// libretro API extension functions: +// (None here so far). +////// + +// Get a symbol from a libretro core. +// Cores should only return symbols which are actual extensions to the libretro API. +// Frontends should not use this to obtain symbols to standard libretro entry points (static linking or dlsym). +// The symbol name must be equal to the function name, e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". +// The returned function pointer must be cast to the corresponding type. +typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym); +struct retro_get_proc_address_interface +{ + retro_get_proc_address_t get_proc_address; +}; + +enum retro_log_level +{ + RETRO_LOG_DEBUG = 0, + RETRO_LOG_INFO, + RETRO_LOG_WARN, + RETRO_LOG_ERROR, + + RETRO_LOG_DUMMY = INT_MAX +}; + +// Logging function. Takes log level argument as well. +typedef void (*retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); + +struct retro_log_callback +{ + retro_log_printf_t log; +}; + +// Performance related functions +// +// ID values for SIMD CPU features +#define RETRO_SIMD_SSE (1 << 0) +#define RETRO_SIMD_SSE2 (1 << 1) +#define RETRO_SIMD_VMX (1 << 2) +#define RETRO_SIMD_VMX128 (1 << 3) +#define RETRO_SIMD_AVX (1 << 4) +#define RETRO_SIMD_NEON (1 << 5) +#define RETRO_SIMD_SSE3 (1 << 6) +#define RETRO_SIMD_SSSE3 (1 << 7) +#define RETRO_SIMD_MMX (1 << 8) +#define RETRO_SIMD_MMXEXT (1 << 9) +#define RETRO_SIMD_SSE4 (1 << 10) +#define RETRO_SIMD_SSE42 (1 << 11) +#define RETRO_SIMD_AVX2 (1 << 12) +#define RETRO_SIMD_VFPU (1 << 13) +#define RETRO_SIMD_PS (1 << 14) + +typedef uint64_t retro_perf_tick_t; +typedef int64_t retro_time_t; + +struct retro_perf_counter +{ + const char *ident; + retro_perf_tick_t start; + retro_perf_tick_t total; + retro_perf_tick_t call_cnt; + + bool registered; +}; + +// Returns current time in microseconds. Tries to use the most accurate timer available. +typedef retro_time_t (*retro_perf_get_time_usec_t)(void); +// A simple counter. Usually nanoseconds, but can also be CPU cycles. +// Can be used directly if desired (when creating a more sophisticated performance counter system). +typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void); +// Returns a bit-mask of detected CPU features (RETRO_SIMD_*). +typedef uint64_t (*retro_get_cpu_features_t)(void); +// Asks frontend to log and/or display the state of performance counters. +// Performance counters can always be poked into manually as well. +typedef void (*retro_perf_log_t)(void); +// Register a performance counter. +// ident field must be set with a discrete value and other values in retro_perf_counter must be 0. +// Registering can be called multiple times. To avoid calling to frontend redundantly, you can check registered field first. +typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter); +// Starts and stops a registered counter. +typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); +typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); + +// For convenience it can be useful to wrap register, start and stop in macros. +// E.g.: +// #ifdef LOG_PERFORMANCE +// #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) +// #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) +// #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) +// #else +// ... Blank macros ... +// #endif +// These can then be used mid-functions around code snippets. +// +// extern struct retro_perf_callback perf_cb; // Somewhere in the core. +// +// void do_some_heavy_work(void) +// { +// RETRO_PERFORMANCE_INIT(cb, work_1); +// RETRO_PERFORMANCE_START(cb, work_1); +// heavy_work_1(); +// RETRO_PERFORMANCE_STOP(cb, work_1); +// +// RETRO_PERFORMANCE_INIT(cb, work_2); +// RETRO_PERFORMANCE_START(cb, work_2); +// heavy_work_2(); +// RETRO_PERFORMANCE_STOP(cb, work_2); +// } +// +// void retro_deinit(void) +// { +// perf_cb.perf_log(); // Log all perf counters here for example. +// } + +struct retro_perf_callback +{ + retro_perf_get_time_usec_t get_time_usec; + retro_get_cpu_features_t get_cpu_features; + + retro_perf_get_counter_t get_perf_counter; + retro_perf_register_t perf_register; + retro_perf_start_t perf_start; + retro_perf_stop_t perf_stop; + retro_perf_log_t perf_log; +}; + +// FIXME: Document the sensor API and work out behavior. +// It will be marked as experimental until then. +enum retro_sensor_action +{ + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, + + RETRO_SENSOR_DUMMY = INT_MAX +}; + +// Id values for SENSOR types. +#define RETRO_SENSOR_ACCELEROMETER_X 0 +#define RETRO_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_SENSOR_ACCELEROMETER_Z 2 + +typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); +typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id); +struct retro_sensor_interface +{ + retro_set_sensor_state_t set_sensor_state; + retro_sensor_get_input_t get_sensor_input; +}; +//// + +enum retro_camera_buffer +{ + RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, + + RETRO_CAMERA_BUFFER_DUMMY = INT_MAX +}; + +// Starts the camera driver. Can only be called in retro_run(). +typedef bool (*retro_camera_start_t)(void); +// Stops the camera driver. Can only be called in retro_run(). +typedef void (*retro_camera_stop_t)(void); +// Callback which signals when the camera driver is initialized and/or deinitialized. +// retro_camera_start_t can be called in initialized callback. +typedef void (*retro_camera_lifetime_status_t)(void); +// A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. +// Width, height and pitch are similar to retro_video_refresh_t. +// First pixel is top-left origin. +typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); +// A callback for when OpenGL textures are used. +// +// texture_id is a texture owned by camera driver. +// Its state or content should be considered immutable, except for things like texture filtering and clamping. +// +// texture_target is the texture target for the GL texture. +// These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly more depending on extensions. +// +// affine points to a packed 3x3 column-major matrix used to apply an affine transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) +// After transform, normalized texture coord (0, 0) should be bottom-left and (1, 1) should be top-right (or (width, height) for RECTANGLE). +// +// GL-specific typedefs are avoided here to avoid relying on gl.h in the API definition. +typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); +struct retro_camera_callback +{ + uint64_t caps; // Set by libretro core. Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + + unsigned width; // Desired resolution for camera. Is only used as a hint. + unsigned height; + retro_camera_start_t start; // Set by frontend. + retro_camera_stop_t stop; // Set by frontend. + + retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; // Set by libretro core if raw framebuffer callbacks will be used. + retro_camera_frame_opengl_texture_t frame_opengl_texture; // Set by libretro core if OpenGL texture callbacks will be used. + + // Set by libretro core. Called after camera driver is initialized and ready to be started. + // Can be NULL, in which this callback is not called. + retro_camera_lifetime_status_t initialized; + + // Set by libretro core. Called right before camera driver is deinitialized. + // Can be NULL, in which this callback is not called. + retro_camera_lifetime_status_t deinitialized; +}; + +// Sets the interval of time and/or distance at which to update/poll location-based data. +// To ensure compatibility with all location-based implementations, values for both +// interval_ms and interval_distance should be provided. +// interval_ms is the interval expressed in milliseconds. +// interval_distance is the distance interval expressed in meters. +typedef void (*retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance); + +// Start location services. The device will start listening for changes to the +// current location at regular intervals (which are defined with retro_location_set_interval_t). +typedef bool (*retro_location_start_t)(void); + +// Stop location services. The device will stop listening for changes to the current +// location. +typedef void (*retro_location_stop_t)(void); + +// Get the position of the current location. Will set parameters to 0 if no new +// location update has happened since the last time. +typedef bool (*retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy, + double *vert_accuracy); + +// Callback which signals when the location driver is initialized and/or deinitialized. +// retro_location_start_t can be called in initialized callback. +typedef void (*retro_location_lifetime_status_t)(void); + +struct retro_location_callback +{ + retro_location_start_t start; + retro_location_stop_t stop; + retro_location_get_position_t get_position; + retro_location_set_interval_t set_interval; + + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; +}; + +enum retro_rumble_effect +{ + RETRO_RUMBLE_STRONG = 0, + RETRO_RUMBLE_WEAK = 1, + + RETRO_RUMBLE_DUMMY = INT_MAX +}; + +// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently, +// and setting e.g. strong rumble does not override weak rumble. +// Strength has a range of [0, 0xffff]. +// +// Returns true if rumble state request was honored. Calling this before first retro_run() is likely to return false. +typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); +struct retro_rumble_interface +{ + retro_set_rumble_state_t set_rumble_state; +}; + +// Notifies libretro that audio data should be written. +typedef void (*retro_audio_callback_t)(void); + +// True: Audio driver in frontend is active, and callback is expected to be called regularily. +// False: Audio driver in frontend is paused or inactive. Audio callback will not be called until set_state has been called with true. +// Initial state is false (inactive). +typedef void (*retro_audio_set_state_callback_t)(bool enabled); +struct retro_audio_callback +{ + retro_audio_callback_t callback; + retro_audio_set_state_callback_t set_state; +}; + +// Notifies a libretro core of time spent since last invocation of retro_run() in microseconds. +// It will be called right before retro_run() every frame. +// The frontend can tamper with timing to support cases like fast-forward, slow-motion and framestepping. +// In those scenarios the reference frame time value will be used. +typedef int64_t retro_usec_t; +typedef void (*retro_frame_time_callback_t)(retro_usec_t usec); +struct retro_frame_time_callback +{ + retro_frame_time_callback_t callback; + retro_usec_t reference; // Represents the time of one frame. It is computed as 1000000 / fps, but the implementation will resolve the rounding to ensure that framestepping, etc is exact. +}; + +// Pass this to retro_video_refresh_t if rendering to hardware. +// Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) + +// Invalidates the current HW context. +// Any GL state is lost, and must not be deinitialized explicitly. If explicit deinitialization is desired by the libretro core, +// it should implement context_destroy callback. +// If called, all GPU resources must be reinitialized. +// Usually called when frontend reinits video driver. +// Also called first time video driver is initialized, allowing libretro core to initialize resources. +typedef void (*retro_hw_context_reset_t)(void); +// Gets current framebuffer which is to be rendered to. Could change every frame potentially. +typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); + +// Get a symbol from HW context. +typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); + +enum retro_hw_context_type +{ + RETRO_HW_CONTEXT_NONE = 0, + RETRO_HW_CONTEXT_OPENGL = 1, // OpenGL 2.x. Driver can choose to use latest compatibility context. + RETRO_HW_CONTEXT_OPENGLES2 = 2, // GLES 2.0 + RETRO_HW_CONTEXT_OPENGL_CORE = 3, // Modern desktop core GL context. Use version_major/version_minor fields to set GL version. + RETRO_HW_CONTEXT_OPENGLES3 = 4, // GLES 3.0 + RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, // GLES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, use the corresponding enums directly. + + RETRO_HW_CONTEXT_DUMMY = INT_MAX +}; + +struct retro_hw_render_callback +{ + enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. + + // Called when a context has been created or when it has been reset. + // An OpenGL context is only valid after context_reset() has been called. + // + // When context_reset is called, OpenGL resources in the libretro implementation are guaranteed to be invalid. + // It is possible that context_reset is called multiple times during an application lifecycle. + // If context_reset is called without any notification (context_destroy), + // the OpenGL context was lost and resources should just be recreated + // without any attempt to "free" old resources. + retro_hw_context_reset_t context_reset; + + retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. + retro_hw_get_proc_address_t get_proc_address; // Set by frontend. + bool depth; // Set if render buffers should have depth component attached. + bool stencil; // Set if stencil buffers should be attached. + // If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored. + bool bottom_left_origin; // Use conventional bottom-left origin convention. Is false, standard libretro top-left origin semantics are used. + unsigned version_major; // Major version number for core GL context or GLES 3.1+. + unsigned version_minor; // Minor version number for core GL context or GLES 3.1+. + + bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc. + // The reset callback might still be called in extreme situations such as if the context is lost beyond recovery. + // For optimal stability, set this to false, and allow context to be reset at any time. + + retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed in a controlled way by the frontend. + // OpenGL resources can be deinitialized cleanly at this step. + // context_destroy can be set to NULL, in which resources will just be destroyed without any notification. + // + // Even when context_destroy is non-NULL, it is possible that context_reset is called without any destroy notification. + // This happens if context is lost by external factors (such as notified by GL_ARB_robustness). + // In this case, the context is assumed to be already dead, + // and the libretro implementation must not try to free any OpenGL resources in the subsequent context_reset. + + bool debug_context; // Creates a debug context. +}; + +// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events. +// down is set if the key is being pressed, or false if it is being released. +// keycode is the RETROK value of the char. +// character is the text character of the pressed key. (UTF-32). +// key_modifiers is a set of RETROKMOD values or'ed together. +// +// The pressed/keycode state can be indepedent of the character. +// It is also possible that multiple characters are generated from a single keypress. +// Keycode events should be treated separately from character events. +// However, when possible, the frontend should try to synchronize these. +// If only a character is posted, keycode should be RETROK_UNKNOWN. +// Similarily if only a keycode event is generated with no corresponding character, character should be 0. +typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); + +struct retro_keyboard_callback +{ + retro_keyboard_event_t callback; +}; + +// Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. +// Should be set for implementations which can swap out multiple disk images in runtime. +// If the implementation can do this automatically, it should strive to do so. +// However, there are cases where the user must manually do so. +// +// Overview: To swap a disk image, eject the disk image with set_eject_state(true). +// Set the disk index with set_image_index(index). Insert the disk again with set_eject_state(false). + +// If ejected is true, "ejects" the virtual disk tray. +// When ejected, the disk image index can be set. +typedef bool (*retro_set_eject_state_t)(bool ejected); +// Gets current eject state. The initial state is 'not ejected'. +typedef bool (*retro_get_eject_state_t)(void); +// Gets current disk index. First disk is index 0. +// If return value is >= get_num_images(), no disk is currently inserted. +typedef unsigned (*retro_get_image_index_t)(void); +// Sets image index. Can only be called when disk is ejected. +// The implementation supports setting "no disk" by using an index >= get_num_images(). +typedef bool (*retro_set_image_index_t)(unsigned index); +// Gets total number of images which are available to use. +typedef unsigned (*retro_get_num_images_t)(void); +// +// Replaces the disk image associated with index. +// Arguments to pass in info have same requirements as retro_load_game(). +// Virtual disk tray must be ejected when calling this. +// Replacing a disk image with info = NULL will remove the disk image from the internal list. +// As a result, calls to get_image_index() can change. +// +// E.g. replace_image_index(1, NULL), and previous get_image_index() returned 4 before. +// Index 1 will be removed, and the new index is 3. +struct retro_game_info; +typedef bool (*retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); +// Adds a new valid index (get_num_images()) to the internal disk list. +// This will increment subsequent return values from get_num_images() by 1. +// This image index cannot be used until a disk image has been set with replace_image_index. +typedef bool (*retro_add_image_index_t)(void); + +struct retro_disk_control_callback +{ + retro_set_eject_state_t set_eject_state; + retro_get_eject_state_t get_eject_state; + + retro_get_image_index_t get_image_index; + retro_set_image_index_t set_image_index; + retro_get_num_images_t get_num_images; + + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; +}; + +enum retro_pixel_format +{ + // 0RGB1555, native endian. 0 bit must be set to 0. + // This pixel format is default for compatibility concerns only. + // If a 15/16-bit pixel format is desired, consider using RGB565. + RETRO_PIXEL_FORMAT_0RGB1555 = 0, + + // XRGB8888, native endian. X bits are ignored. + RETRO_PIXEL_FORMAT_XRGB8888 = 1, + + // RGB565, native endian. This pixel format is the recommended format to use if a 15/16-bit format is desired + // as it is the pixel format that is typically available on a wide range of low-power devices. + // It is also natively supported in APIs like OpenGL ES. + RETRO_PIXEL_FORMAT_RGB565 = 2, + + // Ensure sizeof() == sizeof(int). + RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX +}; + +struct retro_message +{ + const char *msg; // Message to be displayed. + unsigned frames; // Duration in frames of message. +}; + +// Describes how the libretro implementation maps a libretro input bind +// to its internal input system through a human readable string. +// This string can be used to better let a user configure input. +struct retro_input_descriptor +{ + // Associates given parameters with a description. + unsigned port; + unsigned device; + unsigned index; + unsigned id; + + const char *description; // Human readable description for parameters. + // The pointer must remain valid until retro_unload_game() is called. +}; + +struct retro_system_info +{ + // All pointers are owned by libretro implementation, and pointers must remain valid until retro_deinit() is called. + + const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc. + const char *library_version; // Descriptive version of core. + + const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe. + // I.e. "bin|rom|iso". + // Typically used for a GUI to filter out extensions. + + bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path. + // ::data and ::size are both invalid. + // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid. + // This is typically set to true for libretro implementations that must load from file. + // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc. + + bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real content. + // Necessary for certain libretro implementations that load games from zipped archives. +}; + +struct retro_game_geometry +{ + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. + + float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, + // an aspect ratio of base_width / base_height is assumed. + // A frontend could override this setting if desired. +}; + +struct retro_system_timing +{ + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + // If NULL, obtains the complete environment string if more complex parsing is necessary. + // The environment string is formatted as key-value pairs delimited by semicolons as so: + // "key1=value1;key2=value2;..." + const char *value; // Value to be obtained. If key does not exist, it is set to NULL. +}; + +struct retro_game_info +{ + const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. + // May be NULL if rom was loaded from stdin or similar. + // retro_system_info::need_fullpath guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. +}; + +// Callbacks +// +// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. +typedef bool (*retro_environment_t)(unsigned cmd, void *data); + +// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). +// Width and height specify dimensions of buffer. +// Pitch specifices length in bytes between two lines in buffer. +// For performance reasons, it is highly recommended to have a frame that is packed in memory, i.e. pitch == width * byte_per_pixel. +// Certain graphic APIs, such as OpenGL ES, do not like textures that are not packed in memory. +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); + +// Renders a single audio frame. Should only be used if implementation generates a single sample at a time. +// Format is signed 16-bit native endian. +typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved. +// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. +// Only one of the audio callbacks must ever be used. +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); + +// Polls input. +typedef void (*retro_input_poll_t)(void); +// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK. +// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device() +// will still use the higher level RETRO_DEVICE_JOYPAD to request input. +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); + +// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init(). +// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made. +void retro_set_environment(retro_environment_t); +void retro_set_video_refresh(retro_video_refresh_t); +void retro_set_audio_sample(retro_audio_sample_t); +void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +void retro_set_input_poll(retro_input_poll_t); +void retro_set_input_state(retro_input_state_t); + +// Library global initialization/deinitialization. +void retro_init(void); +void retro_deinit(void); + +// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised. +unsigned retro_api_version(void); + +// Gets statically known system info. Pointers provided in *info must be statically allocated. +// Can be called at any time, even before retro_init(). +void retro_get_system_info(struct retro_system_info *info); + +// Gets information about system audio/video timings and geometry. +// Can be called only after retro_load_game() has successfully completed. +// NOTE: The implementation of this function might not initialize every variable if needed. +// E.g. geom.aspect_ratio might not be initialized if core doesn't desire a particular aspect ratio. +void retro_get_system_av_info(struct retro_system_av_info *info); + +// Sets device to be used for player 'port'. +// By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all available ports. +// Setting a particular device type is not a guarantee that libretro cores will only poll input based on that particular device type. It is only a hint to the libretro core when a core cannot automatically detect the appropriate input device type on its own. It is also relevant when a core can change its behavior depending on device type. +void retro_set_controller_port_device(unsigned port, unsigned device); + +// Resets the current game. +void retro_reset(void); + +// Runs the game for one video frame. +// During retro_run(), input_poll callback must be called at least once. +// +// If a frame is not rendered for reasons where a game "dropped" a frame, +// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true. +// In this case, the video callback can take a NULL argument for data. +void retro_run(void); + +// Returns the amount of data the implementation requires to serialize internal state (save states). +// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to +// ensure that the frontend can allocate a save state buffer once. +size_t retro_serialize_size(void); + +// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise. +bool retro_serialize(void *data, size_t size); +bool retro_unserialize(const void *data, size_t size); + +void retro_cheat_reset(void); +void retro_cheat_set(unsigned index, bool enabled, const char *code); + +// Loads a game. +bool retro_load_game(const struct retro_game_info *game); + +// Loads a "special" kind of game. Should not be used except in extreme cases. +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +// Unloads a currently loaded game. +void retro_unload_game(void); + +// Gets region of game. +unsigned retro_get_region(void); + +// Gets region of memory. +void *retro_get_memory_data(unsigned id); +size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/allegrowrapper/wrapalleg.c b/allegrowrapper/wrapalleg.c new file mode 100755 index 0000000..68cd53c --- /dev/null +++ b/allegrowrapper/wrapalleg.c @@ -0,0 +1,207 @@ + +#include "wrapalleg.h" + +#include +#include +#include +#define abs(a) miabs(a) + +int miabs(int a){ + if((a)<0)a=-a; + return a; +} + +void upcase(char *p) +{ + while(*p != '\0') + { + if(*p >= 97 && *p <= 122) + *p -= 32; + ++p; + } +} +void downcase(char *p) +{ + while(*p != '\0') + { + if(*p >= 97-32 && *p <= 122-32) + *p += 32; + ++p; + } +} + +void clear(BITMAP *buff){ + + memset(&buff->line,0,buff->w*buff->h); +} + +BITMAP *create_bitmap(int w,int h){ + + BITMAP *buff; + + buff = malloc(sizeof (BITMAP)); + buff->line=malloc(1*w*h); + + buff->w=w; + buff->h=h; + buff->pitch=w; + buff->depth=1; + + return buff; +} + +int destroy_bitmap(BITMAP *buff){ + + if (buff->line) { + free(buff->line); + } + free(buff); + + return 0; +} + + +void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color){ + +// int i,j,idx; +// +// int dx= abs(x2-x); +// int dy= abs(y2-y); +// int V_WIDTH = buff->w; +// unsigned char *buffer=buff->line[0]; +// +// for(i=x;iw; +// unsigned char *buffer=buff->line[0]; +// +// for(i=x;iw; +// unsigned char *buffer=buff->line[0]; +// +// for(i=x;iw; +// unsigned char *buffer=buff->line[0]; +// +// for(j=y;jw; +// unsigned char *buffer=buff->line[0]; +// +// dx = x2 - x1; +// dy = y2 - y1; +// sx = (dx >= 0) ? 1 : -1; +// sy = (dy >= 0) ? 1 : -1; +// +// if (dx==0) { +// if (dy>0) { +// DrawVline(buff, x1, y1,0, dy, color); +// return; +// +// } else if (dy<0) { +// DrawVline(buff, x1, y2,0, -dy, color); +// return; +// +// } else { +// idx=x1+y1*V_WIDTH; +// buffer[idx]=color; +// return ; +// } +// } +// if (dy == 0) { +// if (dx>0) { +// DrawHline(buff, x1, y1, dx, 0, color); +// return; +// +// } else if (dx<0) { +// DrawHline(buff, x2, y1, -dx,0, color); +// return; +// } +// } +// +// dx = sx * dx + 1; +// dy = sy * dy + 1; +// +// pixx = 1; +// pixy = V_WIDTH; +// +// pixx *= sx; +// pixy *= sy; +// +// if (dx < dy) { +// swaptmp = dx; +// dx = dy; +// dy = swaptmp; +// swaptmp = pixx; +// pixx = pixy; +// pixy = swaptmp; +// } +// +// x = 0; +// y = 0; +// +// idx=x1+y1*V_WIDTH; +// +// for (; x < dx; x++, idx +=pixx) { +// buffer[idx]=color; +// y += dy; +// if (y >= dx) { +// y -= dx; +// idx += pixy; +// } +// } + +} diff --git a/allegrowrapper/wrapalleg.h b/allegrowrapper/wrapalleg.h new file mode 100755 index 0000000..76258a5 --- /dev/null +++ b/allegrowrapper/wrapalleg.h @@ -0,0 +1,56 @@ + +#ifndef WRAP_H +#define WRAP_H 1 + +#include +#define INLINE static inline +#define rest(a) usleep(a) +#define strupr upcase +#define strlwr downcase +#define keypressed() 0 +#define poll_keyboard() +#define yield_timeslice() + +typedef struct +{ + unsigned char *line; + int w; + int h; + int pitch; + int depth; + +}BITMAP; + +typedef struct +{ + unsigned char r; + unsigned char g; + unsigned char b; +}APALETTE; + + +BITMAP *create_bitmap(int w,int h); +int destroy_bitmap(BITMAP *buff); +void line(BITMAP *buff,int x1,int y1,int x2,int y2,unsigned char color); +void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color); +void rectfill(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color); +void upcase(char *p); +void downcase(char *p); + +extern unsigned char key[256*2]; + +extern void update_joy(void); + +#define INLINE static inline + +#define EMUWIDTH 340 +#define EMUHEIGHT 250 + +#define TEX_WIDTH 400 +#define TEX_HEIGHT 300 + +#define RGB565(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b)) + + +#endif + diff --git a/clean/src/CHANGELOG b/clean/src/CHANGELOG new file mode 100755 index 0000000..71dbb60 --- /dev/null +++ b/clean/src/CHANGELOG @@ -0,0 +1,316 @@ +v1.18: 01/15/2007 + + - added the option -biosdir to define bios directory path + - added the option -romdir to define rom directory path + - added the option -help to help display + - directory search fix : When you don't have the "roms/" and/or "bios/" + directory, the program will dump core (by Walter de Jong). + - O2Launcher works now, o2em ignore roms and bios path if o2Launcher + is running. + - quad display fix: changed the way quad chars are drawn, fixes problems + in KTAA as well as score display in Black Hole and Red Baron (Soeren Gust) + - support for Soerens MegaCART bank switching (Information about + how to use this will be included in the next verison of Soerens + Bios-Documentation) (Soeren Gust) + - new feature in debugger: savevpp to make an uncompressed dump of the VPP + screen and slide data (Soeren Gust) + - dis48: fix to work under linux again (Soeren Gust) + - init_sound volume is not set to maximum (By Gunter Wambaugh) + - added makefile and options for freeBSD (By Gunter Wambaugh) + - Other minor fixes. + + + all the next changes were implemented by Manopac: + + - added the option -s0 to redefine the system keys (see o2em.txt for usage) + - bugfix: highscore-file is only written if scoretype is set + - changed Default Stick 1 key from right to "L" to enable Fire and + movement at the same time + - two joysticks can be used now: first stick in command-line is mapped to joystick 1, + second to joystick 2 (compatible to old command line options) + - changes in debugger: status of registers is now displayed after instructions + are executed + - new features in debugger: savedatah and savedatab to save data from memory + as sourcecode ("db xxx") + - changed Default Stick 1 key from right to "L" to enable Fire + and movement at the same time + - two joysticks can be used now: first stick in command-line is mapped to + joystick 1, second to joystick 2 (compatible to old command line options) + - changes in debugger: status of registers is now displayed after + instructions are executed + - new features in debugger: savedatah and savedatab to save data from memory + as sourcecode ("db xxx") + - removed the limit that KTAA was the only 3K enabled rom (every + rom divideable by 3K is allowed now) + - dis48: added option -bios to disassemble bios (start at address 0) + - dis48: empty line after each page + - new feature to save the highscore in games (F6 to set in game) + - new feature to save/load state (F2/F3) (with command line option savefile) + - new features in debugger: savevdc and saveext to save data from Extram and VDC + - new feature in debugger: viewsprite + - new feature in debugger: bp (breakpoint) - o2em runs with output until + breakpoint is reached (bpc to clear) + - new feature in debugger: so (step over) - runs to next instruction in memory + - more explicit register display (P1 & PSW) + - fixed the "double size sprites are shifted only 1 instead of 2 pixles" bug + - new features in debugger (load / save file, change values in memory, + assemble to memory) + +v1.17: 05/01/2005 + + - BIOS identified by CRC, to activate a specific BIOS type: -o2rom, or + -g7400, or -c52, or -jopac. The old form can be used. See O2EM.txt for more. + + - Automatic identification of BIOS VP+ when the selected game is only VP+. + + - Creation of the standard directories (ROMS, BIOS, VOICE) when uncompressing + O2EM archive. + + - ATLANTIS, FROGGER, COMANDO NOTURNO and CATCH THE BALL now work without + graphic bugs. This correction is based on a specific patch for each game. + Thanks Rafael Cardoso for reports these bugs. + + +V1.16: 12/28/2004 + + - Fixed a slowdown in Pick Axe Pete (based on a patch by Arlindo de + Oliveira). + + - Reverted back to the old palette for O2 games, while using the new + palette for Videpac Plus games (selected based on bios version in use). + + +V1.15: 12/12/2004 + + - Added support for 12kb and 16kb games. Trans American Rally+ works now. + + - Added fixes to the VP+ gfx emulation made by Soeren Gust. Flashpoint + works properly now. + + - Fixed a bug in the Windows-specific emulation timing code that caused + the emulator to crash when run on a Windows machine which was on for a + few days without a reboot. + + - Fixed a bug in the emulation of the DAA instruction, which caused bugs + in the score of several games (Le Tresor Englouti, Cosmic Conflict, etc.). + + - Fixed instruction timings (patch by Soeren) + + - Modified the palette to use values calculated from the Videopac+ RGB + encoder specs by René van den Enden, instead of guessed values. + + - Other minor fixes. + + + +V1.01: 10/23/2002 + + - Major speed optimization. + + - Implemented VDC <-> VP+ collision detection. + + - On the original machines it is possible to make all VDC + colors bright by clearing P17. This affects the background and + dark grid colors. Implemented. Now the Killer Bees! intro screen + works correctly. + + - Fixed the wrong color order when mixing between VP+ and VDC graphics. + Jopac Moto Crash now works. Fixed by Soeren Gust. + + - Now the VBLANK pulse is visible on the T1 input. This can be used + to differentiate between PAL and NTSC. + + - Other minor fixes. + + + +V1.00: 09/12/2002 + + - Implemented complete Videopac+ G7400 emulation. Implemented it from + scratch, based on the EF9340/41 datasheet (sent by Simon Scudder), on + the technical docs made by Soeren Gust and disassembling the VP+ bios. + You will need a Videopac+ bios image file in order to use this feature. + You can use the -bios option to select it, rename the file to o2rom.bin, + or select it in O2EM Launcher settings. Please note that a few O2 games + do not work with the VP+ bios, so most likely you will need both bios + versions to be able to run all the games. For copyright reasons these + files are not included with O2EM, but you can find them in the Internet. + + - Added a default configuration file. Now you can specify your preferred + options in a configuration file, instead of typing it every time you + execute the emulator. The command line options override the default + settings in the file. See O2EM.txt for more. + + - Extended the -s1 and -s2 switches to allow customizable keys with the + joystick emulation. Based on a patch written by Zimmerman that + implemented customizable keys it in a different way. See O2EM.txt for + more. + + - Added support to the Four in 1 Row game. + + - Added the -exrom switch to enable the use of a special ROM mapping mode. + See O2EM.txt for more. + + - Improved the sound with Frogger and Popeye. + + - Minor fixes. + + + +V0.90: 08/07/2002 + + - Fixed the color palette, based on screen shots from a real O2 console. + + - Fixed a bug in the sprite drawing priority. Now in several games the + sprites look better (Demon Attack, Turtles, Atlantis, Computer Golf, + Football, Helicopter Rescue, etc.). + + - Modified the emulation of sprites and characters in the border region of + the screen. Fixed the bug of character wrapping to the other side of the + screen and other problems (Atlantis and others). Now the main characters of + P.T.Barnum's Acrobats! do not fall from the edge of screen. + + - Fixed the audio pitch and implemented white noise emulation. Now + explosions sound much better! + + - Fixed a background line blinking problem that used to affect lots of + games. + + - Fixed the color bar at the left of the screen. + + - Enhanced the support for European/Pal games. Now several games look and + play better. Shark Hunter intro works correctly. Frogger and Depth Charge + are fully playable ! + + - Implemented an audio filter that accurately emulates the behavior of the + low-pass filter present in the audio output of the real console. The sound + is better now. (Enable it with -filter). + + - Fixed the screen size. Now you can see all the graphics in the game, + including the time in Labyrinth. + + - Implemented Dot Grid emulation. Now Marksman is playable. + + - Implemented a cached video emulation, to make it run faster with slow + machines / video cards. + + - Implemented screen shots (use the F8 key and the -scshot option) + + - Implemented the sprite shifted/smooth modes. Now the main character of + Q*bert looks hi-res. + + - Several minor fixes. + + + The following fixes were made by Soeren Gust: + + + - Implemented the missing JNI instruction. + + - Implemented the 1kb data ROM / 3kb program ROM addressing mode used by + Musician. + + - Fixed the height of the grid lines. + + - Added support for 3Kb per bank + + + +V0.87: 06/21/2002 + + - Fixed a collision bug introduced with version 0.86. + Now Cosmic Conflict runs again. Thanks to Dan Boris for reporting + this bug. + + - Implemented the option to set the O2 bios file name/dir, as + requested by my friend Heitor, to enable him to support it with his + nice O2EMLauncher frontend for O2EM 0.8x, as requested by its users. + Get O2EMLauncher here: http://www.odyssey.com.br/o2emlauncher/ + + + +Version 0.86: + + - Fixed a bug in the drawing of quad characters. Now you can play + Q*Bert and Nimble Numbers Ned. Some other games will also have + improved graphics or text (Popeye, Super Cobra, etc.) . + + - Fixed another bug in the collision detection. Now Demon Attack + works correctly. + + + +Version 0.85: + + - Fixed the collision detection. Now you can play Killer Bees! + + - Implemented partial support to mid-screen changes to the VDC + registers without interrupts. Now several games look better, and some + that didn't work can be played, including Power Lords and Super Cobra. + + - Fixed a bug in the video emulation that made some games like Turtles + and Shark Hunter appear with some strange static characters. + + + +Version 0.80: + +The following changes were already implemented by Daniel Boris in version +0.701. Implemented them again in the sources based on version v0.65: + + - Fixed a bug in the CPU core related to the handling of branch + instructions near page boundaries. (Without it Sid the Spellbinder + crashed after the first level). + + - CPU core now jumps to the correct address on an external interrupt. + Killer Bees runs again. + + - Fixed shape of '$' character and added missing 64th character to + character set (ripped the correct character data from the v0.701 + executable file). + + - Fixed bug in drawing of bottom grid line. + + - Added Voice support. Re implemented it from scratch, based on O2 + technical specs released by Dan Boris and disassembling Smithereens + and Turtles (now it always work with Turtles). + +The following changes are new to version 0.80: + + - Updated the code to compile with Allegro 4.0.x and to work + without changes under Windows, Linux and DOS, with optimizations + for each. + + - Implemented the option of windowed or fullscreen video modes, + with scaling, centering and optional 50% scanlines. + + - Cleaned the code to make it more portable and maintainable. + + - Improved timing, using the most accurate way available for + each platform. + + - Fixed the keyboard scan code translation table. + + - Fixed and improved the built-in debugger. + + - Fixed the reset. It now works with Turtles. + + - Fixed joystick detection code. + + - Implemented variable speed control relative to original O2. + + - Implemented individual volume control for sounds and voice. + + - Implemented Pause/Information (F1). + + - Avoided collision of keyboard input with key joystick + emulation. Now Caps Lock enables/disables the W,D,S,A,Space keys + for keyboard input when they are used by joystick emulation. + Works well with games like K.C.'s Krazy Chase. + + - It now releases more CPU time to the system (if possible). + + - Other minor changes/fixes. + + + diff --git a/clean/src/COPYING b/clean/src/COPYING new file mode 100755 index 0000000..255c6f4 --- /dev/null +++ b/clean/src/COPYING @@ -0,0 +1,138 @@ + + The Clarified Artistic License + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Distribution fee" is a fee you charge for providing a copy + of this Package to another party. + + "Freely Available" means that no fee is charged for the right to + use the item, though there may be fees involved in handling the + item. It also means that recipients of the item may redistribute + it under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain, or those made Freely Available, or from +the Copyright Holder. A Package modified in such a way shall still be +considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major network + archive site allowing unrestricted access to them, or by allowing the + Copyright Holder to include your modifications in the Standard Version + of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) permit and encourge anyone who receives a copy of the modified Package + permission to make your modifications Freely Available + in some specific way. + + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) offer the machine-readable source of the Package, with your + modifications, by mail order. + +5. You may charge a distribution fee for any distribution of this Package. +If you offer support for this Package, you may charge any fee you choose +for that support. You may not charge a license fee for the right to use +this Package itself. You may distribute this Package in aggregate with +other (possibly commercial and possibly nonfree) programs as part of a +larger (possibly commercial and possibly nonfree) software distribution, +and charge license fees for other parts of that software distribution, +provided that you do not advertise this Package as a product of your own. +If the Package includes an interpreter, You may embed this Package's +interpreter within an executable of yours (by linking); this shall be +construed as a mere form of aggregation, provided that the complete +Standard Version of the interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of the Standard Version of the Package with a commercial +distribution is always permitted provided that the use of this Package +is embedded; that is, when no overt attempt is made to make this Package's +interfaces visible to the end user of the commercial distribution. +Such use shall not be construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + diff --git a/clean/src/Makefile b/clean/src/Makefile new file mode 100755 index 0000000..2314944 --- /dev/null +++ b/clean/src/Makefile @@ -0,0 +1,81 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer -I/usr/include +LFLAGS = -s +#LIBALLEG = /usr/lib/liballeg.so.4.2 -lalleg_unsharable +LIBS=`allegro-config --libs` +VERSION='1.18' +ARCH=`uname -i` + + +all: o2em dis48 + +clean: + rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o + + +o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBS) + +dis48: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48 + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h types.h + $(CC) $(CFLAGS) -c score.c -o score.o + +dist: all + mkdir -p o2em-$(VERSION) + mv o2em o2em-$(VERSION) + mv dis48 o2em-$(VERSION) + cp o2em.png o2em-$(VERSION) + cp COPYING o2em-$(VERSION) + cp README o2em-$(VERSION) + mv o2em-$(VERSION) o2em + tar czf o2em-$(VERSION)-$(ARCH).tar.gz o2em + rm -r o2em diff --git a/clean/src/Makefile.djgpp b/clean/src/Makefile.djgpp new file mode 100755 index 0000000..12c7e4a --- /dev/null +++ b/clean/src/Makefile.djgpp @@ -0,0 +1,71 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer +LFLAGS = -s +LIBALLEG = -lalleg + + +all: o2em.exe dis48.exe + +clean: + del *.o + + +o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG) + +dis48.exe: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h + $(CC) $(CFLAGS) -c score.c -o score.o + +o2em.res: o2em.rc o2em.ico + $(WINDRES) -O coff -o o2em.res -i o2em.rc + diff --git a/clean/src/Makefile.freebsd b/clean/src/Makefile.freebsd new file mode 100755 index 0000000..c47f8aa --- /dev/null +++ b/clean/src/Makefile.freebsd @@ -0,0 +1,68 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer -I${PREFIX}/include -DFREEBSD -DPREFIX=\"${PREFIX}\" +LFLAGS = -s +LIBALLEG = -L${PREFIX}/lib -lalleg -lalleg_unsharable + + +all: o2em dis48 + +clean: + rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o + + +o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG) + +dis48: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48 + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h types.h + $(CC) $(CFLAGS) -c score.c -o score.o + diff --git a/clean/src/Makefile.mingw b/clean/src/Makefile.mingw new file mode 100755 index 0000000..c05f50f --- /dev/null +++ b/clean/src/Makefile.mingw @@ -0,0 +1,72 @@ +CC = gcc +WINDRES = windres + +CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include +LFLAGS = -mno-cygwin -s +LIBALLEG = -L/usr/local/lib -lalleg + + +all: o2em.exe dis48.exe + +clean: + del -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res o2em.exe dis48.exe + + +o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG) + +dis48.exe: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h + $(CC) $(CFLAGS) -c score.c -o score.o + +o2em.res: o2em.rc o2em.ico + $(WINDRES) -O coff -o o2em.res -i o2em.rc + diff --git a/clean/src/Makefile.win b/clean/src/Makefile.win new file mode 100755 index 0000000..c0e5a23 --- /dev/null +++ b/clean/src/Makefile.win @@ -0,0 +1,35 @@ +# Project: Project1 +# Makefile created by Dev-C++ 4.9.9.1 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = ../OBJ/file_private.res +OBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES) +LINKOBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES) +LIBS = -L"C:/Dev-Cpp/lib" -L"C:/Dev-Cpp/lib" +INCS = -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include" +CXXINCS = -I"C:/Dev-Cpp/include/c++/3.3.1" -I"C:/Dev-Cpp/include/c++/3.3.1/mingw32" -I"C:/Dev-Cpp/include/c++/3.3.1/backward" -I"C:/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include" +BIN = file.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) + +.PHONY: all all-before all-after clean clean-custom + +all: all-before file.exe all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o "file.exe" $(LIBS) + +../OBJ/get_file.o: get_file.cpp + $(CPP) -c get_file.cpp -o ../OBJ/get_file.o $(CXXFLAGS) + +../OBJ/crc32.o: crc32.c + $(CPP) -c crc32.c -o ../OBJ/crc32.o $(CXXFLAGS) + +../OBJ/file_private.res: file_private.rc + $(WINDRES) -i file_private.rc --input-format=rc -o ../OBJ/file_private.res -O coff --include-dir C:/Dev-Cpp/Projetos/o2em-win diff --git a/clean/src/O2EM.ICO b/clean/src/O2EM.ICO new file mode 100755 index 0000000000000000000000000000000000000000..f867aace5da69bc5f51112fc8e3bfb24694f3bfb GIT binary patch literal 5694 zcmeI0L2kn^5Ci2~&pqS~d4_*xJud%JckRxF0OJ)3}d*7cf{+IkN z%{jlCTm034_NBAy$@zD@a?DQIPoF!#np^zUfcB-c>&f|5UUO^yj0W`YMrT@3pBZ&I z=fj~c=X^NS<(v+Cpu%`@wBX4K`J4~M#(^WjjJb3PpEa?XcCUC#M%sLMGY4s|)_ z!=ZOMo>!H9(JDs{4#lr399reb!J+t7g+r?xIXD!*s&HtPBL_FmuMLketvz?@$7m-z zt^NFFGHyri6SrAS> + + Developed by Daniel Boris, Andre de la Rocha and Arlindo Oliveira + + This package is released under the + Clarified Artistic License (see COPYING) + + Project Homepage + http://o2em.sourceforge.net + +--------------------------------------------------------------------------- + + +O2EM is an open source Odyssey2 / Videopac console emulator, created by +Daniel Boris in 1996. Since version 0.80 it has been developed by André de +la Rocha and since version 1.16 it has been developed by Arlindo M. de Oliveira. + +This release includes the source code for O2EM v1.18 and binaries for +Windows. The sources probably can also be compiled under other platforms +that support the Allegro game library. The binary version for Linux/X11 and +DOS continues available just until the version 1.16. + +With the Windows binary, the latest stable version of the Allegro DLL is also +included. To use the Linux version you must get the Allegro library for Linux +yourself and install it as root. The DOS version does not need additional +files. + +O2EM is a command line based program, but there are several Windows frontends +you can use. The "official" one is O2EM Launcher, created by Heitor +Barcellos. + +In order to build O2EM from its sources, you need either the MingW or Cygwin +packages on Windows, DJGPP on DOS and GCC on Linux. See the links below. + +The latest version of O2EM can be found at http://o2em.sourceforge.net If you +want to send bug reports, or be part of the O2EM development, go to the O2EM +project page at SourceForge : http://sourceforge.net/projects/o2em/ + + + +Useful links: + +Dan Boris' home page: http://www.atarihq.com/danb/ +Allegro library: http://alleg.sourceforge.net/ +MingW C/C++ compiler: http://sourceforge.net/projects/mingw/ +Soeren Gust page : http://soeren.informationstheater.de/ +Odyssey2 Home: http://www.classicgaming.com/o2home/ +Odysseymania the brazilian webpage : http://odysseymania.classicgaming.com.br +OdysseyBR Group: http://gamesource.groups.yahoo.com/group/OdysseyBR/ +Videopac Forum: http://www.videopac.org + +Acknowledgments: + + +We wish to thank the following people: + + Keita Iida (Keita/Pooka/Fygar) + for his enthusiasm, for the O2EM beta testing, and general encouragement. + + Marco Kerstens (MarcoK) + for providing Videopac schematics, and general support. + + Matthew Pritchard + for sending some official O2 programming documents. + + Bo Krogsgaard (Therion23) + for putting the idea of doing the emulator into my head to start with. + + Jason F. Gohlke + for providing valuable Voice tech info as well as the voice samples. + + Soeren Gust : For sending his patches to O2EM and for technical + information about the console. Part of his technical document was + used to implement VP+ emulation. + + René van den Enden : for providing information about several + unsupported games and other help. + + Simon Scudder : for sending technical information about the O2 + (including the datasheet of the VP+ gfx chipset), sampled sounds and + his nice O2 disassembler. + + Heitor Barcellos : for creating the O2EM Launcher frontend. + + Marcelo Ribeiro : for the icon used with the windows version of O2EM, + bug reports, and for information about O2 games. + + Rafael : for compiling a big list of bugs present in O2EM v0.87. + + Zimmerman : for sending his patch to add key customization, on which + v1.00 customization was based. + + Arlindo de Oliveira : for sending patches to fix bugs in O2EM and for + his interest in keeping the O2 emulation alive. + + The members of the OdysseyBR user group: for several bug reports, as + well for support in general. + +----------------------------------------------------------------------------- + +Building: + +o2em depends on Allegro, for Ubuntu / Debian, run: + +sudo apt-get install liballegro4-dev + +----------------------------------------------------------------------------- + +Quick Setup: + +To get O2EM up and running quickly follow these steps: + +1. Unzip the O2EM archive on your hard drive, that will create the necessary + standard directories: ROMS, BIOS and VOICE into the main directory O2EM118. +2. Download the bios ROM O2ROM.BIN (or G7400.BIN, or C52.BIN, or JOPAC.BIN) + and put it into BIOS directory. +3. Download one or more game ROMs, for example KCMUNCH.BIN for KC Munchkin and + put the ROM in ROMS directory. +4. From the O2EM118 directory type: o2em KCMUNCH.BIN to start the game.If wants + to play KC Munchkin with BIOS VP+, type: o2em KCMUNCH.BIN -g7400 + +--------------------------------------------------------------------------- +Setup: + + Before you can run O2EM you need a copy of the Odyssey2 or Videopac bios +ROM. For copyright reasons, this ROM image can not be included in this +archive. This ROM image is stored inside the 8048 processor and can be read +out with the appropriate equipment. The image should be 1024 bytes long and +should be in the BIOS directory into the main directory O2EM118. + + You will also need cartridge images, but again for copyright reasons +these can not be provided. PLEASE DO NOT E-mail us asking for ROM images! All +messages asking for ROM images will be promptly deleted. + + If you wish to use Voice emulation for games like KC's Krazy Chase. +Download the voice samples and unzip them into the VOICE directory +into the main directory O2EM118. There are two sets of voice samples, +mainsamp.zip which is the main voice samples and sidsamp.zip which are the +samples used by the game Sid the Spellbinder. You only need the Sid samples +if you want voice in that game. + +--------------------------------------------------------------------------- + + +Usage: + + +o2em [options] + + = file to load with extension + + +options: + +-help Help display + +-wsize=n Window size used by the emulator (1=original, 2=double size, etc.) + +-fullscreen Use full screen mode + +-scanlines Enable scanlines use by the video emulation. Scanlines are a + feature that makes your display look like a TV screen. + +-nosound Turn off sound emulation + +-novoice Turn off voice emulation + +-svolume=n Set sound volume (0-100) + +-vvolume=n Set voice volume (0-100) + +-debug Start the emulator in debug mode + +-speed=n Relative speed (100 = original speed) + +-nolimit Turn off speed limiter + +-bios=file Set the file name and directory to find the console + bios. By default it looks for a file named o2rom.bin. + You can use a bios file from an Odyssey2, Videopac or + Videopac+ console. If you want to run VP+ games (in + VP+ mode) then you need a VP+ bios. + +-romdir=path Set the directory to find the game rom. By default it + looks for path named .../roms + +-biosdir=path Set the directory to find the console bios. By default it + looks for path named .../bios + +-o2rom Start the emulator with Odyssey 2 bios (default for most games). + +-c52 Start the emulator with french Odyssey 2 bios. + +-g7400 Start the emulator with VP+ bios (default for detected VP+ only games). + +-jopac Start the emulator with french VP+ bios. + +-euro This option enables the use of European timing / 50Hz mode. + This option is usually not needed as most of the games that + really require this mode will be auto-detected. + +-filter Enable the low-pass audio filter. + +-scshot=file Set the screen shot file name or template. The screen shot + will be saved when you press the F8 key in the emulator. + The extension of the file you give will set the file type. + supported file types are bmp, pcx and tga. You can also give + a template to save several files, using the @ character. + Using an option like -scshot=dump@.bmp will save files with + names like dump00.bmp, dump01.bmp, etc. The pictures will + have a resolution of (320x240)*wsize. + +-exrom Enable the use of an alternative ROM mapping for 4Kb games, to + support some games that use a special 3kb program rom/1kb data + ROM mode. The only known that use it are Four in 1 Row and + Musician and both are detected by their CRC and set correctly. + So this option is to be used only with games that are currently + unknown to O2EM. Do not enable it as default, as it will make + all the 4kb games that do not use this special mode crash. + +-s0=QUIT,PAUSE,DEBUG,RESET,SCREENCAP,SAVE,LOAD,INJECT_HIGH + These option defines which keys are used for some of the system + keys, if you use this option, you have to enter all 8 keys, to + override the original keys (ESC,F1,F4,F5,F8,F2,F3,F6) + +-s1=mode/keys Define stick 1 mode/keys +-s2=mode/keys Define stick 2 mode/keys + + These options define how the console joysticks are emulated. + You can use a joystick connected to your computer or use + the keyboard. You can specify a mode number (compatible with + previous versions of O2EM) to disable the joystick emulation, + to select an actual joystick or to set a default keyboard + emulation mode : + 0=Disable, + 1=Default Right keys (arrows keys and right shift) + 2=Default Left keys (W,S,A,D,SPACE) + 3=Joystick + Example: -s1=1 -s2=3 + + You can also specify a list of 5 keyboard codes that will + be used to emulate the joystick, separated by comas + (without spaces), using this order : UP,DOWN,LEFT,RIGHT,FIRE. + The following codes are accepted (not case sensitive): + A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0_PAD,1_PAD,2_PAD,3_PAD,4_PAD,5_PAD,6_PAD,7_PAD,8_PAD,9_PAD, + TILDE, MINUS, EQUALS, BACKSPACE, TAB, OPENBRACE, CLOSEBRACE, + ENTER, COLON, QUOTE, BACKSLASH, BACKSLASH2, COMMA, STOP, + SLASH, SPACE, INSERT, DEL, HOME, END, PGUP, PGDN, LEFT, + RIGHT, UP, DOWN, SLASH_PAD, ASTERISK, MINUS_PAD, PLUS_PAD, + DEL_PAD, ENTER_PAD, PRTSCR, PAUSE, ABNT_C1, YEN, KANA, AT, + CIRCUMFLEX, COLON2, KANJI, LSHIFT, RSHIFT, LCONTROL, + RCONTROL, ALT, ALTGR, LWIN, RWIN, MENU, SCRLOCK, NUMLOCK + Example: -s1=y,h,g,j,lcontrol -s2=8_PAD,5_PAD,4_PAD,6_PAD,RCONTROL + +-scoreadr=address where the high-score is saved for specific rom +-scoretype=type how the high-score is saved for specific rom +-score=highscore default highscore on launch ("inject" with F6) +-scorefile=file file where the highscore is saved on exit + +-savefile=file filename for save/load state + + + + +---------------------------------------------------------------------------- + +Default configuration file: + +O2EM now can use a configuration file to set the default options, so you can +specify your preferred options in this file, instead of typing it every time +you execute the emulator. The command line options override the default +settings in the file. This file must be called o2em_def.cfg and be in the +same directory of O2EM118. This configuration file is a text file where you can +put the same options you would use when calling O2EM by the command line, but +each option must be in a different line and you should not precede it with +the - character. You can also put comment lines in the file, starting the +line with the # character. Example configuration file: + + # My config + wsize=3 + Euro + scanlines + filter + g7400 + s1=8_pad,5_pad,4_pad,6_pad,rcontrol + + +You disable any option set in this file when you call O2EM in the command +line, passing the =0 parameter to the option. For this example configuration, +you could disable the filter option set in the file putting -filter=0 when +you call O2EM. + + +---------------------------------------------------------------------------- + +Controls: + + Arrow keys + L = Default joystick 1 emulation + + W,D,S,A + Space = Default joystick 2 emulation + + ESC/F12 = Leave the emulator + + F1 = Pause/Information + + F2 = Save State-File + + F3 = Load State-File + + F4 = Enter debugger + + F5 = Reset emulator (same as pressing the reset on the O2 keyboard) + + F6 = Inject Highscore + + F8 = Make a screen shot + + Caps Lock = Enables/Disables the O2 keyboard input of the keys used by + joystick emulation + +---------------------------------------------------------------------------- + +Debugger: + +The emulator comes with a built in debugger that was used for development. +The debugger is not very polished and fairly incomplete but it can be useful +for single stepping through programs and watching their behavior. + +H = display help + +---------------------------------------------------------------------------- + + diff --git a/clean/src/audio.c b/clean/src/audio.c new file mode 100755 index 0000000..d1f2c27 --- /dev/null +++ b/clean/src/audio.c @@ -0,0 +1,188 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 audio emulation + */ + + +#include +#include +#include +#include "cpu.h" +#include "types.h" +#include "config.h" +#include "vmachine.h" +#include "audio.h" +#include "allegro.h" + +#define SAMPLE_RATE 44100 +#define PERIOD1 11 +#define PERIOD2 44 + +#define SOUND_BUFFER_LEN 1056 + +#define AUD_CTRL 0xAA +#define AUD_D0 0xA7 +#define AUD_D1 0xA8 +#define AUD_D2 0xA9 + + +int sound_IRQ; +static AUDIOSTREAM *stream=NULL; +FILE *sndlog=NULL; + +static double flt_a=0.0, flt_b=0.0; +static unsigned char flt_prv = 0; + + +static void filter(unsigned char *buf, unsigned long len); + + +void audio_process(unsigned char *buffer){ + unsigned long aud_data; + int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos; + + aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16)); + + intena = VDCwrite[0xA0] & 0x04; + + pnt = cnt = 0; + + noise = VDCwrite[AUD_CTRL] & 0x10; + enabled = VDCwrite[AUD_CTRL] & 0x80; + rndbit = (enabled && noise) ? (rand()%2) : 0; + + while (pnt < SOUND_BUFFER_LEN) { + pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1); + volume = AudioVector[pos] & 0x0F; + enabled = AudioVector[pos] & 0x80; + period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2; + re_circ = AudioVector[pos] & 0x40; + + buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0; + cnt++; + + if (cnt >= period) { + cnt=0; + aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1); + rndbit = (enabled && noise) ? (rand()%2) : 0; + + if (enabled && intena && (!sound_IRQ)) { + sound_IRQ = 1; + ext_IRQ(); + } + } + } + + if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN); +} + + +void update_audio(void) { + unsigned char *p; + if (app_data.sound_en) { + p = (unsigned char *)get_audio_stream_buffer(stream); + if (p) { + audio_process(p); + if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog); + free_audio_stream_buffer(stream); + } + } +} + + +void init_audio(void) { + int i; +#ifdef OPENEMU + sound_IRQ=0; + if ((app_data.sound_en) || (app_data.voice)) { + printf("Initializing sound system...\n"); + i = install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); + if (i != 0) { + printf(" ERROR: could not initialize sound card\n %s\n",allegro_error); + printf(" Sound system disabled\n"); + app_data.sound_en = 0; + app_data.voice = 0; + } + else { + if (digi_driver->name && (strlen(digi_driver->name)>0)){ + printf(" Sound system initialized ok\n"); + printf(" Sound driver [%s] detected\n",digi_driver->name); + set_volume(-1,-1); + init_sound_stream(); + } else { + printf(" ERROR: could not initialize sound card\n"); + printf(" Sound system disabled\n"); + app_data.sound_en = 0; + app_data.voice = 0; + } + } + } +#endif + sndlog = NULL; +} + + +void init_sound_stream(void){ + int vol; + if (app_data.sound_en){ + if (app_data.filter) + vol = (255*app_data.svolume)/100; + else + vol = (255*app_data.svolume)/200; + stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128); + if (!stream) { + printf("Error creating audio stream!\n"); + app_data.sound_en=0; + } + flt_a = flt_b = 0.0; + flt_prv = 0; + } +} + + +void mute_audio(void){ + if (app_data.sound_en && stream){ + stop_audio_stream(stream); + stream=NULL; + } +} + + +void close_audio(void) { + if (app_data.sound_en && stream) { + stop_audio_stream(stream); + } + if (sndlog) fclose(sndlog); + app_data.sound_en=0; +} + + +static void filter(unsigned char *buffer, unsigned long len){ + static unsigned char buf[SOUND_BUFFER_LEN]; + int t; + unsigned long i; + if (len>SOUND_BUFFER_LEN) return; + memcpy(buf,buffer,len); + for (i=0; i255.0)||(flt_a<-255.0)) flt_a=0.0; + buffer[i] = (unsigned char)((flt_a+255.0)/2.0); + } + flt_prv = buf[len-1]; +} + + diff --git a/clean/src/audio.h b/clean/src/audio.h new file mode 100755 index 0000000..47d971c --- /dev/null +++ b/clean/src/audio.h @@ -0,0 +1,17 @@ +#ifndef __AUDIO_H +#define __AUDIO_H + +void update_audio(void); +void init_audio(void); +void close_audio(void); +void init_sound_stream(void); +void mute_audio(void); + + +extern int sound_IRQ; +extern FILE *sndlog; + + +#endif + + diff --git a/clean/src/config.h b/clean/src/config.h new file mode 100755 index 0000000..715a373 --- /dev/null +++ b/clean/src/config.h @@ -0,0 +1,14 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define O2EM_VERSION "1.18" +#define RELEASE_DATE "(Jan/2007)" + +#define ROM_O2 1 +#define ROM_G7400 2 +#define ROM_C52 3 +#define ROM_JOPAC 4 +#define ROM_UNKNOWN 99 + +#endif + diff --git a/clean/src/cpu.c b/clean/src/cpu.c new file mode 100755 index 0000000..9d36f46 --- /dev/null +++ b/clean/src/cpu.c @@ -0,0 +1,1572 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + ** Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * 8048 microcontroller emulation + */ + + +#include +#include "types.h" +#include "vmachine.h" +#include "keyboard.h" +#include "voice.h" +#include "vdc.h" +#include "vpp.h" +#include "cpu.h" + +#define push(d) {intRAM[sp++] = (d); if (sp > 23) sp = 8;} +#define pull() (sp--, (sp < 8)?(sp=23):0, intRAM[sp]) +#define make_psw() {psw = (cy << 7) | ac | f0 | bs | 0x08; psw = psw | ((sp - 8) >> 1);} +#define illegal(o) {} +#define undef(i) {printf("** unimplemented instruction %x, %x**\n",i,pc);} +#define ROM(adr) (rom[(adr) & 0xfff]) + + +void init_cpu(void){ + pc=0; + sp=8; + bs=0; + p1=p2=0xFF; + ac=cy=f0=0; + A11=A11ff=0; + timer_on=0; + count_on=0; + reg_pnt=0; + tirq_en=xirq_en=irq_ex=xirq_pend=tirq_pend=0; +} + + +void ext_IRQ(void){ + int_clk = 5; /* length of pulse on /INT */ + if (xirq_en && !irq_ex) { + irq_ex=1; + xirq_pend=0; + clk+=2; + make_psw(); + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = 0x03; + A11ff=A11; + A11=0; + } + if (pendirq && (!xirq_en)) xirq_pend=1; +} + + +void tim_IRQ(void){ + if (tirq_en && !irq_ex) { + irq_ex=2; + tirq_pend=0; + clk+=2; + make_psw(); + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = 0x07; + A11ff=A11; + A11=0; + } + if (pendirq && (!tirq_en)) tirq_pend=1; +} + + +void make_psw_debug(void){ + make_psw(); +} + + + +void cpu_exec(void) { + Byte op; + ADDRESS adr; + Byte dat; + int temp; + + for (;;) { + + clk=0; + + lastpc=pc; + op=ROM(pc++); + switch (op) { + case 0x00: /* NOP */ + clk++; + break; + case 0x01: /* ILL */ + illegal(op); + clk++; + break; + case 0x02: /* OUTL BUS,A */ + clk+=2; + undef(0x02); + break; + case 0x03: /* ADD A,#data */ + clk+=2; + cy=ac=0; + dat=ROM(pc++); + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x04: /* JMP */ + pc=ROM(pc) | A11; + clk+=2; + break; + case 0x05: /* EN I */ + xirq_en=1; + clk++; + break; + case 0x06: /* ILL */ + clk++; + illegal(op); + break; + case 0x07: /* DEC A */ + acc--; + clk++; + break; + case 0x08: /* INS A,BUS*/ + clk+=2; + acc=in_bus(); + break; + case 0x09: /* IN A,Pp */ + acc=p1; + clk+=2; + break; + case 0x0A: /* IN A,Pp */ + acc=read_P2(); + clk+=2; + break; + case 0x0B: /* ILL */ + clk++; + illegal(op); + break; + case 0x0C: /* MOVD A,P4 */ + clk+=2; + acc=read_PB(0); + break; + case 0x0D: /* MOVD A,P5 */ + clk+=2; + acc=read_PB(1); + break; + case 0x0E: /* MOVD A,P6 */ + clk+=2; + acc=read_PB(2); + break; + case 0x0F: /* MOVD A,P7 */ + clk+=2; + acc=read_PB(3); + break; + case 0x10: /* INC @Ri */ + intRAM[intRAM[reg_pnt] & 0x3F]++; + clk++; + break; + case 0x11: /* INC @Ri */ + intRAM[intRAM[reg_pnt+1] & 0x3F]++; + clk++; + break; + case 0x12: /* JBb address */ + clk+=2; + dat = ROM(pc); + if (acc & 0x01) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x13: /* ADDC A,#data */ + clk+=2; + dat=ROM(pc++); + ac=0; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x14: /* CALL */ + make_psw(); + adr = ROM(pc) | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x15: /* DIS I */ + xirq_en=0; + clk++; + break; + case 0x16: /* JTF */ + clk+=2; + dat = ROM(pc); + if (t_flag) + pc=(pc & 0xF00) | dat; + else + pc++; + t_flag=0; + break; + case 0x17: /* INC A */ + acc++; + clk++; + break; + case 0x18: /* INC Rr */ + intRAM[reg_pnt]++; + clk++; + break; + case 0x19: /* INC Rr */ + intRAM[reg_pnt+1]++; + clk++; + break; + case 0x1A: /* INC Rr */ + intRAM[reg_pnt+2]++; + clk++; + break; + case 0x1B: /* INC Rr */ + intRAM[reg_pnt+3]++; + clk++; + break; + case 0x1C: /* INC Rr */ + intRAM[reg_pnt+4]++; + clk++; + break; + case 0x1D: /* INC Rr */ + intRAM[reg_pnt+5]++; + clk++; + break; + case 0x1E: /* INC Rr */ + intRAM[reg_pnt+6]++; + clk++; + break; + case 0x1F: /* INC Rr */ + intRAM[reg_pnt+7]++; + clk++; + break; + case 0x20: /* XCH A,@Ri */ + clk++; + dat=acc; + acc=intRAM[intRAM[reg_pnt] & 0x3F]; + intRAM[intRAM[reg_pnt] & 0x3F] = dat; + break; + case 0x21: /* XCH A,@Ri */ + clk++; + dat=acc; + acc=intRAM[intRAM[reg_pnt+1] & 0x3F]; + intRAM[intRAM[reg_pnt+1] & 0x3F] = dat; + break; + case 0x22: /* ILL */ + clk++; + illegal(op); + break; + case 0x23: /* MOV a,#data */ + clk+=2; + acc = ROM(pc++); + break; + + case 0x24: /* JMP */ + pc=ROM(pc) | 0x100 | A11; + clk+=2; + break; + case 0x25: /* EN TCNTI */ + tirq_en=1; + clk++; + break; + case 0x26: /* JNT0 */ + clk+=2; + dat = ROM(pc); + if (!get_voice_status()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x27: /* CLR A */ + clk++; + acc=0; + break; + case 0x28: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt]; + intRAM[reg_pnt]=dat; + clk++; + break; + case 0x29: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+1]; + intRAM[reg_pnt+1]=dat; + clk++; + break; + case 0x2A: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+2]; + intRAM[reg_pnt+2]=dat; + clk++; + break; + case 0x2B: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+3]; + intRAM[reg_pnt+3]=dat; + clk++; + break; + case 0x2C: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+4]; + intRAM[reg_pnt+4]=dat; + clk++; + break; + case 0x2D: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+5]; + intRAM[reg_pnt+5]=dat; + clk++; + break; + case 0x2E: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+6]; + intRAM[reg_pnt+6]=dat; + clk++; + break; + case 0x2F: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+7]; + intRAM[reg_pnt+7]=dat; + clk++; + break; + case 0x30: /* XCHD A,@Ri */ + clk++; + adr=intRAM[reg_pnt] & 0x3F; + dat=acc & 0x0F; + acc=acc & 0xF0; + acc=acc | (intRAM[adr] & 0x0F); + intRAM[adr] &= 0xF0; + intRAM[adr] |= dat; + break; + case 0x31: /* XCHD A,@Ri */ + clk++; + adr=intRAM[reg_pnt+1] & 0x3F; + dat=acc & 0x0F; + acc=acc & 0xF0; + acc=acc | (intRAM[adr] & 0x0F); + intRAM[adr] &= 0xF0; + intRAM[adr] |= dat; + break; + case 0x32: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x02) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x33: /* ILL */ + clk++; + illegal(op); + break; + case 0x34: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x100 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x35: /* DIS TCNTI */ + tirq_en=0; + tirq_pend=0; + clk++; + break; + case 0x36: /* JT0 */ + clk+=2; + dat=ROM(pc); + if (get_voice_status()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x37: /* CPL A */ + acc = acc ^ 0xFF; + clk++; + break; + case 0x38: /* ILL */ + clk++; + illegal(op); + break; + case 0x39: /* OUTL P1,A */ + clk+=2; + write_p1(acc); + break; + case 0x3A: /* OUTL P2,A */ + clk+=2; + p2=acc; + break; + case 0x3B: /* ILL */ + clk++; + illegal(op); + break; + case 0x3C: /* MOVD P4,A */ + clk+=2; + write_PB(0,acc); + break; + case 0x3D: /* MOVD P5,A */ + clk+=2; + write_PB(1,acc); + break; + case 0x3E: /* MOVD P6,A */ + clk+=2; + write_PB(2,acc); + break; + case 0x3F: /* MOVD P7,A */ + clk+=2; + write_PB(3,acc); + break; + case 0x40: /* ORL A,@Ri */ + clk++; + acc = acc | intRAM[intRAM[reg_pnt] & 0x3F]; + break; + case 0x41: /* ORL A,@Ri */ + clk++; + acc = acc | intRAM[intRAM[reg_pnt+1] & 0x3F]; + break; + case 0x42: /* MOV A,T */ + clk++; + acc = itimer; + break; + case 0x43: /* ORL A,#data */ + clk+=2; + acc = acc | ROM(pc++); + break; + case 0x44: /* JMP */ + pc=ROM(pc) | 0x200 | A11; + clk+=2; + break; + case 0x45: /* STRT CNT */ + /* printf("START: %d=%d\n",master_clk/22,itimer); */ + count_on=1; + clk++; + break; + case 0x46: /* JNT1 */ + clk+=2; + dat = ROM(pc); + if (!read_t1()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x47: /* SWAP A */ + clk++; + dat=(acc & 0xF0) >> 4; + acc = acc << 4; + acc = acc | dat; + break; + case 0x48: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt]; + break; + case 0x49: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+1]; + break; + case 0x4A: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+2]; + break; + case 0x4B: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+3]; + break; + case 0x4C: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+4]; + break; + case 0x4D: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+5]; + break; + case 0x4E: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+6]; + break; + case 0x4F: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+7]; + break; + + case 0x50: /* ANL A,@Ri */ + acc = acc & intRAM[intRAM[reg_pnt] & 0x3F]; + clk++; + break; + case 0x51: /* ANL A,@Ri */ + acc = acc & intRAM[intRAM[reg_pnt+1] & 0x3F]; + clk++; + break; + case 0x52: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x04) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x53: /* ANL A,#data */ + clk+=2; + acc = acc & ROM(pc++); + break; + case 0x54: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x200 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x55: /* STRT T */ + timer_on=1; + clk++; + break; + case 0x56: /* JT1 */ + clk+=2; + dat = ROM(pc); + if (read_t1()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x57: /* DA A */ + clk++; + if (((acc & 0x0F) > 0x09) || ac) { + if (acc>0xf9) cy=1; + acc += 6; + } + dat = (acc & 0xF0) >> 4; + if ((dat > 9) || cy) { + dat+=6; + cy=1; + } + acc = (acc & 0x0F) | (dat << 4); + break; + case 0x58: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt]; + break; + case 0x59: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+1]; + break; + case 0x5A: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+2]; + break; + case 0x5B: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+3]; + break; + case 0x5C: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+4]; + break; + case 0x5D: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+5]; + break; + case 0x5E: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+6]; + break; + case 0x5F: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+7]; + break; + + case 0x60: /* ADD A,@Ri */ + clk++; + cy=ac=0; + dat=intRAM[intRAM[reg_pnt] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x61: /* ADD A,@Ri */ + clk++; + cy=ac=0; + dat=intRAM[intRAM[reg_pnt+1] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x62: /* MOV T,A */ + clk++; + itimer=acc; + break; + case 0x63: /* ILL */ + clk++; + illegal(op); + break; + case 0x64: /* JMP */ + pc=ROM(pc) | 0x300 | A11; + clk+=2; + break; + case 0x65: /* STOP TCNT */ + clk++; + /* printf("STOP %d\n",master_clk/22); */ + count_on=timer_on=0; + break; + case 0x66: /* ILL */ + clk++; + illegal(op); + break; + case 0x67: /* RRC A */ + dat=cy; + cy=acc & 0x01; + acc = acc >> 1; + if (dat) + acc = acc | 0x80; + else + acc = acc & 0x7F; + clk++; + break; + case 0x68: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x69: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+1]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6A: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+2]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6B: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+3]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6C: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+4]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6D: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+5]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6E: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+6]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6F: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+7]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x70: /* ADDC A,@Ri */ + clk++; + ac=0; + dat=intRAM[intRAM[reg_pnt] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x71: /* ADDC A,@Ri */ + clk++; + ac=0; + dat=intRAM[intRAM[reg_pnt+1] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x72: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x08) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x73: /* ILL */ + clk++; + illegal(op); + break; + case 0x74: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x300 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x75: /* EN CLK */ + clk++; + undef(op); + break; + case 0x76: /* JF1 address */ + clk+=2; + dat=ROM(pc); + if (f1) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x77: /* RR A */ + clk++; + dat=acc & 0x01; + acc = acc >> 1; + if (dat) + acc = acc | 0x80; + else + acc = acc & 0x7f; + break; + + case 0x78: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x79: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+1]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7A: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+2]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7B: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+3]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7C: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+4]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7D: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+5]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7E: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+6]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7F: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+7]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x80: /* MOVX A,@Ri */ + acc=ext_read(intRAM[reg_pnt]); + clk+=2; + break; + case 0x81: /* MOVX A,@Ri */ + acc=ext_read(intRAM[reg_pnt+1]); + clk+=2; + break; + case 0x82: /* ILL */ + clk++; + illegal(op); + break; + case 0x83: /* RET */ + clk+=2; + pc = ((pull() & 0x0F) << 8); + pc = pc | pull(); + break; + case 0x84: /* JMP */ + pc=ROM(pc) | 0x400 | A11; + clk+=2; + break; + case 0x85: /* CLR F0 */ + clk++; + f0=0; + break; + case 0x86: /* JNI address */ + clk+=2; + dat=ROM(pc); + if (int_clk > 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x87: /* ILL */ + illegal(op); + clk++; + break; + case 0x88: /* BUS,#data */ + clk+=2; + undef(op); + break; + case 0x89: /* ORL Pp,#data */ + write_p1(p1 | ROM(pc++)); + clk+=2; + break; + case 0x8A: /* ORL Pp,#data */ + p2 = p2 | ROM(pc++); + clk+=2; + break; + case 0x8B: /* ILL */ + illegal(op); + clk++; + break; + case 0x8C: /* ORLD P4,A */ + write_PB(0,read_PB(0)|acc); + clk+=2; + break; + case 0x8D: /* ORLD P5,A */ + write_PB(1,read_PB(1)|acc); + clk+=2; + break; + case 0x8E: /* ORLD P6,A */ + write_PB(2,read_PB(2)|acc); + clk+=2; + break; + case 0x8F: /* ORLD P7,A */ + write_PB(3,read_PB(3)|acc); + clk+=2; + break; + case 0x90: /* MOVX @Ri,A */ + ext_write(acc,intRAM[reg_pnt]); + clk+=2; + break; + case 0x91: /* MOVX @Ri,A */ + ext_write(acc,intRAM[reg_pnt+1]); + clk+=2; + break; + case 0x92: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x10) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x93: /* RETR*/ + /* printf("RETR %d\n",master_clk/22); */ + clk+=2; + dat=pull(); + pc = (dat & 0x0F) << 8; + cy = (dat & 0x80) >> 7; + ac = dat & 0x40; + f0 = dat & 0x20; + bs = dat & 0x10; + if (bs) + reg_pnt=24; + else + reg_pnt=0; + pc = pc | pull(); + irq_ex=0; + A11=A11ff; + break; + case 0x94: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x400 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x95: /* CPL F0 */ + f0 = f0 ^ 0x20; + clk++; + break; + case 0x96: /* JNZ address */ + clk+=2; + dat=ROM(pc); + if (acc != 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x97: /* CLR C */ + cy=0; + clk++; + break; + case 0x98: /* ANL BUS,#data */ + clk+=2; + undef(op); + break; + case 0x99: /* ANL Pp,#data */ + write_p1(p1 & ROM(pc++)); + clk+=2; + break; + case 0x9A: /* ANL Pp,#data */ + p2 = p2 & ROM(pc++); + clk+=2; + break; + case 0x9B: /* ILL */ + illegal(op); + clk++; + break; + case 0x9C: /* ANLD P4,A */ + write_PB(0,read_PB(0)&acc); + clk+=2; + break; + case 0x9D: /* ANLD P5,A */ + write_PB(1,read_PB(1)&acc); + clk+=2; + break; + case 0x9E: /* ANLD P6,A */ + write_PB(2,read_PB(2)&acc); + clk+=2; + break; + case 0x9F: /* ANLD P7,A */ + write_PB(3,read_PB(3)&acc); + clk+=2; + break; + case 0xA0: /* MOV @Ri,A */ + intRAM[intRAM[reg_pnt] & 0x3F]=acc; + clk++; + break; + case 0xA1: /* MOV @Ri,A */ + intRAM[intRAM[reg_pnt+1] & 0x3F]=acc; + clk++; + break; + case 0xA2: /* ILL */ + clk++; + illegal(op); + break; + case 0xA3: /* MOVP A,@A */ + acc=ROM((pc & 0xF00) | acc); + clk+=2; + break; + case 0xA4: /* JMP */ + pc=ROM(pc) | 0x500 | A11; + clk+=2; + break; + case 0xA5: /* CLR F1 */ + clk++; + f1=0; + break; + case 0xA6: /* ILL */ + illegal(op); + clk++; + break; + case 0xA7: /* CPL C */ + cy = cy ^ 0x01; + clk++; + break; + case 0xA8: /* MOV Rr,A */ + intRAM[reg_pnt] = acc; + clk++; + break; + case 0xA9: /* MOV Rr,A */ + intRAM[reg_pnt+1] = acc; + clk++; + break; + case 0xAA: /* MOV Rr,A */ + intRAM[reg_pnt+2] = acc; + clk++; + break; + case 0xAB: /* MOV Rr,A */ + intRAM[reg_pnt+3] = acc; + clk++; + break; + case 0xAC: /* MOV Rr,A */ + intRAM[reg_pnt+4] = acc; + clk++; + break; + case 0xAD: /* MOV Rr,A */ + intRAM[reg_pnt+5] = acc; + clk++; + break; + case 0xAE: /* MOV Rr,A */ + intRAM[reg_pnt+6] = acc; + clk++; + break; + case 0xAF: /* MOV Rr,A */ + intRAM[reg_pnt+7] = acc; + clk++; + break; + case 0xB0: /* MOV @Ri,#data */ + intRAM[intRAM[reg_pnt] & 0x3F]=ROM(pc++); + clk+=2; + break; + case 0xB1: /* MOV @Ri,#data */ + intRAM[intRAM[reg_pnt+1] & 0x3F]=ROM(pc++); + clk+=2; + break; + case 0xB2: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x20) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xB3: /* JMPP @A */ + adr = (pc & 0xF00) | acc; + pc=(pc & 0xF00) | ROM(adr); + clk+=2; + break; + case 0xB4: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x500 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xB5: /* CPL F1 */ + f1 = f1 ^ 0x01; + clk++; + break; + case 0xB6: /* JF0 address */ + clk+=2; + dat=ROM(pc); + if (f0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xB7: /* ILL */ + clk++; + illegal(op); + break; + case 0xB8: /* MOV Rr,#data */ + intRAM[reg_pnt]=ROM(pc++); + clk+=2; + break; + case 0xB9: /* MOV Rr,#data */ + intRAM[reg_pnt+1]=ROM(pc++); + clk+=2; + break; + case 0xBA: /* MOV Rr,#data */ + intRAM[reg_pnt+2]=ROM(pc++); + clk+=2; + break; + case 0xBB: /* MOV Rr,#data */ + intRAM[reg_pnt+3]=ROM(pc++); + clk+=2; + break; + case 0xBC: /* MOV Rr,#data */ + intRAM[reg_pnt+4]=ROM(pc++); + clk+=2; + break; + case 0xBD: /* MOV Rr,#data */ + intRAM[reg_pnt+5]=ROM(pc++); + clk+=2; + break; + case 0xBE: /* MOV Rr,#data */ + intRAM[reg_pnt+6]=ROM(pc++); + clk+=2; + break; + case 0xBF: /* MOV Rr,#data */ + intRAM[reg_pnt+7]=ROM(pc++); + clk+=2; + break; + case 0xC0: /* ILL */ + illegal(op); + clk++; + break; + case 0xC1: /* ILL */ + illegal(op); + clk++; + break; + case 0xC2: /* ILL */ + illegal(op); + clk++; + break; + case 0xC3: /* ILL */ + illegal(op); + clk++; + break; + case 0xC4: /* JMP */ + pc=ROM(pc) | 0x600 | A11; + clk+=2; + break; + case 0xC5: /* SEL RB0 */ + bs=reg_pnt=0; + clk++; + break; + case 0xC6: /* JZ address */ + clk+=2; + dat=ROM(pc); + if (acc == 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xC7: /* MOV A,PSW */ + clk++; + make_psw(); + acc=psw; + break; + case 0xC8: /* DEC Rr */ + intRAM[reg_pnt]--; + clk++; + break; + case 0xC9: /* DEC Rr */ + intRAM[reg_pnt+1]--; + clk++; + break; + case 0xCA: /* DEC Rr */ + intRAM[reg_pnt+2]--; + clk++; + break; + case 0xCB: /* DEC Rr */ + intRAM[reg_pnt+3]--; + clk++; + break; + case 0xCC: /* DEC Rr */ + intRAM[reg_pnt+4]--; + clk++; + break; + case 0xCD: /* DEC Rr */ + intRAM[reg_pnt+5]--; + clk++; + break; + case 0xCE: /* DEC Rr */ + intRAM[reg_pnt+6]--; + clk++; + break; + case 0xCF: /* DEC Rr */ + intRAM[reg_pnt+7]--; + clk++; + break; + case 0xD0: /* XRL A,@Ri */ + acc = acc ^ intRAM[intRAM[reg_pnt] & 0x3F]; + clk++; + break; + case 0xD1: /* XRL A,@Ri */ + acc = acc ^ intRAM[intRAM[reg_pnt+1] & 0x3F]; + clk++; + break; + case 0xD2: /* JBb address */ + clk+=2; + dat = ROM(pc); + if (acc & 0x40) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xD3: /* XRL A,#data */ + clk+=2; + acc = acc ^ ROM(pc++); + break; + case 0xD4: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x600 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xD5: /* SEL RB1 */ + bs=0x10; + reg_pnt=24; + clk++; + break; + case 0xD6: /* ILL */ + illegal(op); + clk++; + break; + case 0xD7: /* MOV PSW,A */ + psw=acc; + clk++; + cy = (psw & 0x80) >> 7; + ac = psw & 0x40; + f0 = psw & 0x20; + bs = psw & 0x10; + if (bs) + reg_pnt = 24; + else + reg_pnt = 0; + sp = (psw & 0x07) << 1; + sp+=8; + break; + case 0xD8: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt]; + clk++; + break; + case 0xD9: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+1]; + clk++; + break; + case 0xDA: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+2]; + clk++; + break; + case 0xDB: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+3]; + clk++; + break; + case 0xDC: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+4]; + clk++; + break; + case 0xDD: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+5]; + clk++; + break; + case 0xDE: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+6]; + clk++; + break; + case 0xDF: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+7]; + clk++; + break; + case 0xE0: /* ILL */ + clk++; + illegal(op); + break; + case 0xE1: /* ILL */ + clk++; + illegal(op); + break; + case 0xE2: /* ILL */ + clk++; + illegal(op); + break; + case 0xE3: /* MOVP3 A,@A */ + + adr = 0x300 | acc; + acc=ROM(adr); + clk+=2; + break; + case 0xE4: /* JMP */ + pc=ROM(pc) | 0x700 | A11; + clk+=2; + break; + case 0xE5: /* SEL MB0 */ + A11=0; + A11ff = 0; + clk++; + break; + case 0xE6: /* JNC address */ + clk+=2; + dat=ROM(pc); + if (!cy) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xE7: /* RL A */ + clk++; + dat=acc & 0x80; + acc = acc << 1; + if (dat) + acc = acc | 0x01; + else + acc = acc & 0xFE; + break; + case 0xE8: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt]--; + dat=ROM(pc); + if (intRAM[reg_pnt] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xE9: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+1]--; + dat=ROM(pc); + if (intRAM[reg_pnt+1] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEA: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+2]--; + dat=ROM(pc); + if (intRAM[reg_pnt+2] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEB: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+3]--; + dat=ROM(pc); + if (intRAM[reg_pnt+3] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEC: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+4]--; + dat=ROM(pc); + if (intRAM[reg_pnt+4] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xED: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+5]--; + dat=ROM(pc); + if (intRAM[reg_pnt+5] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEE: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+6]--; + dat=ROM(pc); + if (intRAM[reg_pnt+6] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEF: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+7]--; + dat=ROM(pc); + if (intRAM[reg_pnt+7] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xF0: /* MOV A,@Ri */ + clk++; + acc=intRAM[intRAM[reg_pnt] & 0x3F]; + break; + case 0xF1: /* MOV A,@Ri */ + clk++; + acc=intRAM[intRAM[reg_pnt + 1] & 0x3F]; + break; + case 0xF2: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x80) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xF3: /* ILL */ + illegal(op); + clk++; + break; + case 0xF4: /* CALL */ + clk+=2; + make_psw(); + adr = ROM(pc) | 0x700 | A11; + pc++; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xF5: /* SEL MB1 */ + if (irq_ex) { + A11ff = 0x800; + } + else + { + A11=0x800; + A11ff = 0x800; + } + clk++; + break; + case 0xF6: /* JC address */ + clk+=2; + dat=ROM(pc); + if (cy) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xF7: /* RLC A */ + dat=cy; + cy=(acc & 0x80) >> 7; + acc = acc << 1; + if (dat) + acc = acc | 0x01; + else + acc = acc & 0xFE; + clk++; + break; + case 0xF8: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt]; + break; + case 0xF9: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 1]; + break; + case 0xFA: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 2]; + break; + case 0xFB: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 3]; + break; + case 0xFC: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 4]; + break; + case 0xFD: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 5]; + break; + case 0xFE: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 6]; + break; + case 0xFF: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 7]; + break; + } + + + master_clk+=clk; + h_clk+=clk; + clk_counter+=clk; + + /* flag for JNI */ + if (int_clk > clk) + int_clk -= clk; + else + int_clk = 0; + + /* pending IRQs */ + if (xirq_pend) ext_IRQ(); + if (tirq_pend) tim_IRQ(); + + if (h_clk > LINECNT-1) { + h_clk-=LINECNT; + if (enahirq && (VDCwrite[0xA0] & 0x01)) ext_IRQ(); + if (count_on && mstate == 0) { + itimer++; + if (itimer == 0) { + t_flag=1; + tim_IRQ(); + draw_region(); + } + } + } + + if (timer_on) { + master_count+=clk; + if (master_count > 31) { + master_count-=31; + itimer++; + if (itimer == 0) { + t_flag=1; + tim_IRQ(); + } + } + } + + if ((mstate==0) && (master_clk > VBLCLK)) handle_vbl(); + + if ((mstate==1) && (master_clk > evblclk)) { + handle_evbl(); + if (app_data.crc == 0xA7344D1F) handle_evbll(); /* Atlantis */ + break; + } + + if (app_data.debug) break; + + if (pc==app_data.breakpoint) break; + } + +} + diff --git a/clean/src/cpu.h b/clean/src/cpu.h new file mode 100755 index 0000000..042fee2 --- /dev/null +++ b/clean/src/cpu.h @@ -0,0 +1,65 @@ +#ifndef CPU_H +#define CPU_H + +#include "types.h" + +extern Byte acc; /* Accumulator */ +extern ADDRESS pc; /* Program counter */ +extern long clk; /* clock */ + +extern Byte itimer; /* Internal timer */ +extern Byte reg_pnt; /* pointer to register bank */ +extern Byte timer_on; /* 0=timer off/1=timer on */ +extern Byte count_on; /* 0=count off/1=count on */ + +extern Byte t_flag; /* Timer flag */ + +extern Byte psw; /* Processor status word */ +extern Byte sp; /* Stack pointer (part of psw) */ + +extern Byte p1; /* I/O port 1 */ +extern Byte p2; /* I/O port 2 */ + +extern Byte xirq_pend; +extern Byte tirq_pend; + +void init_cpu(void); +void cpu_exec(void); +void ext_IRQ(void); +void tim_IRQ(void); +void make_psw_debug(void); + +Byte acc; /* Accumulator */ +ADDRESS pc; /* Program counter */ +long clk; /* clock */ + +Byte itimer; /* Internal timer */ +Byte reg_pnt; /* pointer to register bank */ +Byte timer_on; /* 0=timer off/1=timer on */ +Byte count_on; /* 0=count off/1=count on */ +Byte psw; /* Processor status word */ +Byte sp; /* Stack pointer (part of psw) */ + +Byte p1; /* I/O port 1 */ +Byte p2; /* I/O port 2 */ +Byte xirq_pend; /* external IRQ pending */ +Byte tirq_pend; /* timer IRQ pending */ +Byte t_flag; /* Timer flag */ + +ADDRESS lastpc; +ADDRESS A11; /* PC bit 11 */ +ADDRESS A11ff; +Byte bs; /* Register Bank (part of psw) */ +Byte f0; /* Flag Bit (part of psw) */ +Byte f1; /* Flag Bit 1 */ +Byte ac; /* Aux Carry (part of psw) */ +Byte cy; /* Carry flag (part of psw) */ +Byte xirq_en; /* external IRQ's enabled */ +Byte tirq_en; /* Timer IRQ enabled */ +Byte irq_ex; /* IRQ executing */ + +int master_count; + + +#endif /* CPU_H */ + diff --git a/clean/src/crc32.c b/clean/src/crc32.c new file mode 100755 index 0000000..40e2c99 --- /dev/null +++ b/clean/src/crc32.c @@ -0,0 +1,116 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * CRC32 functions used to identify files + */ + +// Some stuff ported from here: +// http://www.opensource.apple.com/source/xnu/xnu-1504.7.4/bsd/libkern/crc32.c + +#include +#include +#include +#include "crc32.h" + + +static uint32_t crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +uint32_t crc32_buf(const void *buf, size_t size) +{ + uint32_t crc = ~0; + const uint8_t *p = buf; + + while (size--) crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xFF]; + return ~crc; +} + +uint32_t crc32_file(const char *filename) +{ + uint32_t crc = ~0; + FILE *f; + int c; + f = fopen(filename,"rb"); + if (f) { + while ((c=fgetc(f)) != EOF) { + crc = (crc >> 8) ^ crc32tab[(crc ^ c) & 0xFF]; + } + fclose(f); + } + return ~crc; +} + diff --git a/clean/src/crc32.h b/clean/src/crc32.h new file mode 100755 index 0000000..5e66e75 --- /dev/null +++ b/clean/src/crc32.h @@ -0,0 +1,8 @@ +#include +#ifndef __CRC32_H +#define __CRC32_H + +uint32_t crc32_buf(const void *buf, size_t len); +uint32_t crc32_file(const char *filename); + +#endif diff --git a/clean/src/cset.c b/clean/src/cset.c new file mode 100755 index 0000000..7d6b6e9 --- /dev/null +++ b/clean/src/cset.c @@ -0,0 +1,86 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 character table + */ + + +#include "types.h" +#include "cset.h" + + +Byte cset[512]= { +0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00, +0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00, +0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00, +0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00, +0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00, +0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00, +0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00, +0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00, +0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00, +0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00, +0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00, +0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00, +0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00, +0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, +0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00, +0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00, +0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00, +0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00, +0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, +0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00, +0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00, +0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00, +0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00, +0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00, +0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, +0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00, +0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00, +0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00, +0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00, +0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00, +0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00, +0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00, +0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00, +0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00, +0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00, +0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, +0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00, +0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00, +0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00, +0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00, +0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00, +0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, +0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00, +0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00, +0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00, +0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00, +0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00, +0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00, +0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00, +0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00, +0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00, +0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00, +0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00, +0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00, +0x00,0x00,0x0C,0x08,0x08,0xFF,0x7E,0x00, +0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00, +0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00, +0x00,0x00,0x00,0x06,0x6E,0xFF,0x7E,0x00}; + diff --git a/clean/src/cset.h b/clean/src/cset.h new file mode 100755 index 0000000..6c61d51 --- /dev/null +++ b/clean/src/cset.h @@ -0,0 +1,6 @@ +#ifndef __CSET_H +#define __CSET_H + +extern Byte cset[512]; + +#endif diff --git a/clean/src/debug.c b/clean/src/debug.c new file mode 100755 index 0000000..ec3bf69 --- /dev/null +++ b/clean/src/debug.c @@ -0,0 +1,1052 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2EM built-in debugger + */ + +#include +#include +#include "cpu.h" +#include "keyboard.h" +#include "vmachine.h" +#include "audio.h" +#include "vdc.h" +#include "table.h" +#include "debug.h" +#include "allegro.h" +#include "vpp.h" +#include "score.h" + +#if defined(ALLEGRO_WINDOWS) +#include "winalleg.h" +#include +#define KBHIT _kbhit +#elif defined(ALLEGRO_DOS) +#include +#define KBHIT kbhit +#else +#define KBHIT() 0 +#endif + +static int assemble(char *opcode, int p); +static int disasm(ADDRESS p); +static int spriteprint(ADDRESS p); +static void show_reg(void); +int nMemDump; +int nDisAsm; +int nSprite; +void decimal2binary(int decimal_value, char binary_value[32], short digits); + +void debug(void) +{ + int done, i, go, j; + char *result; + char inp[80]; + char *tok; + ADDRESS ad, run_to; + char cr[2], ff[2]; + Byte d, a; + + dbstick1 = dbstick2 = 0; + cr[0] = 13; + cr[1] = 0; + ff[0] = 0x0c; + ff[1] = 0; + + done = go = 0; + set_display_switch_mode(SWITCH_BACKGROUND); + + if (sndlog) + fclose(sndlog); + +#ifdef ALLEGRO_WINDOWS + FreeConsole(); + AllocConsole(); +#endif + + printf("\nDebug mode\n\n"); + + if (pc == app_data.breakpoint) { + printf("Breakpoint reached at %x\n", pc); + } + + nMemDump = pc; + nDisAsm = pc; + nSprite = 0; + show_reg(); + + while (!done) { + while (go > 0) { + disasm(pc); + cpu_exec(); + go--; + if (KBHIT()) { + go = 0; + cpu_exec(); + show_reg(); + } + } + printf("> "); + result = fgets(inp, 76, stdin); + if (result != NULL && strlen(inp) > 0 && inp[strlen(inp) - 1] == '\n') + inp[strlen(inp) - 1] = 0; + strlwr(inp); + strcat(inp, " \n"); + tok = strtok(inp, " "); + if (!tok) + tok = ""; + if (!strcmp(tok, "h") || !strcmp(tok, "?") || !strcmp(tok, "help")) { + printf("display - show display\n"); + printf("viewsprite # - show memory # as sprite\n"); +// printf("editsprite # - edit memory # as sprite\n"); + printf("showfps - display the number of frames per second\n"); + +#ifdef ALLEGRO_DOS + printf("cls - clear screen\n"); +#endif + + printf("clrkey - clear keypresses\n"); + printf("setkey n - set key n pressed\n"); + printf("stick1 # - set stick1 to #\n"); + printf("stick2 # - set stick2 to #\n"); + + printf("reg - display registers\n"); + printf("stack - display stack\n"); + printf("col - display collision table\n"); + printf( + "video (a d) - display VDC registers (or write data d to a)\n"); + printf( + "extram (a d) - display external RAM (or write data d to a)\n"); + printf( + "intram (a d) - display internal ram (or write data d to a)\n"); + + printf("s - step\n"); + printf("so - step over\n"); + printf("go # - execute # instructions\n"); + printf("run # - run to address #\n"); + printf("runvb - run to VBL\n"); + printf("runnvb - run to no VBL\n"); + printf("bp # - breakpoint at address #\n"); + printf("bpc - clear breakpoint\n"); + printf("reset - reset the machine\n"); + + printf("load file a - load file to memory to address\n"); + printf("save file a n - save memory to file from address n Bytes\n"); + printf("savedatah file a n - save memory to file from address a n Bytes format hex\n"); + printf("savedatab file a n - save memory to file from address a n Bytes format binary\n"); + printf("savevdc file a n - save VDC to file from address a n Bytes format hex\n"); + printf("saveext file a n - save ExtRam to file from address a n Bytes format hex\n"); + printf("savevpp file - save the VPP to file\n"); + + printf("as # - assemble memory #\n"); + printf("di # - disassemble memory #\n"); + printf("md # - display memory #\n"); + printf("c # - change memory from location #\n"); + + printf("sndlog [file] - log raw sound to file\n"); + printf("ss [file] - save state [to file]\n"); + printf("ls [file] - load state [from file]\n"); + + printf("q - quit debugger and return to emulation\n"); + printf("\n"); + } else if (!strcmp(tok, "display")) { + grmode(); + clip_low = 0; + clip_high = 85000; + draw_display(); + finish_display(); + init_keyboard(); + do { + rest(1); + } while ((key_done == 0) && (!keypressed())); + set_textmode(); + set_display_switch_mode(SWITCH_BACKGROUND); + } else if (!strcmp(tok, "viewsprite")) { + if (tok) { + tok = strtok(NULL, " "); + ad = 65535; + sscanf(tok, "%hx", &ad); + if (ad == 65535) + ad = nSprite; + + for (i = 0; i < 8; i++) { + if (ad < 32768) + ad = ad + spriteprint(ad); + else + ad = 0; + } + nSprite = ad; + printf("\n"); + } +//TODO !!!! ---------------------------------------------------------------------------------------------------- + } else if (!strcmp(tok, "editsprite")) { + if (tok) { + tok = strtok(NULL, " "); + ad = 65535; + sscanf(tok, "%hx", &ad); + if (ad != 65535) { + for (i = 0; i < 8; i++) { + if (ad < 32768) + ad = ad + spriteprint(ad); + else + ad = 0; + } + printf("\n"); + } + } +//---------------------------------------------------------------------------------------------------- + } else if (!strcmp(tok, "cls")) { +#ifdef ALLEGRO_DOS + clrscr(); +#endif + } else if (!strcmp(tok, "clrkey")) { + for (i = 0; i < 128; i++) + key2[i] = 0; + } else if (!strcmp(tok, "setkey")) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%d", &i); + if ((i > 0) && (i < 128)) { + printf("Key %d set to pressed\n", i); + key2[i] = 1; + } + key2vcnt = 0; + } + } else if (!strcmp(tok, "stick1")) { + tok = strtok(NULL, " "); + if (tok) { + i = 0; + sscanf(tok, "%x", &i); + printf("Stick 1 set to %d\n", i); + dbstick1 = i; + key2vcnt = 0; + } + } else if (!strcmp(tok, "stick2")) { + tok = strtok(NULL, " "); + if (tok) { + i = 0; + sscanf(tok, "%x", &i); + printf("Stick 2 set to %d\n", i); + dbstick2 = i; + key2vcnt = 0; + } + } else if (!strcmp(tok, "s")) { + cpu_exec(); + show_reg(); + } else if (!strcmp(tok, "so")) { + run_to = pc + lookup[rom[pc]].bytes; + printf("%hx\n", run_to); + while (pc != run_to) { + cpu_exec(); + if (KBHIT()) + break; + } + show_reg(); + } else if (!strcmp(tok, "reset")) { + init_cpu(); + init_roms(); + init_vpp(); + } else if (!strcmp(tok, "reg")) { + show_reg(); + } else if (!strcmp(tok, "stack")) { + for (i = 8; i < 24; i += 2) { + ad = intRAM[i]; + d = intRAM[i + 1]; + ad = ad | ((d & 0x0F) << 8); + printf("%x: PC=%x PSW=%x", i, ad, d); + if (i == sp) + printf(" < 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%i", &t); + fn = fopen(file, "wb"); + if (fn == NULL) { + fprintf(stderr, + "Error opening save-file %s: %i\n", + file, errno); + } else { + fwrite((rom + adr), t, 1, fn); + fclose(fn); + printf( + "File %s saved: %i bytes from address:%x\n", + file, t, adr); + } + } + } + + } + } + } else if (!strcmp(tok, "savedatah")) { + int t; + int adr; + FILE *fn; + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%i", &t); + fn = fopen(file, "wt"); + if (fn == NULL) { + fprintf(stderr, + "Error opening save-data file %s: %i\n", + file, errno); + } else { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j = 0; + for (i = 0; i < ((int) ((t - 1) / 8)) + 1; + i++) { + fprintf(fn, "db "); + for (j = 0; j < 8 && i * 8 + j < t; j++) { + fprintf(fn, "0%02Xh", + rom[adr + i * 8 + j]); + if (j < 7 && i * 8 + j + 1 < t) + fprintf(fn, ","); + } + fprintf(fn, "\n"); + } + + fclose(fn); + printf( + "File %s saved: %i bytes from address:%x\n", + file, t, adr); + } + } + } + } + } + } else if (!strcmp(tok, "savevdc")) { + int t; + int adr; + FILE *fn; + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%i", &t); + fn = fopen(file, "wt"); + if (fn == NULL) { + fprintf(stderr, + "Error opening save-data file %s: %i\n", + file, errno); + } else { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j = 0; + for (i = 0; i < ((int) ((t - 1) / 8)) + 1; + i++) { + fprintf(fn, "db "); + for (j = 0; j < 8 && i * 8 + j < t; j++) { + fprintf(fn, "0%02Xh", + VDCwrite[adr + i * 8 + j]); + if (j < 7 && i * 8 + j + 1 < t) + fprintf(fn, ","); + } + fprintf(fn, "\n"); + } + + fclose(fn); + printf( + "File %s saved: %i bytes from address:%x\n", + file, t, adr); + } + } + } + } + } + } else if (!strcmp(tok, "saveext")) { + int t; + int adr; + FILE *fn; + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%i", &t); + fn = fopen(file, "wt"); + if (fn == NULL) { + fprintf(stderr, + "Error opening save-data file %s: %i\n", + file, errno); + } else { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j = 0; + for (i = 0; i < ((int) ((t - 1) / 8)) + 1; + i++) { + fprintf(fn, "db "); + for (j = 0; j < 8 && i * 8 + j < t; j++) { + fprintf(fn, "0%02Xh", + extRAM[adr + i * 8 + j]); + if (j < 7 && i * 8 + j + 1 < t) + fprintf(fn, ","); + } + fprintf(fn, "\n"); + } + + fclose(fn); + printf( + "File %s saved: %i bytes from address:%x\n", + file, t, adr); + } + } + } + } + } + } else if (!strcmp(tok, "savedatab")) { + int t; + int adr; + FILE *fn; + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%i", &t); + fn = fopen(file, "wt"); + if (fn == NULL) { + fprintf(stderr, + "Error opening save-data file %s: %i\n", + file, errno); + } else { + char binary_value[32]; + // write format "db xxxxxxxxb" 1 Zeichen pro Zeile + for (i = 0; i < t; i++) { + decimal2binary(rom[adr + i], binary_value, + 8); + fprintf(fn, "db %sb\n", binary_value); + } + + fclose(fn); + printf( + "File %s saved: %i bytes from address:%x\n", + file, t, adr); + } + } + } + } + } + } else if (!strcmp(tok, "savevpp")) { + extern Byte vpp_mem[40][32][4]; + extern Byte dchars[2][960]; + Byte mchars[2][960]; /* bit-mirrored dchars */ + FILE *fn; + char file[80] = ""; + int i, j; + + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + fn = fopen(file, "wt"); + if (fn == NULL) { + fprintf(stderr, "Error opening vpp data file %s: %i\n", + file, errno); + } else { + /* write char/attribute data */ + for (i = 0; i < 25; i++) { + /* service row is 24 in file, 31 in memory */ + if (i == 24) + i = 31; + for (j = 0; j < 40; j++) { + if (fwrite(&vpp_mem[j][i][0], 1, 1, fn) != 1) { + fprintf( + stderr, + "Error writing vpp data file %s: %i\n", + file, errno); + break; + } + if (fwrite(&vpp_mem[j][i][1], 1, 1, fn) != 1) { + fprintf( + stderr, + "Error writing vpp data file %s: %i\n", + file, errno); + break; + } + } + /* mirror slice bits */ + for (i = 0; i < 2; i++) + for (j = 0; j < 960; j++) { + mchars[i][j] = ((dchars[i][j] & 0x80) >> 7) + | ((dchars[i][j] & 0x40) >> 5) + | ((dchars[i][j] & 0x20) >> 3) + | ((dchars[i][j] & 0x10) >> 1) + | ((dchars[i][j] & 0x08) << 1) + | ((dchars[i][j] & 0x04) << 3) + | ((dchars[i][j] & 0x02) << 5) + | ((dchars[i][j] & 0x01) << 7); + } + /* write slice data */ + if (fwrite(mchars, 960, 2, fn) != 2) { + fprintf(stderr, + "Error Writing vpp data file %s: %i\n", + file, errno); + break; + } + fclose(fn); + } + } + } + } + } else if (!strcmp(tok, "load")) { + int adr; + FILE *fn; + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &adr); + fn = fopen(file, "rb"); + if (fn == NULL) { + fprintf(stderr, "Error opening load-file %s: %i\n", + file, errno); + } else { + int length; + int ret; + fseek(fn, 0L, SEEK_END); + length = ftell(fn); + rewind(fn); + ret = fread((rom + adr), length, 1, fn); + if (ret == 0) { + printf("Problem reading file\n"); + } + fclose(fn); + printf("File %s loaded to address:%x (%i bytes)\n", + file, adr, length); + } + } + } + } + } else if (!strcmp(tok, "keys")) { + j = 0; + printf("%02x:", 0); + for (i = 0; i < 128; i++) { + printf("%02x,", key2[i]); + j++; + if (j == 16) { + printf("\n"); + printf("%02x:", i + 1); + + j = 0; + } + } + printf("\n"); + } else if (!strcmp(tok, "col")) { + j = 0; + printf("%02x:", 0); + for (i = 0; i < 256; i++) { + printf("%02x,", coltab[i]); + j++; + if (j == 16) { + printf("\n"); + printf("%02x:", i + 1); + j = 0; + } + } + printf("\n"); + printf("Colreg: %x\n ", ext_read(0xA2)); + } else if (!strcmp(tok, "extram")) { + int t; + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &t); + a = (Byte) t; + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &t); + d = (Byte) t; + extRAM[a] = d; + } else { + j = 0; + printf("%02x:", 0); + for (i = 0; i < 256; i++) { + printf("%02x", extRAM[i]); + if (j < 15) + printf(","); + j++; + if (j == 16 && i != 255) { + printf("\n"); + printf("%02x:", i + 1); + + j = 0; + } + } + } + } + printf("\n\n"); + } else if (!strcmp(tok, "intram")) { + int t; + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &t); + a = (Byte) t; + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%x", &t); + d = (Byte) t; + intRAM[a] = d; + } else { + j = 0; + printf("%02x:", 0); + for (i = 0; i < 64; i++) { + printf("%02x", intRAM[i]); + if (j < 15) + printf(","); + j++; + if (j == 16 && i != 63) { + printf("\n"); + printf("%02x:", i + 1); + j = 0; + } + } + printf("\n\n"); + } + } + } else if (!strcmp(tok, "run")) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%hx", &run_to); + printf("Run to %x\n", run_to); + while (pc != run_to) { + cpu_exec(); + if (KBHIT()) + break; + } + show_reg(); + } + } else if (!strcmp(tok, "bp")) { + int bp; + tok = strtok(NULL, " "); + bp = 65535; + sscanf(tok, "%x", &bp); + if (bp == 65535) { + if (app_data.breakpoint == 65535) + printf("No Breakpoint set.\n"); + else + printf("Breakpoint at %x\n", app_data.breakpoint); + } else { + sscanf(tok, "%x", &bp); + app_data.breakpoint = bp; + printf("Breakpoint set to %x\n", app_data.breakpoint); + } + } else if (!strcmp(tok, "bpc")) { + if (app_data.breakpoint == 65535) + printf("No Breakpoint set.\n"); + else { + app_data.breakpoint = 65535; + printf("Breakpoint cleared.\n"); + } + } else if (!strcmp(tok, "runvb")) { + printf("Run to VBL\n"); + while (master_clk < 5500) { + cpu_exec(); + if (KBHIT()) + break; + } + show_reg(); + } else if (!strcmp(tok, "runnvb")) { + printf("Run to no VBL\n"); + while (master_clk > 5500) { + cpu_exec(); + if (KBHIT()) + break; + } + show_reg(); + } else if (!strcmp(tok, "go")) { + tok = strtok(NULL, " "); + if (tok) + sscanf(tok, "%d", &go); + } else if (!strcmp(tok, "di")) { + if (tok) { + tok = strtok(NULL, " "); + ad = 65535; + sscanf(tok, "%hx", &ad); + if (ad == 65535) + ad = nDisAsm; + + for (i = 0; i < 20; i++) { + if (ad < 32768) + ad = ad + disasm(ad); + else + ad = 0; + } + nDisAsm = ad; + printf("\n"); + } + } else if (!strcmp(tok, "md")) { + tok = strtok(NULL, " "); + if (tok) { + ad = 65535; + sscanf(tok, "%hx", &ad); + if (ad == 65535) + ad = nMemDump; + printf("\n"); + + for (j = 0; j < 10; j++) { + if (ad + j * 16 < 32768) { + printf("%04x : ", ad + j * 16); + for (i = 0; i < 16; i++) + printf("%02x ", rom[ad + j * 16 + i]); + printf("\n"); + } else { + ad = 0; + } + } + nMemDump = ad + 10 * 16; + printf("\n\n"); + } + } else if (!strcmp(tok, "sndlog")) { + if (app_data.sound_en) { + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + sndlog = fopen(file, "wb"); + if (sndlog) + printf("Sound log file created\n"); + else + printf("Sound log file creation failed\n"); + } + } + printf("\n"); + } else + printf("Sound emulation disabled\n\n"); + + } else if (!strcmp(tok, "ss")) { + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + savestate(file); + } + } + printf("\n"); + + } else if (!strcmp(tok, "ls")) { + tok = strtok(NULL, " "); + if (tok) { + char file[80] = ""; + sscanf(tok, "%79s", file); + if (strlen(file) > 0) { + loadstate(file); + } + } + printf("\n"); + + } else if (!strcmp(tok, "showfps")) { + show_fps = 1; + + } else if (!strcmp(tok, "c")) { + int t; + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%hx", &ad); + printf("Addr Old New (enter to exit)\n"); // Header + + do { + printf("%.4X %.2X ?", ad, rom[ad]); // Memory Position, Old Value + + result = fgets(inp, 80, stdin); + if (inp[0] != 10) { + t = 65535; + sscanf(inp, "%x", &t); + if (t < 256) { + d = (Byte) t; + rom[ad] = d; + ad = (ad == 32768) ? 0 : ad + 1; + } else { + printf("wrong value, try again\n"); + } + } + } while (inp[0] != 10); + } + printf("\n"); + } else if (!strcmp(tok, "as")) { + tok = strtok(NULL, " "); + if (tok) { + sscanf(tok, "%hx", &ad); + + printf("Addr Instruction (enter to exit)\n"); // Header + do { + printf("%.4X ", ad); // Memory Position + result = fgets(inp, 80, stdin); + + if (inp[0] != 10) { + ad = ad + assemble(inp, ad); + } + } while (inp[0] != 10); + } + printf("\n"); + + } else if ((strlen(tok) > 0) && (strcmp(tok, "\n"))) { + printf("Unknown command\n\n"); + } + + } + +#ifdef ALLEGRO_WINDOWS + FreeConsole(); +#endif + +} + +static void show_reg(void) +{ + int i; + + make_psw_debug(); + printf("PC=%.3X A=%.2X PSW=%.2X P1=%.2X P2=%.2X", pc, acc, psw, p1, p2); + printf(" clk: %d reg:%d count:%x f:%x\n", master_clk, reg_pnt, itimer, + frame); + disasm(pc); + printf("\n"); + + printf("R%d: %02x R%d': %02x PSW: ", 0, intRAM[0], 0, intRAM[24]); + printf("%sC %sAC %sF0 %sF1 SP:%.2X\n", psw & 0x80 ? "" : "!", + psw & 0x40 ? "" : "!", psw & 0x20 ? "" : "!", psw & 0x10 ? "" : "!", + psw & 0x07); + + printf("R%d: %02x R%d': %02x P1: ", 1, intRAM[1], 1, intRAM[25]); + printf("%sLum %sCopy %sVP+ %sExtRam %sVDC %sKeyB Bank:%i\n", + p1 & 0x80 ? "" : "!", p1 & 0x40 ? "" : "!", p1 & 0x20 ? "" : "!", + p1 & 0x10 ? "" : "!", p1 & 0x08 ? "" : "!", p1 & 0x04 ? "" : "!", + p1 & 0x03); + + printf("R%d: %02x R%d': %02x ", 2, intRAM[2], 2, intRAM[26]); + printf("MB%i RB%i\n", A11ff >> 11, reg_pnt > 4); + + for (i = 3; i < 8; i++) { + printf("R%d: %02x R%d': %02x\n", i, intRAM[i], i, intRAM[i + 24]); + } +} + +static int disasm(ADDRESS p) +{ + Byte op, d; + ADDRESS adr; + + op = rom[p++]; + printf("%04x %02x", p - 1, op); + if (lookup[op].bytes == 2) + printf(" %02x", rom[p]); + else + printf(" "); + printf(" %s", lookup[op].mnemonic); + switch (lookup[op].type) { + case 0: + printf("\n"); + break; + case 1: + d = rom[p]; + printf(" #%02x\n", d); + break; + case 2: + adr = rom[p]; + adr = adr | ((op & 0xE0) << 3); + printf(" $%03x\n", adr); + break; + case 3: + printf(" $%02x\n", rom[p]); + break; + } + return lookup[op].bytes; +} + +static int assemble(char *opcode, int p) +{ + char *str_value; + int op = 0; + int value; + int t; + + while ((op < 256) + && (strncasecmp(opcode, lookup[op].mnemonic, + strlen(lookup[op].mnemonic)) != 0)) + op++; + + if (op == 256) { + printf("Wrong opcode, please try again.\n"); + return (0); + } + + str_value = opcode + strlen(lookup[op].mnemonic); + while (str_value[0] == ' ') + str_value++; + + switch (lookup[op].type) { + case 0: // no other value needed + rom[p] = op; + break; + case 1: // #value needed + if (str_value[0] != '#') { + printf("Error: #xx expected\n"); + return (0); + } + t = 65335; + sscanf(str_value + 1, "%2x", &t); + if (t >= 256) { + printf("Error: #xx expected (value #00-#FF)\n"); + return (0); + } else + value = (Byte) t; + rom[p] = op; + rom[p + 1] = value; + break; + case 2: // $addresss needed (max. 7FF) + if (str_value[0] != '$') { + printf("Error: $xxx expected %s\n", str_value); + return (0); + } + t = 65335; + sscanf(str_value + 1, "%x", &t); + if (t >= 2048) { + printf("Error: $xxx expected (value below $800)\n"); + return (0); + } else + value = (Byte) t; + rom[p] = op | ((t & 1792) >> 3); + rom[p + 1] = value; + break; + + case 3: // $address needed (max. FF) + if (str_value[0] != '$') { + printf("Error: $xx expected\n"); + return (0); + } + t = 65335; + sscanf(str_value + 1, "%x", &t); + if (t >= 256) { + printf("Error: $xx expected (value $00-$FF)\n"); + return (0); + } else + value = (Byte) t; + rom[p] = op; + rom[p + 1] = value; + break; + + } + return lookup[op].bytes; +} + +void decimal2binary(int decimal_value, char binary_value[32], short digits) +{ + short i; + for (i = digits; i >= 0; i--) { + binary_value[i] = (char) ('0' + (int) (decimal_value / (1 << i))); + decimal_value = decimal_value % (1 << i); + } + binary_value[digits] = 0; +} + +static int spriteprint(ADDRESS p) +{ + char binary_value[32]; + int i; + + decimal2binary(rom[p], binary_value, 8); + printf("%04x %sb ", p, binary_value); + + for (i = 7; i >= 0; i--) { + if (binary_value[i] == '0') + printf(" "); + else + printf("%c", 178); + } + + printf("\n"); + return 1; +} diff --git a/clean/src/debug.h b/clean/src/debug.h new file mode 100755 index 0000000..ce9be9e --- /dev/null +++ b/clean/src/debug.h @@ -0,0 +1,14 @@ +#ifndef DEBUG_H +#define DEBUG_H + +void debug(void); + +#endif /* DEBUG_H */ + + + + + + + + diff --git a/clean/src/dis48.c b/clean/src/dis48.c new file mode 100755 index 0000000..b752dbc --- /dev/null +++ b/clean/src/dis48.c @@ -0,0 +1,144 @@ + +/* + * O2/8048 disassembler + */ + + +#include +#include +#include +#include +#include "types.h" +#include "table.h" +#include "debug.h" + +#define BIOSLEN 1024 +#define MAXLEN 8192 + + +Byte rom[MAXLEN+BIOSLEN]; +ADDRESS pc; + +int parse_option(char *attr, char *val); + +static int disasm(ADDRESS p) { + Byte op,d; + ADDRESS adr; + + op=rom[p++]; + printf("%04x %02x",p-1,op); + if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" "); + printf(" %s",lookup[op].mnemonic); + switch(lookup[op].type) { + case 0: + printf("\n"); + break; + case 1: + d=rom[p]; + printf(" #%02x\n",d); + break; + case 2: + adr=rom[p]; + adr = adr | ((op & 0xE0) << 3); + printf(" $%03x\n",adr); + break; + case 3: + printf(" $%02x\n",rom[p]); + break; + } + if (op == 0x83 || op == 0x93 || (((p-2+lookup[op].bytes) & 0xff) == 0xff)) printf("\n"); // Linebreak after ret, retr and end of page + return lookup[op].bytes; +} + + +int main(int argc, char **argv){ + int n; + int i,j; + int start; + long len; + FILE *fn; + static char file[MAXC], attr[MAXC], val[MAXC], *p; + pc = BIOSLEN; + if (argc<2) { + printf("Usage: dis48 [file] [-bios]\n"); + exit(0); + } + + /* load image */ + for(i=1; iMAXLEN) { + printf("Invalid image size"); + fclose(fn); + exit(0); + } + + rewind(fn); + if (fread(&rom[pc],1,len,fn) != (size_t)len) { + printf("Error loading %s\n",argv[1]); + fclose(fn); + exit(0); + } + fclose(fn); + + start = pc; + while (pc < start+len) { + n = disasm(pc); + pc = pc + n; + } + exit(0); +} + +int parse_option(char *attr, char *val) +{ + if (!strcmp(attr,"bios")) { + pc = 0; + } else { + fprintf(stderr,"Invalid option : %s\n",attr); + return 0; + } + return 1; +} diff --git a/clean/src/keyboard.c b/clean/src/keyboard.c new file mode 100755 index 0000000..2b0414f --- /dev/null +++ b/clean/src/keyboard.c @@ -0,0 +1,374 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Keyboard emulation + */ + +#include +#include +#include +#include "types.h" +#include "cpu.h" +#include "config.h" +#include "vmachine.h" +#include "vdc.h" +#include "audio.h" +#include "voice.h" +#include "vpp.h" +#include "keyboard.h" +#include "allegro.h" +#include "score.h" + +int NeedsPoll = 0; + +Byte keycode; +Byte last_key; +Byte new_int=0; /* Is new interrupt installed */ + +Byte key_done=0; +Byte key_debug=0; +#ifdef OPENEMU +struct keyb keybtab[] = { + {KEY_A,"A"}, + {KEY_B,"B"}, + {KEY_C,"C"}, + {KEY_D,"D"}, + {KEY_E,"E"}, + {KEY_F,"F"}, + {KEY_G,"G"}, + {KEY_H,"H"}, + {KEY_I,"I"}, + {KEY_J,"J"}, + {KEY_K,"K"}, + {KEY_L,"L"}, + {KEY_M,"M"}, + {KEY_N,"N"}, + {KEY_O,"O"}, + {KEY_P,"P"}, + {KEY_Q,"Q"}, + {KEY_R,"R"}, + {KEY_S,"S"}, + {KEY_T,"T"}, + {KEY_U,"U"}, + {KEY_V,"V"}, + {KEY_W,"W"}, + {KEY_X,"X"}, + {KEY_Y,"Y"}, + {KEY_Z,"Z"}, + {KEY_0,"0"}, + {KEY_1,"1"}, + {KEY_2,"2"}, + {KEY_3,"3"}, + {KEY_4,"4"}, + {KEY_5,"5"}, + {KEY_6,"6"}, + {KEY_7,"7"}, + {KEY_8,"8"}, + {KEY_9,"9"}, + {KEY_0_PAD,"0_PAD"}, + {KEY_1_PAD,"1_PAD"}, + {KEY_2_PAD,"2_PAD"}, + {KEY_3_PAD,"3_PAD"}, + {KEY_4_PAD,"4_PAD"}, + {KEY_5_PAD,"5_PAD"}, + {KEY_6_PAD,"6_PAD"}, + {KEY_7_PAD,"7_PAD"}, + {KEY_8_PAD,"8_PAD"}, + {KEY_9_PAD,"9_PAD"}, + {KEY_TILDE,"TILDE"}, + {KEY_MINUS,"MINUS"}, + {KEY_EQUALS,"EQUALS"}, + {KEY_BACKSPACE,"BACKSPACE"}, + {KEY_TAB,"TAB"}, + {KEY_OPENBRACE,"OPENBRACE"}, + {KEY_CLOSEBRACE,"CLOSEBRACE"}, + {KEY_ENTER,"ENTER"}, + {KEY_COLON,"COLON"}, + {KEY_QUOTE,"QUOTE"}, + {KEY_BACKSLASH,"BACKSLASH"}, + {KEY_BACKSLASH2,"BACKSLASH2"}, + {KEY_COMMA,"COMMA"}, + {KEY_STOP,"STOP"}, + {KEY_SLASH,"SLASH"}, + {KEY_SPACE,"SPACE"}, + {KEY_INSERT,"INSERT"}, + {KEY_DEL,"DEL"}, + {KEY_HOME,"HOME"}, + {KEY_END,"END"}, + {KEY_PGUP,"PGUP"}, + {KEY_PGDN,"PGDN"}, + {KEY_LEFT,"LEFT"}, + {KEY_RIGHT,"RIGHT"}, + {KEY_UP,"UP"}, + {KEY_DOWN,"DOWN"}, + {KEY_SLASH_PAD,"SLASH_PAD"}, + {KEY_ASTERISK,"ASTERISK"}, + {KEY_MINUS_PAD,"MINUS_PAD"}, + {KEY_PLUS_PAD,"PLUS_PAD"}, + {KEY_DEL_PAD,"DEL_PAD"}, + {KEY_ENTER_PAD,"ENTER_PAD"}, + {KEY_PRTSCR,"PRTSCR"}, + {KEY_PAUSE,"PAUSE"}, + {KEY_ABNT_C1,"ABNT_C1"}, + {KEY_YEN,"YEN"}, + {KEY_KANA,"KANA"}, + {KEY_AT,"AT"}, + {KEY_CIRCUMFLEX,"CIRCUMFLEX"}, + {KEY_COLON2,"COLON2"}, + {KEY_KANJI,"KANJI"}, + {KEY_LSHIFT,"LSHIFT"}, + {KEY_RSHIFT,"RSHIFT"}, + {KEY_LCONTROL,"LCONTROL"}, + {KEY_RCONTROL,"RCONTROL"}, + {KEY_ALT,"ALT"}, + {KEY_ALTGR,"ALTGR"}, + {KEY_LWIN,"LWIN"}, + {KEY_RWIN,"RWIN"}, + {KEY_MENU,"MENU"}, + {KEY_SCRLOCK,"SCRLOCK"}, + {KEY_NUMLOCK,"NUMLOCK"}, + {KEY_F1,"F1"}, + {KEY_F2,"F2"}, + {KEY_F3,"F3"}, + {KEY_F4,"F4"}, + {KEY_F5,"F5"}, + {KEY_F6,"F6"}, + {KEY_F7,"F7"}, + {KEY_F8,"F8"}, + {KEY_F9,"F9"}, + {KEY_F10,"F10"}, + {KEY_F11,"F11"}, + {KEY_F12,"F12"}, + {KEY_ESC,"ESC"}, + {0,""} +}; +#endif + +int joykeys[2][5] = {{0,0,0,0,0},{0,0,0,0,0}}; +int joykeystab[128]; +int syskeys[8] = {0,0,0,0,0,0,0,0}; + +void set_defjoykeys(int stick_number, int control_scheme){ + printf("Setting keyboard controller %d to %d\n", stick_number, control_scheme); + if (control_scheme) { + // TODO : Implement Azery / Qwerty handler + set_joykeys(stick_number, KEY_W, KEY_S, KEY_A, KEY_D, KEY_SPACE); + } else { + set_joykeys(stick_number,KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT,KEY_L); + } +} + +void set_defsystemkeys(void) +{ + set_systemkeys(KEY_F12,KEY_F1,KEY_F4,KEY_F5,KEY_F8,KEY_F2,KEY_F3,KEY_F6); +} + +void set_joykeys(int stick_number, int up, int down, int left, int right, int fire){ + printf("Setting joypad controller %d \n", stick_number); + int i, j; + if ((stick_number<0) || (stick_number>1)) { + return; + } + joykeys[stick_number][0] = up; + joykeys[stick_number][1] = down; + joykeys[stick_number][2] = left; + joykeys[stick_number][3] = right; + joykeys[stick_number][4] = fire; + + for (i=0; i<128; i++) { + joykeystab[i]=0; + } + + for (j=0; j<2; j++) { + for (i=0; i<5; i++) { + if ((joykeys[j][i]<1) || (joykeys[j][i]>127)) { + joykeys[j][i] = 0; + } else { + joykeystab[joykeys[j][i]] = 1; + } + } + } +} + +void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject) +{ + syskeys[0] = k_quit; + syskeys[1] = k_pause; + syskeys[2] = k_debug; + syskeys[3] = k_reset; + syskeys[4] = k_screencap; + syskeys[5] = k_save; + syskeys[6] = k_load; + syskeys[7] = k_inject; +} + +void handle_key(void){ + if (NeedsPoll) poll_keyboard(); + + + if (key[syskeys[0]] || key[KEY_ESC]) { + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[0]] || key[KEY_ESC]); + key_done=1; + } + + if (key[syskeys[1]]) { + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[1]]); + + mute_audio(); + mute_voice(); + abaut(); + + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + + if (key[KEY_ALT] && key[KEY_ENTER]) { + app_data.fullscreen = app_data.fullscreen ? 0 : 1; + grmode(); + abaut(); + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[KEY_ENTER]); + } + + } while ((!key[syskeys[1]]) && (!key[KEY_ESC]) && (!key[syskeys[0]])); + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[1]]); + + init_sound_stream(); + } + + if (key[syskeys[5]]) { + if (savestate(app_data.statefile)==0) { + display_msg("Savefile saved.",5); + } + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[5]]); + } + + /* LOAD STATE */ + if (key[syskeys[6]]) { + int stateError; + if ((stateError=loadstate(app_data.statefile))==0) { + display_msg("Savefile loaded.",5); + } else if (stateError>=199) { + if (stateError==199) display_msg("Wrong ROM-File for Savefile.",5); + else if (stateError==200+ROM_O2) display_msg("Wrong BIOS for Savefile: O2ROM needed.",5); + else if (stateError==200+ROM_G7400) display_msg("Wrong BIOS for Savefile: G7400 ROM needed.",5); + else if (stateError==200+ROM_C52) display_msg("Wrong BIOS for Savefile: C52 ROM needed.",5); + else if (stateError==200+ROM_JOPAC) display_msg("Wrong BIOS for Savefile: JOPAC ROM needed.",5); + else display_msg("Wrong BIOS for Savefile: UNKNOWN ROM needed.",5); + } + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[6]]); + } + + if (key[syskeys[2]]) key_debug=1; + + if (key[syskeys[3]]) { + init_cpu(); + init_roms(); + init_vpp(); + clearscr(); + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[3]]); + } + + /* SET HIGHSCORE */ + if (key[syskeys[7]]) { + set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore); + } + + + if (key[syskeys[4]]) { +#ifdef OPENEMU + BITMAP *bmp; + PALETTE pal; + char *p; + static char name[1024]; + static int scshot_counter = 0; + + if (strlen(app_data.scshot)>0){ + if ((p=strchr(app_data.scshot,'@'))) { + *p = 0; + sprintf(name, "%s%02d%s", app_data.scshot, scshot_counter++, p+1); + *p = '@'; + } else { + strcpy(name, app_data.scshot); + } + get_palette(pal); + bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H); + save_bitmap(name, bmp, pal); + destroy_bitmap(bmp); + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[syskeys[4]]); + } +#endif + } + + if (key[KEY_ALT] && key[KEY_ENTER]) { + app_data.fullscreen = app_data.fullscreen ? 0 : 1; + grmode(); + do { + rest(5); + if (NeedsPoll) poll_keyboard(); + } while (key[KEY_ENTER]); + } + +} + +Byte keyjoy(int jn){ + Byte d; + d=0xFF; + if ((jn>=0) && (jn<=1)){ + if (NeedsPoll) poll_keyboard(); + if (key[joykeys[jn][0]]) d &= 0xFE; + if (key[joykeys[jn][1]]) d &= 0xFB; + if (key[joykeys[jn][2]]) d &= 0xF7; + if (key[joykeys[jn][3]]) d &= 0xFD; + if (key[joykeys[jn][4]]) d &= 0xEF; + } + return d; +} + + +void init_keyboard(void){ + key_done=0; + key_debug=0; + install_keyboard(); + new_int=1; + NeedsPoll = keyboard_needs_poll(); +} + + +void Set_Old_Int9(void){ + remove_keyboard(); + new_int=0; +} + diff --git a/clean/src/keyboard.h b/clean/src/keyboard.h new file mode 100755 index 0000000..c8fae16 --- /dev/null +++ b/clean/src/keyboard.h @@ -0,0 +1,96 @@ +#ifndef __KEYBOARD_H +#define __KEYBOARD_H + +void Set_Old_Int9(void); +void init_keyboard(void); +void handle_key(void); +void set_joykeys(int joy, int up, int down, int left, int right, int fire); +void set_systemkeys(int k_quit, int k_pause, int k_debug, int k_reset, + int k_screencap, int k_save, int k_load, int k_inject); +void set_defjoykeys(int joy, int sc); +void set_defsystemkeys(void); +Byte keyjoy(int jn); + +extern Byte new_int; +extern int NeedsPoll; +extern Byte key_done; +extern Byte key_debug; +extern int joykeys[2][5]; +extern int joykeystab[128]; +extern int syskeys[8]; + +struct keyb +{ + int keybcode; + char *keybname; +}; + +extern struct keyb keybtab[]; + +#ifdef OPENEMU +#endif + +#define KEY_W 0 +#define KEY_S 0 +#define KEY_A 0 +#define KEY_D 0 +#define KEY_SPACE 0 +#define KEY_UP 0 +#define KEY_DOWN 0 +#define KEY_LEFT 0 +#define KEY_RIGHT 0 +#define KEY_L 0 +#define KEY_F12 0 +#define KEY_F1 0 +#define KEY_F4 0 +#define KEY_F5 0 +#define KEY_F8 0 +#define KEY_F2 0 +#define KEY_F3 0 +#define KEY_F6 0 +#define KEY_ESC 0 +#define KEY_ALT 0 +#define KEY_ENTER 0 + +#define KEY_0 0 +#define KEY_1 0 +#define KEY_2 0 +#define KEY_3 0 +#define KEY_4 0 +#define KEY_5 0 +#define KEY_6 0 +#define KEY_7 0 +#define KEY_8 0 +#define KEY_9 0 +#define KEY_SLASH 0 +#define KEY_P 0 +#define KEY_PLUS_PAD 0 +#define KEY_E 0 +#define KEY_R 0 +#define KEY_T 0 +#define KEY_U 0 +#define KEY_I 0 +#define KEY_O 0 +#define KEY_Q 0 +#define KEY_F 0 +#define KEY_G 0 +#define KEY_H 0 +#define KEY_J 0 +#define KEY_K 0 +#define KEY_Z 0 +#define KEY_X 0 +#define KEY_C 0 +#define KEY_V 0 +#define KEY_B 0 +#define KEY_M 0 +#define KEY_STOP 0 +#define KEY_MINUS 0 +#define KEY_ASTERISK 0 +#define KEY_SLASH_PAD 0 +#define KEY_EQUALS 0 +#define KEY_Y 0 +#define KEY_N 0 +#define KEY_DEL 0 + +#endif + diff --git a/clean/src/main.c b/clean/src/main.c new file mode 100755 index 0000000..ddd3c5a --- /dev/null +++ b/clean/src/main.c @@ -0,0 +1,922 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + */ +#include +#include +#include +#include +#include +#include +#include "crc32.h" +#include "audio.h" +#include "vmachine.h" +#include "config.h" +#include "vdc.h" +#include "cpu.h" +#include "debug.h" +#include "keyboard.h" +#include "voice.h" +#include "allegro.h" +#include "score.h" +#ifdef ALLEGRO_WINDOWS +#include "winalleg.h" +#endif +static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC], + biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC], + odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC], + bios_l[MAXC], file_v[MAXC], scorefile[MAXC], statefile[MAXC], + path[MAXC]; +FILE *f; +char name_f, rom_f, c_j; +char pathx, *k, *launcher_flag_r, *launcher_flag_b, identify; +int file_name(char *pathx); +int suck_bios(); +int suck_roms(); +int identify_bios(char *identify); +int contax, o2flag, g74flag, c52flag, jopflag, helpflag; +int j; +unsigned long crcx = ~0; +static long filesize(FILE * stream); +static void load_bios(const char *biosname); +static void load_cart(char *file); +static void helpus(void); +int parse_option(char *attr, char *val); +void read_default_config(void); + +int main(int argc, char *argv[]) +{ + int i, cnt, cnt2; + static char file[MAXC], attr[MAXC], val[MAXC], *p, *binver; +#if defined(ALLEGRO_WINDOWS) + binver = "Windows binary"; +#elif defined(ALLEGRO_DOS) + binver = "DOS binary"; +#elif defined(ALLEGRO_LINUX) + binver = "Linux binary"; +#elif defined(ALLEGRO_BEOS) + binver = "BEOS binary"; +#elif defined(ALLEGRO_QNX) + binver = "QNX binary"; +#elif defined(ALLEGRO_UNIX) + binver = "UNIX binary"; +#elif defined(ALLEGRO_MPW) + binver = "MacOS binary"; +#else + binver = "Unknown binary"; +#endif + printf("%s %s\n", "\nO2EM v" O2EM_VERSION " " RELEASE_DATE " - ", binver); + printf( + "Free Odyssey2 / Videopac+ Emulator - http://o2em.sourceforge.net\n"); + printf("Created by Daniel Boris (c)1996/1998\n"); + printf("Developed by:\n"); + printf(" Andre de la Rocha since version 0.80\n"); + printf(" Arlindo M. de Oliveira since version 1.16\n"); + printf("\n"); + app_data.debug = 0; + app_data.stick[0] = app_data.stick[1] = 1; + app_data.sticknumber[0] = app_data.sticknumber[1] = 0; + set_defjoykeys(0, 0); + set_defjoykeys(1, 1); + set_defsystemkeys(); + app_data.bank = 0; + app_data.limit = 1; + app_data.sound_en = 1; + app_data.speed = 100; + app_data.wsize = 2; +#ifdef ALLEGRO_DOS + app_data.fullscreen = 1; +#else + app_data.fullscreen = 0; +#endif + app_data.scanlines = 0; + app_data.voice = 1; + app_data.window_title = "O2EM v" O2EM_VERSION; + app_data.svolume = 100; + app_data.vvolume = 100; + app_data.filter = 0; + app_data.exrom = 0; + app_data.three_k = 0; + app_data.crc = 0; + app_data.scshot = scshot; + app_data.statefile = statefile; + app_data.euro = 0; + app_data.openb = 0; + app_data.vpp = 0; + app_data.bios = 0; + app_data.scoretype = 0; + app_data.scoreaddress = 0; + app_data.default_highscore = 0; + app_data.breakpoint = 65535; + app_data.megaxrom = 0; + strcpy(file, ""); + strcpy(file_l, ""); + strcpy(bios_l, ""); + strcpy(bios, ""); + strcpy(scshot, ""); + strcpy(statefile, ""); + strcpy(xrom, ""); + strcpy(scorefile, "highscore.txt"); + read_default_config(); + if (argc >= 2) { + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + strncat(file, argv[i], MAXC - 1); + file[MAXC - 1] = 0; + strcpy(file_v, file); + } else { + p = strtok(argv[i], "="); + if (p) { + strncpy(attr, p + 1, MAXC - 1); + attr[MAXC - 1] = 0; + } else { + strcpy(attr, ""); + } + p = strtok(NULL, "="); + if (p) { + strncpy(val, p, MAXC - 1); + val[MAXC - 1] = 0; + if (!strcmp(attr, "romdir") || !strcmp(attr, "ROMDIR")) { + strcpy(romdir, val); + strcat(romdir, file); + strcpy(file, romdir); + strcpy(romdir, val); + } + if (!strcmp(attr, "biosdir") || !strcmp(attr, "BIOSDIR")) { + strcpy(biosdir, val); + } + } else { + strcpy(val, ""); + } + strlwr(attr); + if (!parse_option(attr, val)) { + exit(EXIT_FAILURE); + } + } + } + if (helpflag) { + helpus(); + } + if (strlen(file) == 0) { + fprintf(stderr, "Error: file name missing\n"); + exit(EXIT_FAILURE); + } + printf("Starting emulation ...\n"); + allegro_init (); + install_timer(); + init_audio(); + printf("Using Allegro %s\n", allegro_id); + /********************** ROMs if Launcher running... */ + k = strchr(romdir, '/'); + launcher_flag_r = strchr(file, '\\'); + if (k != 0) { + strcpy(xrom, romdir); + } else if (!launcher_flag_r) { + strcpy(xrom, "roms/"); + strcpy(romdir, file); + strcpy(file, xrom); + strcat(file, romdir); + strcpy(romdir, xrom); + } else { + cnt = 0; + cnt2 = 0; + for (cnt = 0; file[cnt] != '\0'; cnt = cnt + 1) { + if (file[cnt] == '\\') { + cnt2 = cnt; + } + } + for (cnt = 0; cnt <= cnt2; cnt++) { + file_l[cnt] = file[cnt]; + } + strcpy(romdir, file_l); + strcpy(xrom, romdir); + } + file_name(xrom); + if (contax < 3) { + printf("\nROMs directory empty!\n"); + exit(EXIT_FAILURE); + } + app_data.crc = crc32_file(file); + crcx = app_data.crc; + suck_roms(); + launcher_flag_b = strchr(bios, '\\'); + + if (!launcher_flag_b) { + k = strchr(biosdir, '/'); + if (k != 0) { + strcpy(xbios, biosdir); + } else { + strcpy(xbios, "bios/"); + strcpy(biosdir, xbios); + } + file_name(xbios); + if (contax < 3) { + printf("\nBIOS directory empty!\n"); + exit(EXIT_FAILURE); + } + suck_bios(); + c_j = strcmp(bios, "jopac"); + if ((rom_f != 1) && (c_j != 0)) { + strcpy(bios, g7400); + } + if ((!o2flag) && (!jopflag) && (!c52flag) && (!g74flag)) { + printf("\ndir '%s' without BIOS !\n", biosdir); + exit(EXIT_FAILURE); + } + printf("BIOS found:\n"); + if (!strcmp(bios, "g7400")) { + strcpy(bios, g7400); + if (g74flag != 1) { + printf("\nG7400 BIOS not found !\n"); + exit(EXIT_FAILURE); + } + } + if (g74flag) + printf(" G7400 VP+\n"); + if (!strcmp(bios, "c52")) { + strcpy(bios, c52); + if (c52flag != 1) { + printf("\nC52 BIOS not found !\n"); + exit(EXIT_FAILURE); + } + } + if (c52flag) + printf(" C52\n"); + if (!strcmp(bios, "jopac")) { + strcpy(bios, jopac); + if (jopflag != 1) { + printf("\nJOPAC BIOS not found !\n"); + exit(EXIT_FAILURE); + } + } + if (jopflag) + printf(" JOPAC VP+\n"); + if ((!strcmp(bios, "")) || (!strcmp(bios, "o2rom"))) { + strcpy(bios, odyssey2); + if ((!o2flag) && (!c52flag) && (rom_f)) { + printf("Odyssey2 BIOS not found !\n"); + exit(EXIT_FAILURE); + } + if ((!o2flag) && (c52flag) && (rom_f)) { + printf("\nOdyssey2 BIOS not found !\n"); + printf("Loading C52 BIOS ... "); + strcpy(bios, c52); + } + } + if (o2flag) + printf(" Odyssey 2\n"); + } + if (launcher_flag_b) { + identify_bios(bios); + if (rom_f != 1) { + if (!((g74flag) || (jopflag))) { + fprintf(stderr, "\nError: ROM only VP+ BIOS"); + exit(EXIT_FAILURE); + } + } + } else { + if (rom_f != 1) { + if (!((g74flag) || (jopflag))) { + printf("\nROM only VP+ BIOS\n"); + exit(EXIT_FAILURE); + } + if (!(g74flag)) { + printf("\nVP+ G7400 BIOS not found !"); + printf("\nLoading VP+ Jopac BIOS ..."); + strcpy(bios, jopac); + } + } + } + load_bios(bios); + load_cart(file); + if (app_data.voice) + load_voice_samples(path); + init_display(); + init_cpu(); + init_system(); + set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore); + int stateError; + if ((stateError = loadstate(app_data.statefile)) == 0) { + printf("Savefile loaded."); + } else if (stateError >= 199) { + if (stateError == 199) + fprintf(stderr, "Wrong ROM-File for Savefile."); + else if (stateError == 200 + ROM_O2) + fprintf(stderr, "Wrong BIOS for Savefile: O2ROM needed."); + else if (stateError == 200 + ROM_G7400) + fprintf(stderr, "Wrong BIOS for Savefile: G7400 ROM needed."); + else if (stateError == 200 + ROM_C52) + fprintf(stderr, "Wrong BIOS for Savefile: C52 ROM needed."); + else if (stateError == 200 + ROM_JOPAC) + fprintf(stderr, "Wrong BIOS for Savefile: JOPAC ROM needed."); + else + fprintf(stderr, "Wrong BIOS for Savefile: UNKNOWN ROM needed."); + return (0); + } + if (app_data.debug) + key_debug = 1; +#ifndef _DEBUG +#ifdef ALLEGRO_WINDOWS + FreeConsole (); +#endif +#endif + run(); + if (app_data.scoretype != 0) + save_highscore(get_score(app_data.scoretype, app_data.scoreaddress), + scorefile); + exit(EXIT_SUCCESS); + } + if (!strcmp(attr, "help") || !strcmp(attr, "HELP")) + helpus(); + printf("type o2em -help\n"); + exit(EXIT_SUCCESS); +} + +END_OF_MAIN (); + +int parse_option(char *attr, char *val) +{ + int control_scheme; + if (!strcmp(attr, "nolimit")) { + app_data.limit = !(val[0] != '0'); + } else if (!strcmp(attr, "nosound")) { + app_data.sound_en = !(val[0] != '0'); + } else if (!strcmp(attr, "novoice")) { + app_data.voice = !(val[0] != '0'); + } else if (!strcmp(attr, "filter")) { + app_data.filter = (val[0] != '0'); + } else if (!strcmp(attr, "debug")) { + app_data.debug = (val[0] != '0'); + } else if ((!strcmp(attr, "s1")) || (!strcmp(attr, "s2"))) { + int stick_number; + stick_number = (!strcmp(attr, "s1")) ? 0 : 1; + if (strlen(val) < 2) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 3)) { + if ((control_scheme == 1) || (control_scheme == 2)) { + app_data.stick[stick_number] = 1; + set_defjoykeys(stick_number, control_scheme - 1); + } else { + app_data.stick[stick_number] = (control_scheme == 0) ? 0 : 2; + if (control_scheme == 3) { + app_data.sticknumber[stick_number] = app_data.sticknumber[0] + + app_data.sticknumber[1] + 1; + } + set_joykeys(stick_number, 0, 0, 0, 0, 0); + } + } else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else { + char *p, *s; + int i, k, code, nk, codes[5]; + strupr(val); + nk = 0; + p = strtok(val, ","); + while (p) { + i = code = 0; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + while (k && (code == 0)) { + if (strcmp(s, p) == 0) + code = k; + i++; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + } + if (!code) { + fprintf(stderr, + "Invalid value for option %s : key %s unknown\n", + attr, p); + return 0; + } + codes[nk] = code; + p = strtok(NULL, ","); + nk++; + if (nk > 5) { + fprintf( + stderr, + "Invalid value for option %s : invalid number of keys\n", + attr); + return 0; + } + } + if (nk != 5) { + fprintf( + stderr, + "Invalid value for option %s : invalid number of keys\n", + attr); + return 0; + } + app_data.stick[stick_number] = 1; + set_joykeys(stick_number, codes[0], codes[1], codes[2], codes[3], codes[4]); + } + } else if (!strcmp(attr, "s0")) { + char *p, *s; + int i, k, code, nk, codes[8]; + strupr(val); + nk = 0; + p = strtok(val, ","); + while (p) { + i = code = 0; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + while (k && (code == 0)) { + if (strcmp(s, p) == 0) + code = k; + i++; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + } + if (!code) { + fprintf(stderr, + "Invalid value for option %s : key %s unknown\n", attr, + p); + return 0; + } + codes[nk] = code; + p = strtok(NULL, ","); + nk++; + if (nk > 8) { + fprintf( + stderr, + "Invalid value for option %s : invalid number of keys\n", + attr); + return 0; + } + } + if (nk != 8) { + fprintf(stderr, + "Invalid value for option %s : invalid number of keys\n", + attr); + return 0; + } + set_systemkeys(codes[0], codes[1], codes[2], codes[3], codes[4], + codes[5], codes[6], codes[7]); + } else if (!strcmp(attr, "speed")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme > 0) && (control_scheme <= 10000)) + app_data.speed = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else if (!strcmp(attr, "svolume")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 100)) + app_data.svolume = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + if (control_scheme == 0) + app_data.sound_en = 0; + } else if (!strcmp(attr, "vvolume")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 100)) + app_data.vvolume = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + if (control_scheme == 0) + app_data.voice = 0; + } else if (!strcmp(attr, "wsize")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme > 0) && (control_scheme < 5)) { + app_data.wsize = control_scheme; + app_data.fullscreen = 0; + } else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else if (!strcmp(attr, "fullscreen")) { + app_data.fullscreen = (val[0] != '0'); + } else if (!strcmp(attr, "scanlines")) { + app_data.scanlines = (val[0] != '0'); + } else if (!strcmp(attr, "scshot")) { + strcpy(scshot, val); + } else if (!strcmp(attr, "savefile")) { + strcpy(statefile, val); + } else if (!strcmp(attr, "biosdir")) { + strcpy(xbios, val); + } else if (!strcmp(attr, "bios")) { + strcpy(bios, val); + } else if (!strcmp(attr, "romdir")) { + strcpy(xrom, val); + } else if (!strcmp(attr, "help")) { + helpflag = 1; + } else if (!strcmp(attr, "euro")) { + app_data.euro = (val[0] != '0'); + } else if (!strcmp(attr, "exrom")) { + app_data.exrom = (val[0] != '0'); + } else if (!strcmp(attr, "3k")) { + app_data.three_k = (val[0] != '0'); + } else if (!strcmp(attr, "g7400")) { + strcpy(bios, "g7400"); + } else if (!strcmp(attr, "c52")) { + strcpy(bios, "c52"); + } else if (!strcmp(attr, "jopac")) { + strcpy(bios, "jopac"); + } else if (!strcmp(attr, "o2rom")) { + strcpy(bios, "o2rom"); + } else if (!strcmp(attr, "scorefile")) { + strcpy(scorefile, val); + } else if (!strcmp(attr, "scoreadr")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 255)) + app_data.scoreaddress = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else if (!strcmp(attr, "scoretype")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 9999)) + app_data.scoretype = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else if (!strcmp(attr, "score")) { + control_scheme = -1; + sscanf(val, "%d", &control_scheme); + if ((control_scheme >= 0) && (control_scheme <= 999999)) + app_data.default_highscore = control_scheme; + else { + fprintf(stderr, "Invalid value for option %s\n", attr); + return 0; + } + } else { + if (!helpflag) { + fprintf(stderr, "Invalid option : %s\n", attr); + return 0; + } + } + return 1; +} + +void read_default_config(void) +{ + FILE *f; + static char attr[MAXC], val[MAXC], s[MAXC]; + char *p, *fn; + int i, l; + fn = "o2em_def.cfg"; + f = fopen(fn, "r"); + if (!f) { + fn = "O2EM_DEF.CFG"; + f = fopen(fn, "r"); + } + if (!f) + return; + + l = 0; + while (fgets(s, MAXC - 1, f)) { + l++; + p = s; + while (*p && (isspace (*p))) + p++; + if (*p && (*p != '#')) { + i = 0; + while (*p && (!isspace (*p)) && (*p != '=')) + attr[i++] = *p++; + attr[i] = 0; + while (*p && (isspace (*p))) + p++; + i = 0; + if (*p == '=') { + p++; + while (*p && (isspace (*p))) + p++; + if (*p == '"') { + p++; + while (*p && (*p != '"') && (*p != '\n') && (*p != '\r')) + val[i++] = *p++; + } else { + while (*p && (!isspace (*p))) + val[i++] = *p++; + } + } + val[i] = 0; + if (strlen(attr) > 0) { + strlwr(attr); + if (!parse_option(attr, val)) { + printf("Error in the %s file at line number %d !\n\n", fn, + l); + } + } + } + } + fclose(f); +} + +static long filesize(FILE * stream) +{ + long curpos, length; + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + fseek(stream, curpos, SEEK_SET); + return length; +} + +static void load_bios(const char *biosname) +{ + FILE *fn; + static char s[MAXC + 10]; + unsigned long crc; + int i; + + if ((biosname[strlen(biosname) - 1] == '/') + || (biosname[strlen(biosname) - 1] == '\\') + || (biosname[strlen(biosname) - 1] == ':')) { + strcpy(s, biosname); + strcat(s, odyssey2); + fn = fopen(s, "rb"); + + if (!fn) { + strcpy(s, biosname); + strcat(s, odyssey2); + fn = fopen(s, "rb"); + } + } else { + strcpy(s, biosname); + fn = fopen(biosname, "rb"); + } + + if (!fn) { + fprintf(stderr, "Error loading bios ROM (%s)\n", s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0], 1024, 1, fn) != 1) { + fprintf(stderr, "Error loading bios ROM %s\n", odyssey2); + exit(EXIT_FAILURE); + } + strcpy(s, biosname); + fn = fopen(biosname, "rb"); + if (!fn) { + fprintf(stderr, "Error loading bios ROM (%s)\n", s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0], 1024, 1, fn) != 1) { + fprintf(stderr, "Error loading bios ROM %s\n", odyssey2); + exit(EXIT_FAILURE); + } + fclose(fn); + for (i = 1; i < 8; i++) { + memcpy(rom_table[i], rom_table[0], 1024); + } + crc = crc32_buf(rom_table[0], 1024); + if (crc == 0x8016A315) { + printf("Odyssey2 bios ROM loaded\n"); + app_data.vpp = 0; + app_data.bios = ROM_O2; + } else if (crc == 0xE20A9F41) { + printf("Videopac+ G7400 bios ROM loaded\n"); + app_data.vpp = 1; + app_data.bios = ROM_G7400; + } else if (crc == 0xA318E8D6) { + if (!((!o2flag) && (c52flag))) + printf("C52 bios ROM loaded\n"); + else + printf("Ok\n"); + app_data.vpp = 0; + app_data.bios = ROM_C52; + + } else if (crc == 0x11647CA5) { + if (g74flag) + printf("Jopac bios ROM loaded\n"); + else + printf(" Ok\n"); + app_data.vpp = 1; + app_data.bios = ROM_JOPAC; + } else { + printf("Bios ROM loaded (unknown version)\n"); + app_data.vpp = 0; + app_data.bios = ROM_UNKNOWN; + } +} + +static void load_cart(char *file) +{ + FILE *fn; + long l; + int i, nb; + app_data.crc = crc32_file(file); + if (app_data.crc == 0xAFB23F89) + app_data.exrom = 1; /* Musician */ + if (app_data.crc == 0x3BFEF56B) + app_data.exrom = 1; /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) + app_data.exrom = 1; /* Four in 1 Row! (french) */ + + if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) + && (!app_data.debug)) { + fprintf(stderr, "Error: file %s is an incomplete ROM dump\n", file_v); + exit(EXIT_FAILURE); + } + + fn = fopen(file, "rb"); + if (!fn) { + fprintf(stderr, "Error loading %s\n", file_v); + exit(EXIT_FAILURE); + } + printf("Loading: \"%s\" Size: ", file_v); + l = filesize(fn); + if ((l % 1024) != 0) { + fprintf(stderr, "Error: file %s is an invalid ROM dump\n", file_v); + exit(EXIT_FAILURE); + } + + /* special MegaCART design by Soeren Gust */ + if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144) + || (l == 524288) || (l == 1048576)) { + app_data.megaxrom = 1; + app_data.bank = 1; + megarom = malloc(1048576); + if (megarom == NULL) { + fprintf(stderr, "Out of memory loading %s\n", file); + exit(EXIT_FAILURE); + } + if (fread(megarom, l, 1, fn) != 1) { + fprintf(stderr, "Error loading %s\n", file); + exit(EXIT_FAILURE); + } + + /* mirror shorter files into full megabyte */ + if (l < 65536) + memcpy(megarom + 32768, megarom, 32768); + if (l < 131072) + memcpy(megarom + 65536, megarom, 65536); + if (l < 262144) + memcpy(megarom + 131072, megarom, 131072); + if (l < 524288) + memcpy(megarom + 262144, megarom, 262144); + if (l < 1048576) + memcpy(megarom + 524288, megarom, 524288); + /* start in bank 0xff */ + memcpy(&rom_table[0][1024], megarom + 4096 * 255 + 1024, 3072); + printf("MegaCart %ldK", l / 1024); + nb = 1; + } else if (((l % 3072) == 0)) { + app_data.three_k = 1; + nb = l / 3072; + + for (i = nb - 1; i >= 0; i--) { + if (fread(&rom_table[i][1024], 3072, 1, fn) != 1) { + fprintf(stderr, "Error loading %s\n", file); + exit(EXIT_FAILURE); + } + } + printf("%dK", nb * 3); + } else { + nb = l / 2048; + if ((nb == 2) && (app_data.exrom)) { + if (fread(&extROM[0], 1024, 1, fn) != 1) { + fprintf(stderr, "Error loading %s\n", file); + exit(EXIT_FAILURE); + } + if (fread(&rom_table[0][1024], 3072, 1, fn) != 1) { + fprintf(stderr, "Error loading %s\n", file); + exit(EXIT_FAILURE); + } + printf("3K EXROM"); + } else { + for (i = nb - 1; i >= 0; i--) { + if (fread(&rom_table[i][1024], 2048, 1, fn) != 1) { + fprintf(stderr, "Error loading %s\n", file); + exit(EXIT_FAILURE); + } + memcpy(&rom_table[i][3072], &rom_table[i][2048], 1024); /* simulate missing A10 */ + } + printf("%dK", nb * 2); + } + } + fclose(fn); + rom = rom_table[0]; + if (nb == 1) + app_data.bank = 1; + else if (nb == 2) + app_data.bank = app_data.exrom ? 1 : 2; + else if (nb == 4) + app_data.bank = 3; + else + app_data.bank = 4; + + if ((rom_table[nb - 1][1024 + 12] == 'O') + && (rom_table[nb - 1][1024 + 13] == 'P') + && (rom_table[nb - 1][1024 + 14] == 'N') + && (rom_table[nb - 1][1024 + 15] == 'B')) + app_data.openb = 1; + + printf(" CRC: %08lX\n", app_data.crc); +} + +/*************************** Helpus*/ +void helpus(void) +{ + allegro_init (); + install_timer(); + init_display(); + init_system(); +#ifdef ALLEGRO_WINDOWS + FreeConsole (); +#endif + help(); + exit(EXIT_SUCCESS); +} + +int file_name(char *pathx) +{ + DIR *dir_p; + struct dirent *dir_entry_p; + contax = 0; + dir_p = opendir(pathx); + if (dir_p == NULL) { + fprintf(stderr, "dir '%s' not found !\n", pathx); + exit(-1); + } + while (0 != (dir_entry_p = readdir(dir_p))) { + strcpy(arkivo[contax], dir_entry_p->d_name); + contax++; + } + closedir(dir_p); + return (0); +} + +/********************* Search BIOS */ +int suck_bios() +{ + int i; + for (i = 0; i < contax; ++i) { + strcpy(biossux, biosdir); + strcat(biossux, arkivo[i]); + identify_bios(biossux); + } + return (0); +} + +/********************* Search ROM */ +int suck_roms() +{ + int i; + rom_f = 1; + for (i = 0; i < contax; ++i) { + strcpy(romssux, romdir); + strcat(romssux, arkivo[i]); + app_data.crc = crc32_file(romssux); + if (app_data.crc == crcx) { + if ((app_data.crc == 0xD7089068) || (app_data.crc == 0xB0A7D723) + || (app_data.crc == 0x0CA26992) + || (app_data.crc == 0x0B6EB25B) + || (app_data.crc == 0x06861A9C) + || (app_data.crc == 0xB2F0F0B4) + || (app_data.crc == 0x68560DC7) + || (app_data.crc == 0x0D2D721D) + || (app_data.crc == 0xC4134DF8) + || (app_data.crc == 0xA75C42F8)) { + rom_f = 0; + } + } + } + return 0; +} + +/********************* Ready BIOS */ +int identify_bios(char *biossux) +{ + app_data.crc = crc32_file(biossux); + if (app_data.crc == 0x8016A315) { + strcpy(odyssey2, biossux); + o2flag = 1; + } + if (app_data.crc == 0xE20A9F41) { + strcpy(g7400, biossux); + g74flag = 1; + } + if (app_data.crc == 0xA318E8D6) { + strcpy(c52, biossux); + c52flag = 1; + } + if (app_data.crc == 0x11647CA5) { + strcpy(jopac, biossux); + jopflag = 1; + } + return (0); +} diff --git a/clean/src/o2em.png b/clean/src/o2em.png new file mode 100755 index 0000000000000000000000000000000000000000..1febae9e7c926428344d8c63752b659b9c69d636 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPmx1fkMa=-le(Yxo;x+3Iho zVS>vs|IWRwKF9TF`dQ&u%mSgZ=ML(hniW2Q8LT%UU;e?lw?CO61~D*1gzl0p`~C5v z(c|jF^^DqfMG%QMw)_E07v;aRTQ4%}2!4LtEc28G7mvv4FO#liofBygg literal 0 HcmV?d00001 diff --git a/clean/src/o2em.rc b/clean/src/o2em.rc new file mode 100755 index 0000000..8960011 --- /dev/null +++ b/clean/src/o2em.rc @@ -0,0 +1,3 @@ +#include + +allegro_icon ICON DISCARDABLE "o2em.ico" diff --git a/clean/src/o2em.res b/clean/src/o2em.res new file mode 100755 index 0000000000000000000000000000000000000000..6c5d4e16f1c50a4171f60f2c70f467ed599b6d84 GIT binary patch literal 5982 zcmeI0F-{yo5JhX)l@=t+0YW$>a6sh9fddC?EQBo~K)wJ02{Asv_Cb6EAHjhG2R;ag zARAZB_#vjef44_+#xzX7t>6FmvC$G7f@ zvE$Fu?5D$;->*-Cq0W3hGAl2gS5C*1^`_hZ-5PywZuTwAKG-kLQvCZ?_`m!53;ST_ z{&i|+_Qfvk+CJMy=Y_BR@aNdi&A9i^2Ncd@f0q6fe;V8M*~fm5Jh#8HGSyQDrVc#E z4m4ZFww`Q>_kV&nY%=9HcVI*7x~0wOzyA!^Y(j3$(m+x^r4PbhD4)`&{ICP6Pf8!A z|LuRyQ7f`vURQdpZ_4)_$oXXuI^Vv7m&!YqR_a@hLA?wso`IJr$DxcEHLFH3A zIjDR}CkK^J>ExjDDV-ctKBbe(#IKnBxmG#!?9Vkm#q7_u%Asd}uJI{mf38&yJ^OQw zPci#*t#atuPo3APq4Fu698^A~lY`2qbaGJnluiyRpVG-eSt3_fZJ!;@(%nq@w2FOv z8q0|NhvDascgOihvc%iR_pObX_qznU{*8QZf6ijQQ5*g9Bg7AHEW217Cho15%eK2E ajvM9X@veGdaSI(|F}O32OPra_ef|TLo!mYE literal 0 HcmV?d00001 diff --git a/clean/src/score.c b/clean/src/score.c new file mode 100755 index 0000000..317420d --- /dev/null +++ b/clean/src/score.c @@ -0,0 +1,144 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * + * http://o2em.sourceforge.net + * + * + * + * Score loading/saving by manopac + */ + +#include +#include +#include +#include +#include +#include +#include +#include "vmachine.h" +#include "types.h" +#include "score.h" + +/*-------------------------------------------------- + Calculate Score from given Values + Scoretype = abcd: + ramtype a = 1: ext ram / 2: int ram + valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit + directíon c = 1: higher value digits first / 2: low value digits first + count d = number of digits + --------------------------------------------------*/ +int get_score(int scoretype, int scoreaddress) +{ + int score=0; + + if (scoretype!=0) + { + int position; + int i; + Byte *RAM; + + int count = scoretype%10; + int direction = ((scoretype/10)%10)==1?1:-1; + float valuetype = (float) (3-((scoretype/100)%10))/2; + int ramtype = scoretype/1000; + + position = scoreaddress+ (direction==1?0:(count*valuetype-1)); + RAM = ramtype==1?extRAM:intRAM; + + for(i=0;i>(((i+1)%2)*4)*(abs((int) ((valuetype-1)*2))))&15); + } + } + + return(score); +} + +/*-------------------------------------------------- + Set HighScore into Memory + Scoretype = abcd: + ramtype a = 1: ext ram / 2: int ram + valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit + directíon c = 1: higher value digits first / 2: low value digits first + count d = number of digits + --------------------------------------------------*/ + +void set_score(int scoretype, int scoreaddress, int score) +{ + + if (scoretype!=0 && score>0) + { + int position; + int i; + Byte *RAM; + int digit; + + int count = scoretype%10; + int direction = ((scoretype/10)%10)==1?-1:1; + float valuetype = (float) (3-((scoretype/100)%10))/2; + int ramtype = scoretype/1000; + + position = scoreaddress+ (direction==1?0:(count*valuetype-1)); + RAM = ramtype==1?extRAM:intRAM; + + for(i=count-1;i>=0;i--) + { + digit = score / power(10,i); + RAM[position+(int)(valuetype*i*direction)]=((valuetype==0.5)&&(i%2==0))?(RAM[position+(int)(valuetype*i*direction)]<<4)+digit:digit; + score = score - digit*power(10,i); + } + } +} + + + +/*----------------------------------------------------- + Save Highscore to File +-------------------------------------------------------*/ +void save_highscore(int highscore,char *scorefile) +{ + FILE *fn; + + highscore = highscore==app_data.default_highscore?0:highscore; + + fn = fopen(scorefile,"w"); + if (fn==NULL) { + fprintf(stderr,"Error opening highscore-file %s: %i\n",scorefile,errno); + exit(EXIT_FAILURE); + } + + if (fprintf(fn,"%i",highscore)<=0) + { + fprintf(stderr,"Error writing to highscore-file %s: %i\n",scorefile,errno); + exit(EXIT_FAILURE); + } + + fclose(fn); +} + + +/*********************************** + Integer-Implementation of pow + ***********************************/ +int power(int base, int higher) +{ + if (higher==0) { + return(1); + } else if (higher==1) { + return(base); + } else { + int i; + int value=base; + + for (i=2;i<=higher;i++) + { + value = value*base; + } + return(value); + } +} diff --git a/clean/src/score.h b/clean/src/score.h new file mode 100755 index 0000000..0868801 --- /dev/null +++ b/clean/src/score.h @@ -0,0 +1,10 @@ +#ifndef __SCORE_H +#define __SCORE_H + +int get_score(int scoretype, int scoreaddress); +void set_score(int scoretype, int scoreaddress, int highscore); +void save_highscore(int highscore,char *scorefile); +int power(int base, int higher); + +#endif + diff --git a/clean/src/table.c b/clean/src/table.c new file mode 100755 index 0000000..49169b4 --- /dev/null +++ b/clean/src/table.c @@ -0,0 +1,341 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * 8048 Mnemonics + */ + + +#include "cpu.h" +#include "table.h" + + +struct lookup_tag lookup[] = { + + /* 00 */ {"NOP",1,0}, + /* 01 */ {"ILL",1,0}, + /* 02 */ {"OUTL BUS,A",1,0}, + /* 03 */ {"ADD A,",2,1}, + + /* 04 */ {"JMP",2,2}, + /* 05 */ {"EN I",1,0}, + /* 06 */ {"ILL",1,0}, + /* 07 */ {"DEC A",1,0}, + + /* 08 */ {"INS A,BUS",1,0}, + /* 09 */ {"IN A,P1",1,0}, + /* 0A */ {"IN A,P2",1,0}, + /* 0B */ {"ILL",1,0}, + + /* 0C */ {"MOVD A,P4",1,0}, + /* 0D */ {"MOVD A,P5",1,0}, + /* 0E */ {"MOVD A,P6",1,0}, + /* 0F */ {"MOVD A,P7",1,0}, + + /* 10 */ {"INC @R0",1,0}, + /* 11 */ {"INC @R1",1,0}, + /* 12 */ {"JB0",2,3}, + /* 13 */ {"ADDC A,",2,1}, + + /* 14 */ {"CALL",2,2}, + /* 15 */ {"DIS I",1,0}, + /* 16 */ {"JTF",2,3}, + /* 17 */ {"INC A",1,0}, + + /* 18 */ {"INC R0",1,0}, + /* 19 */ {"INC R1",1,0}, + /* 1A */ {"INC R2",1,0}, + /* 1B */ {"INC R3",1,0}, + + /* 1C */ {"INC R4",1,0}, + /* 1D */ {"INC R5",1,0}, + /* 1E */ {"INC R6",1,0}, + /* 1F */ {"INC R7",1,0}, + + /* 20 */ {"XCH A,@R0",1,0}, + /* 21 */ {"XCH A,@R1",1,0}, + /* 22 */ {"ILL",1,0}, + /* 23 */ {"MOV A,",2,1}, + + /* 24 */ {"JMP",2,2}, + /* 25 */ {"EN TCNTI",1,0}, + /* 26 */ {"JNT0",2,3}, + /* 27 */ {"CLR A",1,0}, + + /* 28 */ {"XCH A,R0",1,0}, + /* 29 */ {"XCH A,R1",1,0}, + /* 2A */ {"XCH A,R2",1,0}, + /* 2B */ {"XCH A,R3",1,0}, + + /* 2C */ {"XCH A,R4",1,0}, + /* 2D */ {"XCH A,R5",1,0}, + /* 2E */ {"XCH A,R6",1,0}, + /* 2F */ {"XCH A,R7",1,0}, + + /* 30 */ {"XCHD A,@R0",1,0}, + /* 31 */ {"XCHD A,@R1",1,0}, + /* 32 */ {"JB1",2,3}, + /* 33 */ {"ILL",1,0}, + + /* 34 */ {"CALL",2,2}, + /* 35 */ {"DIS TCNTI",1,0}, + /* 36 */ {"JT0",2,3}, + /* 37 */ {"CPL A",1,0}, + + /* 38 */ {"ILL",1,0}, + /* 39 */ {"OUTL P1,A",1,0}, + /* 3A */ {"OUTL P2,A",1,0}, + /* 3B */ {"ILL",1,0}, + + /* 3C */ {"MOVD P4,A",1,0}, + /* 3D */ {"MOVD P5,A",1,0}, + /* 3E */ {"MOVD P6,A",1,0}, + /* 3F */ {"MOVD P7,A",1,0}, + + /* 40 */ {"ORL A,@R0",1,0}, + /* 41 */ {"ORL A,@R1",1,0}, + /* 42 */ {"MOV A,T",1,0}, + /* 43 */ {"ORL A,",2,1}, + + /* 44 */ {"JMP",2,2}, + /* 45 */ {"STRT CNT",1,0}, + /* 46 */ {"JNT1",2,3}, + /* 47 */ {"SWAP",1,0}, + + /* 48 */ {"ORL A,R0",1,0}, + /* 49 */ {"ORL A,R1",1,0}, + /* 4A */ {"ORL A,R2",1,0}, + /* 4B */ {"ORL A,R3",1,0}, + + /* 4C */ {"ORL A,R4",1,0}, + /* 4D */ {"ORL A,R5",1,0}, + /* 4E */ {"ORL A,R6",1,0}, + /* 4F */ {"ORL A,R7",1,0}, + + /* 50 */ {"ANL A,@R0",1,0}, + /* 51 */ {"ANL A,@R1",1,0}, + /* 52 */ {"JB2",2,3}, + /* 53 */ {"ANL A,",2,1}, + + /* 54 */ {"CALL",2,2}, + /* 55 */ {"STRT T",1,0}, + /* 56 */ {"JT1",2,3}, + /* 57 */ {"ILL",1,0}, + + /* 58 */ {"ANL A,R0",1,0}, + /* 59 */ {"ANL A,R1",1,0}, + /* 5A */ {"ANL A,R2",1,0}, + /* 5B */ {"ANL A,R3",1,0}, + + /* 5C */ {"ANL A,R4",1,0}, + /* 5D */ {"ANL A,R5",1,0}, + /* 5E */ {"ANL A,R6",1,0}, + /* 5F */ {"ANL A,R7",1,0}, + + /* 60 */ {"ADD A,@R0",1,0}, + /* 61 */ {"ADD A,@R1",1,0}, + /* 62 */ {"MOV T,A",1,0}, + /* 63 */ {"ILL",1,0}, + + /* 64 */ {"JMP",2,2}, + /* 65 */ {"STOP TCNT",1,0}, + /* 66 */ {"ILL",1,0}, + /* 67 */ {"RRC A",1,0}, + + /* 68 */ {"ADD A,R0",1,0}, + /* 69 */ {"ADD A,R1",1,0}, + /* 6A */ {"ADD A,R2",1,0}, + /* 6B */ {"ADD A,R3",1,0}, + + /* 6C */ {"ADD A,R4",1,0}, + /* 6D */ {"ADD A,R5",1,0}, + /* 6E */ {"ADD A,R6",1,0}, + /* 6F */ {"ADD A,R7",1,0}, + + /* 70 */ {"ADDC A,@R0",1,0}, + /* 71 */ {"ADDC A,@R1",1,0}, + /* 72 */ {"JB3",2,3}, + /* 73 */ {"ILL",1,0}, + + /* 74 */ {"CALL",2,2}, + /* 75 */ {"ENT0 CLK",1,0}, + /* 76 */ {"JF1",2,3}, + /* 77 */ {"RR A",1,0}, + + /* 78 */ {"ADDC A,R0",1,0}, + /* 79 */ {"ADDC A,R1",1,0}, + /* 7A */ {"ADDC A,R2",1,0}, + /* 7B */ {"ADDC A,R3",1,0}, + + /* 7C */ {"ADDC A,R4",1,0}, + /* 7D */ {"ADDC A,R5",1,0}, + /* 7E */ {"ADDC A,R6",1,0}, + /* 7F */ {"ADDC A,R7",1,0}, + + /* 80 */ {"MOVX A,@R0",1,0}, + /* 81 */ {"MOVX A,@R1",1,0}, + /* 82 */ {"ILL",1,0}, + /* 83 */ {"RET",1,0}, + + /* 84 */ {"JMP",2,2}, + /* 85 */ {"CLR F0",1,0}, + /* 86 */ {"JNI",2,3}, + /* 87 */ {"ILL",1,0}, + + /* 88 */ {"ORL BUS,",2,1}, + /* 89 */ {"ORL P1,",2,1}, + /* 8A */ {"ORL P2,",2,1}, + /* 8B */ {"ILL",1,0}, + + /* 8C */ {"ORLD P4,A",1,0}, + /* 8D */ {"ORLD P5,A",1,0}, + /* 8E */ {"ORLD P6,A",1,0}, + /* 8F */ {"ORLD P7,A",1,0}, + + /* 90 */ {"MOVX @R0,A",1,0}, + /* 91 */ {"MOVX @R1,A",1,0}, + /* 92 */ {"JB4",2,3}, + /* 93 */ {"RETR",1,0}, + + /* 94 */ {"CALL",2,2}, + /* 95 */ {"CPL F0",1,0}, + /* 96 */ {"JNZ",2,3}, + /* 97 */ {"CLR C",1,0}, + + /* 98 */ {"ANL BUS,",2,1}, + /* 99 */ {"ANL P1,",2,1}, + /* 9A */ {"ANL P2,",2,1}, + /* 9B */ {"ILL",1,0}, + + /* 9C */ {"ANLD P4,A",1,0}, + /* 9D */ {"ANLD P5,A",1,0}, + /* 9E */ {"ANLD P6,A",1,0}, + /* 9F */ {"ANLD P7,A",1,0}, + + /* A0 */ {"MOV @R0,A",1,0}, + /* A1 */ {"MOV @R1,A",1,0}, + /* A2 */ {"ILL",1,0}, + /* A3 */ {"MOVP A,@A",1,0}, + + /* A4 */ {"JMP",2,2}, + /* A5 */ {"CLR F1",1,0}, + /* A6 */ {"ILL",1,0}, + /* A7 */ {"CPL C",1,0}, + + /* A8 */ {"MOV R0,A",1,0}, + /* A9 */ {"MOV R1,A",1,0}, + /* AA */ {"MOV R2,A",1,0}, + /* AB */ {"MOV R3,A",1,0}, + /* AC */ {"MOV R4,A",1,0}, + /* AD */ {"MOV R5,A",1,0}, + /* AE */ {"MOV R6,A",1,0}, + /* AF */ {"MOV R7,A",1,0}, + + /* B0 */ {"MOV @R0,",2,1}, + /* B1 */ {"MOV @R1,",2,1}, + /* B2 */ {"JB5",2,3}, + /* B3 */ {"JMPP @A",1,0}, + + /* B4 */ {"CALL",2,2}, + /* B5 */ {"CPL F1",1,0}, + /* B6 */ {"JF0",2,3}, + /* B7 */ {"ILL",1,0}, + + /* B8 */ {"MOV R0,",2,1}, + /* B9 */ {"MOV R1,",2,1}, + /* BA */ {"MOV R2,",2,1}, + /* BB */ {"MOV R3,",2,1}, + + /* BC */ {"MOV R4,",2,1}, + /* BD */ {"MOV R5,",2,1}, + /* BE */ {"MOV R6,",2,1}, + /* BF */ {"MOV R7,",2,1}, + + /* C0 */ {"ILL",1,0}, + /* C1 */ {"ILL",1,0}, + /* C2 */ {"ILL",1,0}, + /* C3 */ {"ILL",1,0}, + + /* C4 */ {"JMP",2,2}, + /* C5 */ {"SEL RB0",1,0}, + /* C6 */ {"JZ",2,3}, + /* C7 */ {"MOV A,PSW",1,0}, + + /* C8 */ {"DEC R0",1,0}, + /* C9 */ {"DEC R1",1,0}, + /* CA */ {"DEC R2",1,0}, + /* CB */ {"DEC R3",1,0}, + + /* CC */ {"DEC R4",1,0}, + /* CD */ {"DEC R5",1,0}, + /* CE */ {"DEC R6",1,0}, + /* CF */ {"DEC R7",1,0}, + + /* D0 */ {"XRL A,@R0",1,0}, + /* D1 */ {"XRL A,@R1",1,0}, + /* D2 */ {"JB6",2,3}, + /* D3 */ {"XRL A,",2,1}, + + /* D4 */ {"CALL",2,2}, + /* D5 */ {"SEL RB1",1,0}, + /* D6 */ {"ILL",1,0}, + /* D7 */ {"MOV PSW,A",1,0}, + + /* D8 */ {"XRL A,R0",1,0}, + /* D9 */ {"XRL A,R1",1,0}, + /* DA */ {"XRL A,R2",1,0}, + /* DB */ {"XRL A,R3",1,0}, + /* DC */ {"XRL A,R4",1,0}, + /* DD */ {"XRL A,R5",1,0}, + /* DE */ {"XRL A,R6",1,0}, + /* DF */ {"XRL A,R7",1,0}, + + /* E0 */ {"ILL",1,0}, + /* E1 */ {"ILL",1,0}, + /* E2 */ {"ILL",1,0}, + /* E3 */ {"MOVP3 A,@A",1,0}, + + /* E4 */ {"JMP",2,2}, + /* E5 */ {"SEL MB0",1,0}, + /* E6 */ {"JNC",2,3}, + /* E7 */ {"RL A",1,0}, + + /* E8 */ {"DJNZ R0,",2,3}, + /* E9 */ {"DJNZ R1,",2,3}, + /* EA */ {"DJNZ R2,",2,3}, + /* EB */ {"DJNZ R3,",2,3}, + /* EC */ {"DJNZ R4,",2,3}, + /* ED */ {"DJNZ R5,",2,3}, + /* EE */ {"DJNZ R6,",2,3}, + /* EF */ {"DJNZ R7,",2,3}, + + /* F0 */ {"MOV A,@R0",1,0}, + /* F1 */ {"MOV A,@R1",1,0}, + /* F2 */ {"JB7",2,3}, + /* F3 */ {"ILL",1,0}, + + /* F4 */ {"CALL",2,2}, + /* F5 */ {"SEL MB1",1,0}, + /* F6 */ {"JC",2,3}, + /* F7 */ {"RLC A",1,0}, + + /* F8 */ {"MOV A,R0",1,0}, + /* F9 */ {"MOV A,R1",1,0}, + /* FA */ {"MOV A,R2",1,0}, + /* FB */ {"MOV A,R3",1,0}, + /* FC */ {"MOV A,R4",1,0}, + /* FD */ {"MOV A,R5",1,0}, + /* FE */ {"MOV A,R6",1,0}, + /* FF */ {"MOV A,R7",1,0} + +}; + diff --git a/clean/src/table.h b/clean/src/table.h new file mode 100755 index 0000000..df8d890 --- /dev/null +++ b/clean/src/table.h @@ -0,0 +1,10 @@ +#ifndef __TABLE_H +#define __TABLE_H + +extern struct lookup_tag { + char *mnemonic; + unsigned char bytes; + unsigned char type; +} lookup[]; + +#endif diff --git a/clean/src/timefunc.c b/clean/src/timefunc.c new file mode 100755 index 0000000..b50021d --- /dev/null +++ b/clean/src/timefunc.c @@ -0,0 +1,100 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Timing functions + */ + + +#include +#include "allegro.h" +#ifdef ALLEGRO_WINDOWS +#include "winalleg.h" +#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX) +#include +#include +#endif +#include "timefunc.h" + + + +#ifdef ALLEGRO_WINDOWS + +/* Windows */ +long gettimeticks(void){ + LARGE_INTEGER counter, freq; + static LONG_LONG first=-1; + if (QueryPerformanceCounter(&counter)) + if (QueryPerformanceFrequency(&freq)) { + if (first<0) first = counter.QuadPart; + return (long)(((counter.QuadPart-first)*TICKSPERSEC)/freq.QuadPart); + } + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); +} + +#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX) + +#if defined(_BSD_SOURCE) || defined(FREEBSD) + +/* Unix with gettimeofday */ +long gettimeticks(void){ + struct timeval tv; + static LONG_LONG first=-1; + LONG_LONG ll; + if (first<0) { + if (gettimeofday(&tv, NULL) != 0) + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); + first = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + } + if (gettimeofday(&tv, NULL) == 0) { + ll = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + return (long) (((ll-first)*TICKSPERSEC)/1000000); + } + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); +} + +#else + +/* Unix without gettimeofday */ +long gettimeticks(void){ + struct tms t; + return (long)((((LONG_LONG)times(&t))*TICKSPERSEC)/sysconf(_SC_CLK_TCK)); +} + +#endif + +#else + +/* Default (use Allegro timers) */ + +volatile long ticks_counter = 0; +static int timer_init = 0; + +void inc_ticks_counter(void){ + ticks_counter++; +} + +END_OF_FUNCTION(inc_ticks_counter); + +long gettimeticks(void){ + if (timer_init==0) { + ticks_counter=0; + LOCK_VARIABLE(ticks_counter); + LOCK_FUNCTION(inc_ticks_counter); + install_int(inc_ticks_counter, 1); + timer_init=1; + } + return (long)(((LONG_LONG)ticks_counter*TICKSPERSEC)/1000); +} + +#endif + diff --git a/clean/src/timefunc.h b/clean/src/timefunc.h new file mode 100755 index 0000000..61da087 --- /dev/null +++ b/clean/src/timefunc.h @@ -0,0 +1,8 @@ +#ifndef __TIMEFUNC_H +#define __TIMEFUNC_H + +#define TICKSPERSEC 10000 + +long gettimeticks(void); + +#endif diff --git a/clean/src/types.h b/clean/src/types.h new file mode 100755 index 0000000..a0a8afe --- /dev/null +++ b/clean/src/types.h @@ -0,0 +1,8 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char Byte; +typedef unsigned short ADDRESS; +#define MAXC 1024 +#endif /* TYPES_H */ + diff --git a/clean/src/vdc.c b/clean/src/vdc.c new file mode 100755 index 0000000..57d7a99 --- /dev/null +++ b/clean/src/vdc.c @@ -0,0 +1,830 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 Video Display Controller emulation + */ + +#include +#include +#include +#include "types.h" +#include "vmachine.h" +#include "config.h" +#include "keyboard.h" +#include "cset.h" +#include "timefunc.h" +#include "cpu.h" +#include "vpp.h" +#include "vdc.h" +#include "allegro.h" +#include "audio.h" +#include "voice.h" + +#define COL_SP0 0x01 +#define COL_SP1 0x02 +#define COL_SP2 0x04 +#define COL_SP3 0x08 +#define COL_VGRID 0x10 +#define COL_HGRID 0x20 +#define COL_VPP 0x40 +#define COL_CHAR 0x80 + +#define X_START 8 +#define Y_START 24 + +static long colortable[2][16] = { + /* O2 palette */ + { 0x000000, 0x0e3dd4, 0x00981b, 0x00bbd9, 0xc70008, 0xcc16b3, 0x9d8710, + 0xe1dee1, 0x5f6e6b, 0x6aa1ff, 0x3df07a, 0x31ffff, 0xff4255, 0xff98ff, + 0xd9ad5d, 0xffffff }, + /* VP+ G7400 palette */ + { 0x000000, 0x0000b6, 0x00b600, 0x00b6b6, 0xb60000, 0xb600b6, 0xb6b600, + 0xb6b6b6, 0x494949, 0x4949ff, 0x49ff49, 0x49ffff, 0xff4949, 0xff49ff, + 0xffff49, 0xffffff } +}; + +/* Collision buffer */ +static Byte *col = NULL; + +static PALETTE colors, oldcol; + +/* The pointer to the graphics buffer */ +static Byte *vscreen = NULL; + +static BITMAP *bitmap, *bitmap_cache; +static int cached_lines[MAXLINES]; + +Byte coltab[256]; + +long clip_low; +long clip_high; + +int show_fps = 0; + +int wsize; + +static void create_cmap(void); +static void draw_char(Byte ypos, Byte xpos, Byte chr, Byte col); +static void draw_quad(Byte ypos, Byte xpos, Byte cp0l, Byte cp0h, Byte cp1l, + Byte cp1h, Byte cp2l, Byte cp2h, Byte cp3l, Byte cp3h); +static void draw_grid(void); +INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c); + +void draw_region(void) +{ + int i; + if (regionoff == 0xffff) { + i = (master_clk / (LINECNT - 1) - 5); + } else { + i = (master_clk / 22 + regionoff); + } + i = (snapline(i, VDCwrite[0xA0], 0)); + if (app_data.crc == 0xA7344D1F) { + i = (master_clk / 22 + regionoff) + 6; + i = (snapline(i, VDCwrite[0xA0], 0) + 6); + }/*Atlantis*/ + + if (app_data.crc == 0xD0BC4EE6) { + i = (master_clk / 24 + regionoff) - 6; + i = (snapline(i, VDCwrite[0xA0], 0) + 7); + }/*Frogger*/ + + if (app_data.crc == 0x26517E77) { + i = (master_clk / 22 + regionoff); + i = (snapline(i, VDCwrite[0xA0], 0) - 5); + }/*Comando Noturno*/ + + if (app_data.crc == 0xA57E1724) { + i = (master_clk / (LINECNT - 1) - 5); + i = (snapline(i, VDCwrite[0xA0], 0) - 3); + }/*Catch the ball*/ + + if (i < 0) + i = 0; + clip_low = last_line * (long) BMPW; + clip_high = i * (long) BMPW; + if (clip_high > BMPW * BMPH) + clip_high = BMPW * BMPH; + if (clip_low < 0) + clip_low = 0; + if (clip_low < clip_high) + draw_display(); + last_line = i; +} + +static void create_cmap(void) +{ + int i; + + /* Initialise parts of the colors array */ + for (i = 0; i < 16; i++) { + /* Use the color values from the color table */ + colors[i + 32].r = colors[i].r = (colortable[app_data.vpp ? 1 : 0][i] + & 0xff0000) >> 18; + colors[i + 32].g = colors[i].g = (colortable[app_data.vpp ? 1 : 0][i] + & 0x00ff00) >> 10; + colors[i + 32].b = colors[i].b = (colortable[app_data.vpp ? 1 : 0][i] + & 0x0000ff) >> 2; + } + + for (i = 16; i < 32; i++) { + /* Half-bright colors for the 50% scanlines */ + colors[i + 32].r = colors[i].r = colors[i - 16].r / 2; + colors[i + 32].g = colors[i].g = colors[i - 16].g / 2; + colors[i + 32].b = colors[i].b = colors[i - 16].b / 2; + } + + for (i = 64; i < 256; i++) + colors[i].r = colors[i].g = colors[i].b = 0; +} + +void grmode(void) +{ + set_color_depth(8); + wsize = app_data.wsize; + if (app_data.fullscreen) { + if (app_data.scanlines) { + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) { + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) { + fprintf(stderr, "Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } + } else { +#ifdef ALLEGRO_DOS + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) { + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) { + fprintf(stderr,"Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } +#else + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) { + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) { + fprintf(stderr, "Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } +#endif + } + } else { + if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW * wsize, WNDH * wsize, 0, + 0)) { + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW * 2, WNDH * 2, 0, + 0)) { + if (set_gfx_mode(GFX_AUTODETECT, WNDW * 2, WNDH * 2, 0, 0)) { + fprintf(stderr, "Error: could not create window.\n"); + exit(EXIT_FAILURE); + } + } +#ifndef ALLEGRO_DOS + printf("Could not set the requested window size\n"); +#endif + } + } + + if ((app_data.scanlines) && (wsize == 1)) { +#ifndef ALLEGRO_DOS + printf("Could not set scanlines\n"); +#endif + } + set_palette(colors); + set_window_title(app_data.window_title); + clearscr(); + set_display_switch_mode(SWITCH_PAUSE); +} + +void set_textmode(void) +{ + set_palette(oldcol); + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); + if (new_int) { + Set_Old_Int9(); + } +} + +void clearscr(void) +{ + acquire_screen(); + clear(screen); + release_screen(); + clear(bitmap_cache); +} + +INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c) +{ + if ((ad > (unsigned long) clip_low) && (ad < (unsigned long) clip_high)) { + unsigned int i; + if (((len & 3) == 0) && (sizeof(unsigned long) == 4)) { + unsigned long dddd = (((unsigned long) d) & 0xff) + | ((((unsigned long) d) & 0xff) << 8) + | ((((unsigned long) d) & 0xff) << 16) + | ((((unsigned long) d) & 0xff) << 24); + unsigned long cccc = (((unsigned long) c) & 0xff) + | ((((unsigned long) c) & 0xff) << 8) + | ((((unsigned long) c) & 0xff) << 16) + | ((((unsigned long) c) & 0xff) << 24); + for (i = 0; i < len >> 2; i++) { + *((unsigned long*) (vscreen + ad)) = dddd; + cccc |= *((unsigned long*) (col + ad)); + *((unsigned long*) (col + ad)) = cccc; + coltab[c] |= ((cccc | (cccc >> 8) | (cccc >> 16) | (cccc >> 24)) + & 0xff); + ad += 4; + } + } else { + for (i = 0; i < len; i++) { + vscreen[ad] = d; + col[ad] |= c; + coltab[c] |= col[ad++]; + } + } + } +} + +static void draw_grid(void) +{ + unsigned int pnt, pn1; + Byte mask, d; + int j, i, x, w; + Byte color; + + if (VDCwrite[0xA0] & 0x40) { + for (j = 0; j < 9; j++) { + pnt = (((j * 24) + 24) * BMPW); + for (i = 0; i < 9; i++) { + pn1 = pnt + (i * 32) + 20; + color = ColorVector[j * 24 + 24]; + mputvid( + pn1, + 4, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j * 24 + 25]; + mputvid( + pn1 + BMPW, + 4, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j * 24 + 26]; + mputvid( + pn1 + BMPW * 2, + 4, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + } + } + } + + mask = 0x01; + for (j = 0; j < 9; j++) { + pnt = (((j * 24) + 24) * BMPW); + for (i = 0; i < 9; i++) { + pn1 = pnt + (i * 32) + 20; + if ((pn1 + BMPW * 3 >= (unsigned long) clip_low) + && (pn1 <= (unsigned long) clip_high)) { + d = VDCwrite[0xC0 + i]; + if (j == 8) { + d = VDCwrite[0xD0 + i]; + mask = 1; + } + if (d & mask) { + color = ColorVector[j * 24 + 24]; + mputvid( + pn1, + 36, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j * 24 + 25]; + mputvid( + pn1 + BMPW, + 36, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j * 24 + 26]; + mputvid( + pn1 + BMPW * 2, + 36, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_HGRID); + } + } + } + mask = mask << 1; + } + + mask = 0x01; + w = 4; + if (VDCwrite[0xA0] & 0x80) { + w = 32; + } + for (j = 0; j < 10; j++) { + pnt = (j * 32); + mask = 0x01; + d = VDCwrite[0xE0 + j]; + for (x = 0; x < 8; x++) { + pn1 = pnt + (((x * 24) + 24) * BMPW) + 20; + if (d & mask) { + for (i = 0; i < 24; i++) { + if ((pn1 >= (unsigned long) clip_low) + && (pn1 <= (unsigned long) clip_high)) { + color = ColorVector[x * 24 + 24 + i]; + mputvid( + pn1, + w, + (color & 0x07) | ((color & 0x40) >> 3) + | (color & 0x80 ? 0 : 8), COL_VGRID); + } + pn1 += BMPW; + } + } + mask = mask << 1; + } + } +} + +void finish_display(void) +{ + int x, y, sn; + static int cache_counter = 0; + + vpp_finish_bmp(vscreen, 9, 5, BMPW - 9, BMPH - 5, bitmap->w, bitmap->h); + + if (show_fps) { + static long last = -1, index = 0, curr = 0, t = 0; + if (last < 0) + last = gettimeticks(); + index = (index + 1) % 200; + if (!index) { + t = gettimeticks(); + curr = t - last; + last = t; + } + if (curr) { + textprintf_ex(bitmap, font, 20, 4, 7, 0, "FPS :%3d", + (int) ((200.0 * TICKSPERSEC) / curr + 0.5)); + } + } + + for (y = 0; y < bitmap->h; y++) { + cached_lines[y] = !memcmp(bitmap_cache->line[y], bitmap->line[y], bitmap->w); + if (!cached_lines[y]) + memcpy(bitmap_cache->line[y], bitmap->line[y], bitmap->w); + } + + for (y = 0; y < 10; y++) + cached_lines[(y + cache_counter) % bitmap->h] = 0; + cache_counter = (cache_counter + 10) % bitmap->h; + + acquire_screen(); + + sn = ((wsize > 1) && (app_data.scanlines)) ? 1 : 0; + + for (y = 0; y < WNDH; y++) { + if (!cached_lines[y + 2]) + stretch_blit(bitmap, screen, 7, 2 + y, WNDW, 1, 0, y * wsize, + WNDW * wsize, wsize - sn); + } + + if (sn) { + for (y = 0; y < WNDH; y++) { + if (!cached_lines[y + 2]) { + for (x = 0; x < bitmap->w; x++) + bitmap->line[y + 2][x] += 16; + stretch_blit(bitmap, screen, 7, 2 + y, WNDW, 1, 0, + (y + 1) * wsize - 1, WNDW * wsize, 1); + memcpy(bitmap->line[y + 2], bitmap_cache->line[y + 2], bitmap->w); + } + } + } + release_screen(); +} + +void clear_collision(void) +{ + load_colplus(col); + coltab[0x01] = coltab[0x02] = 0; + coltab[0x04] = coltab[0x08] = 0; + coltab[0x10] = coltab[0x20] = 0; + coltab[0x40] = coltab[0x80] = 0; +} + +void draw_display(void) +{ + int i, j, x, sm, t; + Byte y, b, d1, cl, c; + + unsigned int pnt, pnt2; + + for (i = clip_low / BMPW; i < clip_high / BMPW; i++) + memset( + vscreen + i * BMPW, + ((ColorVector[i] & 0x38) >> 3) + | (ColorVector[i] & 0x80 ? 0 : 8), BMPW); + + if (VDCwrite[0xA0] & 0x08) + draw_grid(); + + if (useforen && (!(VDCwrite[0xA0] & 0x20))) + return; + + for (i = 0x10; i < 0x40; i += 4) + draw_char(VDCwrite[i], VDCwrite[i + 1], VDCwrite[i + 2], + VDCwrite[i + 3]); + + /* draw quads, position mapping happens in ext_write (vmachine.c)*/ + for (i = 0x40; i < 0x80; i += 0x10) + draw_quad(VDCwrite[i], VDCwrite[i + 1], VDCwrite[i + 2], + VDCwrite[i + 3], VDCwrite[i + 6], VDCwrite[i + 7], + VDCwrite[i + 10], VDCwrite[i + 11], VDCwrite[i + 14], + VDCwrite[i + 15]); + + c = 8; + for (i = 12; i >= 0; i -= 4) { + pnt2 = 0x80 + (i * 2); + y = VDCwrite[i]; + x = VDCwrite[i + 1] - 8; + t = VDCwrite[i + 2]; + cl = ((t & 0x38) >> 3); + cl = ((cl & 2) | ((cl & 1) << 2) | ((cl & 4) >> 2)) + 8; + /*174*/ + if ((x < 164) && (y > 0) && (y < 232)) { + pnt = y * BMPW + (x * 2) + 20 + sproff; + if (t & 4) { + if ((pnt + BMPW * 32 >= (unsigned long) clip_low) + && (pnt <= (unsigned long) clip_high)) { + for (j = 0; j < 8; j++) { + sm = (((j % 2 == 0) && (((t >> 1) & 1) != (t & 1))) + || ((j % 2 == 1) && (t & 1))) ? 1 : 0; + d1 = VDCwrite[pnt2++]; + for (b = 0; b < 8; b++) { + if (d1 & 0x01) { + if ((x + b + sm < 159) && (y + j < 247)) { + mputvid(sm + pnt, 4, cl, c); + mputvid(sm + pnt + BMPW, 4, cl, c); + mputvid(sm + pnt + 2 * BMPW, 4, cl, c); + mputvid(sm + pnt + 3 * BMPW, 4, cl, c); + } + } + pnt += 4; + d1 = d1 >> 1; + } + pnt += BMPW * 4 - 32; + } + } + } else { + if ((pnt + BMPW * 16 >= (unsigned long) clip_low) + && (pnt <= (unsigned long) clip_high)) { + for (j = 0; j < 8; j++) { + sm = (((j % 2 == 0) && (((t >> 1) & 1) != (t & 1))) + || ((j % 2 == 1) && (t & 1))) ? 1 : 0; + d1 = VDCwrite[pnt2++]; + for (b = 0; b < 8; b++) { + if (d1 & 0x01) { + if ((x + b + sm < 160) && (y + j < 249)) { + mputvid(sm + pnt, 2, cl, c); + mputvid(sm + pnt + BMPW, 2, cl, c); + } + } + pnt += 2; + d1 = d1 >> 1; + } + pnt += BMPW * 2 - 16; + } + } + } + } + c = c >> 1; + } +} + +void draw_char(Byte ypos, Byte xpos, Byte chr, Byte col) +{ + int j, c; + Byte cl, d1; + int y, b, n; + unsigned int pnt; + + y = (ypos & 0xFE); + pnt = y * BMPW + ((xpos - 8) * 2) + 20; + + ypos = ypos >> 1; + n = 8 - (ypos % 8) - (chr % 8); + if (n < 3) + n = n + 7; + + if ((pnt + BMPW * 2 * n >= (unsigned long) clip_low) + && (pnt <= (unsigned long) clip_high)) { + + c = (int) chr + ypos; + if (col & 0x01) + c += 256; + if (c > 511) + c = c - 512; + + cl = ((col & 0x0E) >> 1); + cl = ((cl & 2) | ((cl & 1) << 2) | ((cl & 4) >> 2)) + 8; + + if ((y > 0) && (y < 232) && (xpos < 157)) { + for (j = 0; j < n; j++) { + d1 = cset[c + j]; + for (b = 0; b < 8; b++) { + if (d1 & 0x80) { + if ((xpos - 8 + b < 160) && (y + j < 240)) { + mputvid(pnt, 2, cl, COL_CHAR); + mputvid(pnt + BMPW, 2, cl, COL_CHAR); + } + } + pnt += 2; + d1 = d1 << 1; + } + pnt += BMPW * 2 - 16; + } + } + } +} + +/* This quad drawing routine can display the quad cut off effect used in KTAA. + * It needs more testing with other games, especially the clipping. + * This code is quite slow and needs a rewrite by somebody with more experience + * than I (sgust) have */ + +void draw_quad(Byte ypos, Byte xpos, Byte cp0l, Byte cp0h, Byte cp1l, Byte cp1h, + Byte cp2l, Byte cp2h, Byte cp3l, Byte cp3h) +{ + /* char set pointers */ + int chp[4]; + /* colors */ + Byte col[4]; + /* pointer into screen bitmap */ + unsigned int pnt; + /* offset into current line */ + unsigned int off; + /* loop variables */ + int i, j, lines; + + /* get screen bitmap position of quad */ + pnt = (ypos & 0xfe) * BMPW + ((xpos - 8) * 2) + 20; + /* abort drawing if completely below the bottom clip */ + if (pnt > (unsigned long) clip_high) + return; + /* extract and convert char-set offsets */ + chp[0] = cp0l | ((cp0h & 1) << 8); + chp[1] = cp1l | ((cp1h & 1) << 8); + chp[2] = cp2l | ((cp2h & 1) << 8); + chp[3] = cp3l | ((cp3h & 1) << 8); + for (i = 0; i < 4; i++) + chp[i] = (chp[i] + (ypos >> 1)) & 0x1ff; + lines = 8 - (chp[3] + 1) % 8; + /* abort drawing if completely over the top clip */ + if (pnt + BMPW * 2 * lines < (unsigned long) clip_low) + return; + /* extract and convert color information */ + col[0] = (cp0h & 0xe) >> 1; + col[1] = (cp1h & 0xe) >> 1; + col[2] = (cp2h & 0xe) >> 1; + col[3] = (cp3h & 0xe) >> 1; + for (i = 0; i < 4; i++) + col[i] = ((col[i] & 2) | ((col[i] & 1) << 2) | ((col[i] & 4) >> 2)) + 8; + /* now draw the quad line by line controlled by the last quad */ + while (lines-- > 0) { + off = 0; + /* draw all 4 sub-quads */ + for (i = 0; i < 4; i++) { + /* draw sub-quad pixel by pixel, but stay in same line */ + for (j = 0; j < 8; j++) { + if ((cset[chp[i]] & (1 << (7 - j))) && (off < BMPW)) { + mputvid(pnt + off, 2, col[i], COL_CHAR); + mputvid(pnt + off + BMPW, 2, col[i], COL_CHAR); + } + /* next pixel */ + off += 2; + } + /* space between sub-quads */ + off += 16; + } + /* advance char-set pointers */ + for (i = 0; i < 4; i++) + chp[i] = (chp[i] + 1) & 0x1ff; + /* advance screen bitmap pointer */ + pnt += BMPW * 2; + } +} + +void close_display(void) +{ + free(vscreen); + free(col); +} + +void window_close_hook(void) +{ + key_debug = 0; + key_done = 1; + + // FIXME : Quit program in a clean way + //finish_display(); + //close_display(); + //allegro_exit(); +} +static void txtmsg(int x, int y, int c, const char *s) +{ + textout_centre_ex(bitmap, font, s, x + 1, y + 1, makecol(255, 0, 0), + makecol(0, 0, 0)); + textout_centre_ex(bitmap, font, s, x, y, c, makecol(0, 0, 0)); +} +void display_bg(void) +{ + rectfill(bitmap, 20, 72, 311, 172, 9 + 32); + line(bitmap, 20, 72, 311, 72, 15 + 32); + line(bitmap, 20, 72, 20, 172, 15 + 32); + line(bitmap, 21, 172, 311, 172, 1 + 32); + line(bitmap, 311, 172, 311, 72, 1 + 32); +} + +void abaut(void) +{ + char *ver; + char exitstr[80]; + int i = 0; + while (syskeys[1] != keybtab[i].keybcode) + i++; + + strcpy(exitstr, "Press "); + strcat(exitstr, keybtab[i].keybname); + strcat(exitstr, " to continue"); + +#if defined(ALLEGRO_WINDOWS) + ver = "Windows version"; +#elif defined(ALLEGRO_DOS) + ver = "DOS version"; +#elif defined(ALLEGRO_LINUX) + ver = "Linux version"; +#elif defined(ALLEGRO_BEOS) + ver = "BEOS version"; +#elif defined(ALLEGRO_QNX) + ver = "QNX version"; +#elif defined(ALLEGRO_UNIX) + ver = "UNIX version"; +#elif defined(ALLEGRO_MPW) + ver = "MacOS version"; +#else + ver = "Unknown platform"; +#endif + display_bg(); + txtmsg(166, 76, 15 + 32, "O2EM v" O2EM_VERSION " " RELEASE_DATE); + txtmsg(166, 90, 15 + 32, "Free Odyssey2 / VP+ Emulator"); + txtmsg(166, 104, 15 + 32, ver); + txtmsg(166, 118, 15 + 32, "Developed by Andre de la Rocha"); + txtmsg(168, 132, 15 + 32, "and Arlindo M. de Oliveira"); + txtmsg(166, 148, 15 + 32, "Copyright 1996/1998 by Daniel Boris"); + txtmsg(166, 162, 15 + 32, exitstr); + finish_display(); +} +void display_msg(char *msg, int waits) +{ + mute_audio(); + mute_voice(); + rectfill(bitmap, 60, 72, 271, 90, 9 + 32); + line(bitmap, 60, 72, 271, 72, 15 + 32); + line(bitmap, 60, 72, 60, 90, 15 + 32); + line(bitmap, 61, 90, 271, 90, 1 + 32); + line(bitmap, 271, 90, 271, 72, 1 + 32); + txtmsg(166, 76, 15 + 32, msg); + finish_display(); + rest(waits * 100); + init_sound_stream(); +} +void init_display(void) +{ + get_palette(oldcol); + create_cmap(); + bitmap = create_bitmap(BMPW, BMPH); + bitmap_cache = create_bitmap(BMPW, BMPH); + if ((!bitmap) || (!bitmap_cache)) { + fprintf(stderr, "Could not allocate memory for screen buffer.\n"); + exit(EXIT_FAILURE); + } + vscreen = (Byte *) bitmap->dat; + clear(bitmap); + clear(bitmap_cache); + col = (Byte *) malloc(BMPW * BMPH); + if (!col) { + fprintf(stderr, "Could not allocate memory for collision buffer.\n"); + free(vscreen); + exit(EXIT_FAILURE); + } + memset(col, 0, BMPW * BMPH); + if (!app_data.debug) { + grmode(); + init_keyboard(); + } + set_close_button_callback(window_close_hook); + +} +/*************************** Help*/ +void help(void) +{ + int yet_another_index = 40; + int index = 0; + int counter = 0; + int way = 0; + static char hl[96][70] = { + "-wsize=n", " Window size (1-4)", "", + "-fullscreen", " Full screen mode", "", + "-help", " This instructions", "", + "-scanlines", " Enable scanlines", "", + "-nosound", " Turn off sound emulation", "", + "-novoice", " Turn off voice emulation", "", + "-svolume=n", " Set sound volume (0-100)", "", + "-vvolume=n", " Set voice volume (0-100)", "", + "-filter", " Enable low-pass audio filter", "", + "-debug", " Start the emulator in ", " debug mode", "", + "-speed=n", " Relative speed", " (100 = original)", "", + "-nolimit", " Turn off speed limiter", "", + "-bios=file", " Set the O2 bios file name/dir", "", + "-biosdir=path", " Set the O2 bios path ", " (default= bios/ )", "", + "-romdir=path", " Set the O2 roms Path ", " (default= roms/ )", "", + "-scshot=file", " Set the screenshot file ", " name/template", "", + "-euro", " Use European timing /", " 50Hz mode", "", + "-exrom", " Use special 3K program/", " 1K data ROM mode", "", + "-3k", " Use 3K rom mapping mode", "", + "-s=mode/keys", " Define stick n mode/keys (n=1-2)", "", + "-c52", " Start the emulator with ", " french Odyssey 2 BIOS", "", + "-g7400", " Start the emulator ", " with VP+ BIOS", "", + "-jopac", " Start the emulator with ", " french VP+ bios", "", + "-scoretype=m", " Set Scoretype to m (see manual)", "", + "-scoreadr=n", " Set Scoreaddress to n ", " (decimal value)", "", + "-scorefile=file", " Set Output-Scorefile to ", " file (highscore.txt)", "", + "-score=n", " Set Highscore to n", "", + "-savefile=file", " Load/Save State ", " from/to file" + }; + + textout_ex(bitmap, font, "O2EM v" O2EM_VERSION " Help", 26, 16, 2, 0); + textout_ex(bitmap, font, "Use: o2em [options]", 26, 26, 2, 0); + rect(bitmap, 20, 12, 315, 228, 6); + line(bitmap, 20, 35, 315, 35, 6); + for (index = 0; index < 16; index++) { + textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4, makecol(0, 0, 0)); + yet_another_index += 12; + } + yet_another_index = 40; + finish_display(); + do { + rest(25); + if (NeedsPoll) + poll_keyboard(); + if (key[KEY_DOWN]) { + counter++; + if (counter >= 80) + counter = 80; + rectfill(bitmap, 25, 36, 306, 227, 0); + for (index = 0; index < 16; index++) { + textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4, + makecol(0, 0, 0)); + yet_another_index += 12; + } + yet_another_index = 40; + for (way = 0; way < 8; way++) + finish_display(); + } + if (key[KEY_UP]) { + counter--; + if (counter <= 0) + counter = 0; + rectfill(bitmap, 25, 36, 306, 227, 0); + for (index = 0; index < 16; index++) { + textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4, + makecol(0, 0, 0)); + yet_another_index += 12; + } + yet_another_index = 40; + for (way = 0; way < 8; way++) + finish_display(); + } + + } while (!key[KEY_ESC]); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + } while (key[KEY_ESC]); + return; +} + diff --git a/clean/src/vdc.h b/clean/src/vdc.h new file mode 100755 index 0000000..d94460d --- /dev/null +++ b/clean/src/vdc.h @@ -0,0 +1,35 @@ +#ifndef __VDC_H +#define __VDC_H + +#define BMPW 340 +#define BMPH 250 +#define WNDW 320 +#define WNDH 240 + +#define BOX_W MIN(512, SCREEN_W-16) +#define BOX_H MIN(256, (SCREEN_H-64)&0xFFF0) + +#define BOX_L ((SCREEN_W - BOX_W) / 2) +#define BOX_R ((SCREEN_W + BOX_W) / 2) +#define BOX_T ((SCREEN_H - BOX_H) / 2) +#define BOX_B ((SCREEN_H + BOX_H) / 2) + +extern Byte coltab[]; +extern long clip_low; +extern long clip_high; +extern int show_fps; + +void init_display(void); +void draw_display(void); +void set_textmode(void); +void draw_region(void); +void finish_display(); +void close_display(void); +void grmode(void); +void display_bg(void); +void display_msg(char *msg, int waits); +void clear_collision(void); +void clearscr(void); +void abaut(void); +void help(void); +#endif diff --git a/clean/src/vmachine.c b/clean/src/vmachine.c new file mode 100755 index 0000000..39f0dad --- /dev/null +++ b/clean/src/vmachine.c @@ -0,0 +1,908 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Main O2 machine emulation + */ + +#include +#include +#include +#include "audio.h" +#include "types.h" +#include "cpu.h" +#include "keyboard.h" +#include "config.h" +#include "debug.h" +#include "vdc.h" +#include "vpp.h" +#include "timefunc.h" +#include "voice.h" +#include "vmachine.h" +#include "allegro.h" + +static Byte x_latch, y_latch; +static int romlatch = 0; +static Byte line_count; +static int fps = FPS_NTSC; + +static Byte snapedlines[MAXLINES + 2 * MAXSNAP][256][2]; + +int evblclk = EVBLCLK_NTSC; + +struct resource app_data; +int frame = 0; +Byte dbstick1, dbstick2; + +int int_clk; /* counter for length of /INT pulses */ +int master_clk; /* Master clock */ +int h_clk; /* horizontal clock */ +unsigned long clk_counter; +int last_line; +int key2vcnt = 0; +int mstate; + +int pendirq = 0; +int enahirq = 1; +int useforen = 0; +long regionoff = 0xffff; +int mxsnap = 2; +int sproff = 0; +int tweakedaudio = 0; + +Byte rom_table[8][4096]; + +Byte intRAM[64]; +Byte extRAM[256]; +Byte extROM[1024]; +Byte VDCwrite[256]; +Byte ColorVector[MAXLINES]; +Byte AudioVector[MAXLINES]; +Byte *rom; +Byte *megarom; + +int key2[128]; + +static unsigned int key_map[6][8] = { + { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7 }, + { KEY_8, KEY_9, 0, 0, KEY_SPACE, KEY_SLASH, KEY_L, KEY_P }, + { KEY_PLUS_PAD, KEY_W, KEY_E, KEY_R, KEY_T, KEY_U, KEY_I, KEY_O }, + { KEY_Q, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K }, + { KEY_A, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_M, KEY_STOP }, + { KEY_MINUS, KEY_ASTERISK, KEY_SLASH_PAD, KEY_EQUALS, KEY_Y, KEY_N, KEY_DEL, KEY_ENTER } +}; + +static void do_kluges(void); +static void setvideomode(int t); + +void run(void) +{ + while (!key_done) { + if (key_debug) { + app_data.debug = 1; + set_textmode(); + mute_audio(); + mute_voice(); + debug(); + grmode(); + app_data.debug = 0; + init_keyboard(); + init_sound_stream(); + } + cpu_exec(); + } + close_audio(); + close_voice(); + close_display(); +} + +void handle_vbl(void) +{ + if (!app_data.debug) { + handle_key(); + update_audio(); + update_voice(); + } + draw_region(); + ext_IRQ(); + mstate = 1; +} + +void handle_evbl(void) +{ + static long last = 0; + static int rest_cnt = 0; + int i; + +#ifndef ALLEGRO_DOS + rest(0); +#endif + i = (15 * app_data.speed / 100); + rest_cnt = (rest_cnt + 1) % (i < 5 ? 5 : i); +#ifdef ALLEGRO_WINDOWS + if (rest_cnt==0) rest(1); +#endif + last_line = 0; + master_clk -= evblclk; + frame++; + if (!app_data.debug) { + finish_display(); + } + + if (app_data.crc == 0xA7344D1F) { + for (i = 0; i < 140; i++) { + ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80); + AudioVector[i] = VDCwrite[0xAA]; + } + }/*Atlantis*/ + else + for (i = 0; i < MAXLINES; i++) { + ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80); + AudioVector[i] = VDCwrite[0xAA]; + } + + if (key2vcnt++ > 10) { + key2vcnt = 0; + for (i = 0; i < 128; i++) + key2[i] = 0; + dbstick1 = dbstick2 = 0; + } + if (app_data.limit) { + long d, f; + d = (TICKSPERSEC * 100) / (app_data.speed * fps); + f = ((d - gettimeticks() + last) * 1000) / TICKSPERSEC; + if (f > 0) { +#ifdef ALLEGRO_WINDOWS + f = f-(f%10); + if (f>5) rest(f-5); +#else +#ifndef ALLEGRO_DOS + rest(0); +#endif +#endif + } + while (gettimeticks() - last < d); + last = gettimeticks(); + } + mstate = 0; +} + +void handle_evbll(void) +{ + static long last = 0; + static int rest_cnt = 0; + int i; + +#ifndef ALLEGRO_DOS + rest(0); +#endif + i = (15 * app_data.speed / 100); + rest_cnt = (rest_cnt + 1) % (i < 5 ? 5 : i); +#ifdef ALLEGRO_WINDOWS + if (rest_cnt==0) rest(1); +#endif + + /******************* 150 */ + + for (i = 150; i < MAXLINES; i++) { + ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80); + AudioVector[i] = VDCwrite[0xAA]; + } + + if (key2vcnt++ > 10) { + key2vcnt = 0; + for (i = 0; i < 128; i++) + key2[i] = 0; + dbstick1 = dbstick2 = 0; + } + if (app_data.limit) { + long d, f; + d = (TICKSPERSEC * 100) / (app_data.speed * fps); + f = ((d - gettimeticks() + last) * 1000) / TICKSPERSEC; + if (f > 0) { +#ifdef ALLEGRO_WINDOWS + f = f-(f%10); + if (f>5) rest(f-5); +#else +#ifndef ALLEGRO_DOS + rest(0); +#endif +#endif + } + while (gettimeticks() - last < d) + ; + last = gettimeticks(); + } + mstate = 0; +} + +void init_system(void) +{ + int i, j, k; + + last_line = 0; + dbstick1 = 0x00; + dbstick2 = 0x00; + mstate = 0; + master_clk = 0; + h_clk = 0; + line_count = 0; + itimer = 0; + clk_counter = 0; + init_roms(); + for (i = 0; i < 256; i++) { + VDCwrite[i] = 0; + extRAM[i] = 0; + } + for (i = 0; i < 64; i++) { + intRAM[i] = 0; + } + for (i = 0; i < MAXLINES; i++) + AudioVector[i] = ColorVector[i] = 0; + + for (i = 0; i < MAXLINES + 2 * MAXSNAP; i++) + for (j = 0; j < 256; j++) + for (k = 0; k < 2; k++) + snapedlines[i][j][k] = 0; + + if (app_data.stick[0] == 2 || app_data.stick[1] == 2) { + i = install_joystick(JOY_TYPE_AUTODETECT); + if (i || (num_joysticks < 1)) { + fprintf(stderr, "Error: no joystick detected\n"); + exit(EXIT_FAILURE); + } + } + for (i = 0; i < 128; i++) + key2[i] = 0; + key2vcnt = 0; + if (app_data.euro) + setvideomode(1); + else + setvideomode(0); + do_kluges(); + init_vpp(); + clear_collision(); +} + +void init_roms(void) +{ + rom = rom_table[0]; + romlatch = 0; +} + +Byte read_t1(void) +{ + /*17*/ + if ((h_clk > 16) || (master_clk > VBLCLK)) + return 1; + else + return 0; +} + +void write_p1(Byte d) +{ + if ((d & 0x80) != (p1 & 0x80)) { + int i, l; + l = snapline((int) ((float) master_clk / 22.0 + 0.1), VDCwrite[0xA3], + 1); + for (i = l; i < MAXLINES; i++) + ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (d & 0x80); + } + p1 = d; + if (app_data.bank == 2) { + rom = rom_table[~p1 & 0x01]; + } else if (app_data.bank == 3) { + rom = rom_table[~p1 & 0x03]; + } else if (app_data.bank == 4) { + rom = rom_table[(p1 & 1) ? 0 : romlatch]; + } +} + +Byte read_P2(void) +{ + int i, si, so, km; + + if (NeedsPoll) + poll_keyboard(); + + if (!(p1 & 0x04)) { + si = (p2 & 7); + so = 0xff; + if (si < 6) { + for (i = 0; i < 8; i++) { + km = key_map[si][i]; + if ((key[km] + && ((!joykeystab[km]) || (key_shifts & KB_CAPSLOCK_FLAG))) + || (key2[km])) { + so = i ^ 0x07; + } + } + } + if (so != 0xff) { + p2 = p2 & 0x0F; + p2 = p2 | (so << 5); + } else { + p2 = p2 | 0xF0; + } + } else { + p2 = p2 | 0xF0; + } + return (p2); +} + +Byte ext_read(ADDRESS adr) +{ + Byte d; + Byte si; + Byte m; + int i; + + if (!(p1 & 0x08) && !(p1 & 0x40)) { + /* Handle VDC Read */ + switch (adr) { + case 0xA1: + d = VDCwrite[0xA0] & 0x02; + if (master_clk > VBLCLK) + d = d | 0x08; + if (h_clk < (LINECNT - 7)) + d = d | 0x01; + if (sound_IRQ) + d = d | 0x04; + sound_IRQ = 0; + return d; + case 0xA2: + si = VDCwrite[0xA2]; + m = 0x01; + d = 0; + for (i = 0; i < 8; i++) { + if (si & m) { + if (coltab[1] & m) + d = d | (coltab[1] & (m ^ 0xFF)); + if (coltab[2] & m) + d = d | (coltab[2] & (m ^ 0xFF)); + if (coltab[4] & m) + d = d | (coltab[4] & (m ^ 0xFF)); + if (coltab[8] & m) + d = d | (coltab[8] & (m ^ 0xFF)); + if (coltab[0x10] & m) + d = d | (coltab[0x10] & (m ^ 0xFF)); + if (coltab[0x20] & m) + d = d | (coltab[0x20] & (m ^ 0xFF)); + if (coltab[0x80] & m) + d = d | (coltab[0x80] & (m ^ 0xFF)); + } + m = m << 1; + } + clear_collision(); + return d; + case 0xA5: + if (!(VDCwrite[0xA0] & 0x02)) { + return x_latch; + } else { + x_latch = h_clk * 12; + return x_latch; + } + case 0xA4: + if (!(VDCwrite[0xA0] & 0x02)) { + return y_latch; + } else { + y_latch = master_clk / 22; + if (y_latch > 241) + y_latch = 0xFF; + return y_latch; + } + default: + return VDCwrite[adr]; + } + } else if (!(p1 & 0x10)) { + /* Handle ext RAM Read */ + if (app_data.megaxrom && (adr >= 0x80)) { + /* MegaCART registers are mirrored every 4 bytes */ + if ((adr & 0x83) == 0x83) { + /* TODO: emulate EEPROM data in */ + return 0xff; + } else + return extRAM[adr & 0x83]; + } else + return extRAM[adr & 0xFF]; + } else if (!(p1 & 0x20)) { + /* Read a Videopac+ register */ + return vpp_read(adr); + } else if (app_data.exrom && (p1 & 0x02)) { + /* Handle read from exrom */ + return extROM[(p2 << 8) | (adr & 0xFF)]; + } else if (app_data.megaxrom && !(p1 & 0x02) && !(p1 & 0x40)) { + /* Handle data read from MegaCART */ + return megarom[(extRAM[0x81] << 12) | ((p2 & 0x0f) << 8) | (adr & 0xff)]; + } + + return 0; +} + +Byte in_bus(void) +{ + Byte si = 0, d = 0, mode = 0, jn = 0, sticknum = 0; + + if ((p1 & 0x08) && (p1 & 0x10)) { + /* Handle joystick read */ + if (!(p1 & 0x04)) { + si = (p2 & 7); + } + d = 0xFF; + if (si == 1) { + mode = app_data.stick[0]; + jn = 0; + sticknum = app_data.sticknumber[0] - 1; + } else { + mode = app_data.stick[1]; + jn = 1; + sticknum = app_data.sticknumber[1] - 1; + } + switch (mode) { + case 1: + d = keyjoy(jn); + break; + case 2: + poll_joystick(); + if (joy[sticknum].stick[0].axis[1].d1) + d &= 0xFE; // joy_up + if (joy[sticknum].stick[0].axis[0].d2) + d &= 0xFD; // joy_right + if (joy[sticknum].stick[0].axis[1].d2) + d &= 0xFB; // joy_down + if (joy[sticknum].stick[0].axis[0].d1) + d &= 0xF7; // joy_left + if (joy[sticknum].button[0].b || joy[jn].button[1].b) + d &= 0xEF; // both main-buttons + break; + } + if (si == 1) { + if (dbstick1) + d = dbstick1; + } else { + if (dbstick2) + d = dbstick2; + } + } + return d; +} + +void ext_write(Byte dat, ADDRESS adr) +{ + int i; + + if (!(p1 & 0x08)) { + /* Handle VDC Write */ + if (adr == 0xA0) { + if ((VDCwrite[0xA0] & 0x02) && !(dat & 0x02)) { + y_latch = master_clk / 22; + x_latch = h_clk * 12; + if (y_latch > 241) + y_latch = 0xFF; + } + if ((master_clk <= VBLCLK) && (VDCwrite[0xA0] != dat)) { + draw_region(); + } + } else if (adr == 0xA3) { + int l; + l = snapline((int) ((float) master_clk / 22.0 + 0.5), dat, 1); + for (i = l; i < MAXLINES; i++) + ColorVector[i] = (dat & 0x7f) | (p1 & 0x80); + } else if (adr == 0xAA) { + for (i = master_clk / 22; i < MAXLINES; i++) + AudioVector[i] = dat; + } else if ((adr >= 0x40) && (adr <= 0x7f) && ((adr & 2) == 0)) { + /* simulate quad: all 4 sub quad position registers + * are mapped to the same internal register */ + adr = adr & 0x71; + /* Another minor thing: the y register always returns + * bit 0 as 0 */ + if ((adr & 1) == 0) + dat = dat & 0xfe; + VDCwrite[adr] = VDCwrite[adr + 4] = VDCwrite[adr + 8] = VDCwrite[adr + + 12] = dat; + } + VDCwrite[adr] = dat; + } else if (!(p1 & 0x10) && !(p1 & 0x40)) { + adr = adr & 0xFF; + + if (adr < 0x80) { + /* Handle ext RAM Write */ + extRAM[adr] = dat; + + } else { + if (app_data.bank == 4) { + romlatch = (~dat) & 7; + rom = rom_table[(p1 & 1) ? 0 : romlatch]; + } + + /* Handle The Voice */ + if (!(dat & 0x20)) + reset_voice(); + else { + if (adr == 0xE4) + set_voice_bank(0); + else if ((adr >= 0xE8) && (adr <= 0xEF)) + set_voice_bank(adr - 0xE7); + else if (((adr >= 0x80) && (adr <= 0xDF)) + || ((adr >= 0xF0) && (adr <= 0xFF))) + trigger_voice(adr); + } + } + } else if (!(p1 & 0x20)) { + /* Write to a Videopac+ register */ + vpp_write(dat, adr); + } +} + +static void do_kluges(void) +{ + if (app_data.crc == 0xA7344D1F) + pendirq = 1; /* Atlantis */ + if (app_data.crc == 0xFB83171E) + pendirq = 1; /* Blockout */ + if (app_data.crc == 0xD38153F6) + pendirq = 1; /* Blockout (french) */ + if (app_data.crc == 0x881CEAE4) + pendirq = 1; /* Wall Street */ + + if (app_data.crc == 0x9E42E766) + useforen = 1; /* Turtles */ + if (app_data.crc == 0x1C750349) + useforen = 1; /* Turtles (European version) */ + if (app_data.crc == 0x202F2749) + useforen = 1; /* Q*bert */ + if (app_data.crc == 0x06861A9C) + useforen = 1; /* Flashpoint 5 (Videopac adaption) */ + + if (app_data.crc == 0xFB83171E) + enahirq = 0; /* Blockout*/ + if (app_data.crc == 0xD38153F6) + enahirq = 0; /* Blockout (french) */ + + if (app_data.crc == 0xFB83171E) + regionoff = 1; /* Blockout*/ + if (app_data.crc == 0xD38153F6) + regionoff = 1; /* Blockout (french) */ + if (app_data.crc == 0x202F2749) + regionoff = 0; /* Q*bert */ + if (app_data.crc == 0x5216771A) + regionoff = 1; /* Popeye */ + if (app_data.crc == 0x0C2E4811) + regionoff = 11; /* Out of this World! / Helicopter Rescue! */ + if (app_data.crc == 0x67069924) + regionoff = 11; /* Smithereens! */ + if (app_data.crc == 0x44D1A8A5) + regionoff = 11; /* Smithereens! (European version) */ + if (app_data.crc == 0x2391C2FB) + regionoff = 11; /* Smithereens! + */ + if (app_data.crc == 0xBB4AD548) + regionoff = 11; /* Smithereens! modified 1 */ + if (app_data.crc == 0x25057C11) + regionoff = 11; /* Smithereens! modified 2 */ + if (app_data.crc == 0xB936BD78) + regionoff = 12; /* Type & Tell */ + if (app_data.crc == 0xAD8B9AE0) + regionoff = 2; /* Type & Tell modified 1 */ + if (app_data.crc == 0x5C02BEE6) + regionoff = 2; /* Type & Tell modified 2 */ + if (app_data.crc == 0xDC30AD3D) + regionoff = 10; /* Dynasty! */ + if (app_data.crc == 0x7810BAD5) + regionoff = 8; /* Dynasty! (European) */ + if (app_data.crc == 0xA7344D1F) + regionoff = 0; /* Atlantis */ + if (app_data.crc == 0xD0BC4EE6) + regionoff = 12; /* Frogger */ + if (app_data.crc == 0xA57D84F3) + regionoff = 8; /* Frogger BR */ + if (app_data.crc == 0x825976A9) + regionoff = 0; /* Mousing Cat 8kb */ + if (app_data.crc == 0xF390BFEC) + regionoff = 0; /* Mousing Cat 4kb */ + if (app_data.crc == 0x61A350E6) + regionoff = 0; /* Mousing Cat (french) */ + if (app_data.crc == 0x3BFEF56B) + regionoff = 1; /* Four in 1 Row! */ + if (app_data.crc == 0x7C747245) + regionoff = 1; /* Four in 1 Row! modified */ + if (app_data.crc == 0x9B5E9356) + regionoff = 1; /* Four in 1 Row! (french) */ + + if (app_data.crc == 0x6CEBAB74) + regionoff = 12; /* P.T. Barnum's Acrobats! (European version) */ + if (app_data.crc == 0xE7B26A56) + regionoff = 12; /* P.T. Barnum's Acrobats! (European version - Extra keys) */ + + if (app_data.crc == 0xFB83171E) + mxsnap = 3; /* Blockout*/ + if (app_data.crc == 0xD38153F6) + mxsnap = 3; /* Blockout (french) */ + if (app_data.crc == 0xA57E1724) + mxsnap = 12; /* Catch the Ball / Noughts and Crosses */ + if (app_data.crc == 0xBE4FF48E) + mxsnap = 12; /* Catch the Ball / Noughts and Crosses modified */ + if (app_data.crc == 0xFD179F6D) + mxsnap = 3; /* Clay Pigeon! */ + if (app_data.crc == 0x9C9DDDF9) + mxsnap = 3; /* Verkehr */ + if (app_data.crc == 0x95936B07) + mxsnap = 3; /* Super Cobra */ + if (app_data.crc == 0x881CEAE4) + mxsnap = 3; /* Wall Street */ + if (app_data.crc == 0x9E42E766) + mxsnap = 0; /* Turtles */ + if (app_data.crc == 0x1C750349) + mxsnap = 0; /* Turtles (European version) */ + if (app_data.crc == 0xD0BC4EE6) + mxsnap = 3; /* Frogger */ + if (app_data.crc == 0xA57D84F3) + mxsnap = 3; /* Frogger BR */ + if (app_data.crc == 0x3BFEF56B) + mxsnap = 6; /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) + mxsnap = 6; /* Four in 1 Row! (french) */ + if (app_data.crc == 0x7C747245) + mxsnap = 6; /* Four in 1 Row! modified */ + + if (app_data.crc == 0xA7344D1F) + setvideomode(1); /* Atlantis */ + if (app_data.crc == 0x39E31BF0) + setvideomode(1); /* Jake */ + if (app_data.crc == 0x92D0177B) + setvideomode(1); /* Jake (hack) */ + if (app_data.crc == 0x3351FEDA) + setvideomode(1); /* Power Lords */ + if (app_data.crc == 0x40AE062D) + setvideomode(1); /* Power Lords (alternate) */ + if (app_data.crc == 0xD158EEBA) + setvideomode(1); /* Labirinth */ + if (app_data.crc == 0x26B0FF5B) + setvideomode(1); /* Nightmare */ + if (app_data.crc == 0xDF36683F) + setvideomode(1); /* Shark Hunter */ + if (app_data.crc == 0xAF307559) + setvideomode(1); /* Super Bee 8Kb */ + if (app_data.crc == 0x9585D511) + setvideomode(1); /* Super Bee 4Kb */ + if (app_data.crc == 0x58FA6766) + setvideomode(1); /* War of the Nerves */ + if (app_data.crc == 0x58FA6766) + setvideomode(1); /* War of the Nerves */ + if (app_data.crc == 0x39989464) + setvideomode(1); /* Hockey! / Soccer! */ + if (app_data.crc == 0x3BFEF56B) + setvideomode(1); /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) + setvideomode(1); /* Four in 1 Row! (french) */ + if (app_data.crc == 0x7C747245) + setvideomode(1); /* Four in 1 Row! modified */ + if (app_data.crc == 0x68560DC7) + setvideomode(1); /* Jopac Moto Crash */ + if (app_data.crc == 0x020FCA15) + setvideomode(1); /* Jopac Moto Crash modified (non VP+) */ + if (app_data.crc == 0xC4134DF8) + setvideomode(1); /* Helicopter Rescue + */ + if (app_data.crc == 0x0D2D721D) + setvideomode(1); /* Trans American Rally + */ + if (app_data.crc == 0x9D72D4E9) + setvideomode(1); /* Blobbers */ + if (app_data.crc == 0xB2F0F0B4) + setvideomode(1); /* Le Tresor Englouti + */ + if (app_data.crc == 0x0B2DEB61) + setvideomode(1); /* Tutankham */ + if (app_data.crc == 0x313547EB) + setvideomode(1); /* VP53 */ + if (app_data.crc == 0x06861A9C) + setvideomode(1); /* Flashpoint 5 (Videopac adaption) */ + if (app_data.crc == 0xA57E1724) + setvideomode(0); /* Catch the Ball / Noughts and Crosses */ + if (app_data.crc == 0xBE4FF48E) + setvideomode(0); /* Catch the Ball / Noughts and Crosses modified */ + if (app_data.crc == 0xFB83171E) + setvideomode(0); /* Blockout*/ + if (app_data.crc == 0xD38153F6) + setvideomode(0); /* Blockout (french) */ + if (app_data.crc == 0x9BFC3E01) + setvideomode(0); /* Demon Attack */ + if (app_data.crc == 0x50AF9D45) + setvideomode(0); /* Demon Attack + */ + if (app_data.crc == 0x9884EF36) + setvideomode(0); /* Demon Attack + modified */ + if (app_data.crc == 0x4A578DFE) + setvideomode(0); /* Restaurant ntsc */ + if (app_data.crc == 0x863D5E2D) + setvideomode(0); /* Shark Hunter ntsc */ + + if (app_data.crc == 0xD62814A3) + evblclk = 12000; /* Pick Axe Pete */ + if (app_data.crc == 0xB2FFB353) + evblclk = 12000; /* Pick Axe Pete + */ + if (app_data.crc == 0x81C20196) + evblclk = 12000; /* Pick Axe Pete + (modified) */ + + if ((app_data.crc == 0xF390BFEC) || (app_data.crc == 0x825976A9) + || (app_data.crc == 0x61A350E6)) { /* Mousing Cat */ + setvideomode(1); + evblclk = 7642; + } + + if (app_data.crc == 0xD0BC4EE6) { /* Frogger */ + setvideomode(1); + evblclk = 7642; + + } + if (app_data.crc == 0x26517E77) { /* Commando Noturno */ + setvideomode(1); + evblclk = 6100; + regionoff = 12; + } + if (app_data.crc == 0xA57E1724) { /* Catch the ball*/ + regionoff = 5; + sproff = 1; + + } + + if ((app_data.crc == 0x2DCB77F0) || (app_data.crc == 0xF6882734)) { /* Depth Charge / Marksman */ + setvideomode(1); + evblclk = 8000; + } + if (app_data.crc == 0x881CEAE4) { /* Wall Street */ + setvideomode(1); + evblclk = 6100; + } + if (app_data.crc == 0xD0BC4EE6) + tweakedaudio = 1; /* Frogger */ + if (app_data.crc == 0xA57D84F3) + tweakedaudio = 1; /* Frogger BR */ + if (app_data.crc == 0x5216771A) + tweakedaudio = 1; /* Popeye */ + if (app_data.crc == 0xAFB23F89) + tweakedaudio = 1; /* Musician */ + if (app_data.crc == 0xC4134DF8) + tweakedaudio = 1; /* Helicopter Rescue + */ + if (app_data.crc == 0x0D2D721D) + tweakedaudio = 1; /* Trans American Rally + */ + + if (app_data.crc == 0xD3B09FEC) + sproff = 1; /* Volleyball! */ + if (app_data.crc == 0x551E38A2) + sproff = 1; /* Volleyball! (french) */ + +} + +int snapline(int pos, Byte reg, int t) +{ + int i; + if (pos < MAXLINES + MAXSNAP + MAXSNAP) { + for (i = 0; i < mxsnap; i++) { + if (snapedlines[pos + MAXSNAP - i][reg][t]) + return pos - i; + if (snapedlines[pos + MAXSNAP + i][reg][t]) + return pos + i; + } + snapedlines[pos + MAXSNAP][reg][t] = 1; + } + return pos; +} + +static void setvideomode(int t) +{ + if (t) { + evblclk = EVBLCLK_PAL; + fps = FPS_PAL; + } else { + evblclk = EVBLCLK_NTSC; + fps = FPS_NTSC; + } +} + +int savestate(char* filename) +{ + FILE *fn; + + fn = fopen(filename, "wb"); + if (fn == NULL) { + fprintf(stderr, "Error opening state-file %s: %i\n", filename, errno); + return (errno); + } + + fwrite(&app_data.crc, sizeof(app_data.crc), 1, fn); + fwrite(&app_data.bios, sizeof(app_data.bios), 1, fn); + + fwrite(VDCwrite, 256, 1, fn); + fwrite(extRAM, 256, 1, fn); + fwrite(intRAM, 64, 1, fn); + + fwrite(&pc, sizeof(pc), 1, fn); + fwrite(&sp, sizeof(sp), 1, fn); + fwrite(&bs, sizeof(bs), 1, fn); + fwrite(&p1, sizeof(p1), 1, fn); + fwrite(&p2, sizeof(p2), 1, fn); + + fwrite(&ac, sizeof(ac), 1, fn); + fwrite(&cy, sizeof(cy), 1, fn); + fwrite(&f0, sizeof(f0), 1, fn); + fwrite(&A11, sizeof(A11), 1, fn); + fwrite(&A11ff, sizeof(A11ff), 1, fn); + + fwrite(&timer_on, sizeof(timer_on), 1, fn); + fwrite(&count_on, sizeof(count_on), 1, fn); + fwrite(®_pnt, sizeof(reg_pnt), 1, fn); + + fwrite(&tirq_en, sizeof(tirq_en), 1, fn); + fwrite(&xirq_en, sizeof(xirq_en), 1, fn); + fwrite(&irq_ex, sizeof(irq_ex), 1, fn); + fwrite(&xirq_pend, sizeof(xirq_pend), 1, fn); + fwrite(&tirq_pend, sizeof(tirq_pend), 1, fn); + + fclose(fn); + return (0); + +} + +int loadstate(char* filename) +{ + FILE *fn; + int bios; + unsigned long crc; + + fn = fopen(filename, "rb"); + if (fn == NULL) { + // no savefile yet + return (errno); + } + + sys_fread(&crc, sizeof(crc), 1, fn); + if (crc != app_data.crc) { + // wrong cart + return (199); + } + + sys_fread(&bios, sizeof(bios), 1, fn); + if (bios != app_data.bios) // wrong bios + { + return (200 + bios); + } + + sys_fread(VDCwrite, 256, 1, fn); + sys_fread(extRAM, 256, 1, fn); + sys_fread(intRAM, 64, 1, fn); + + sys_fread(&pc, sizeof(pc), 1, fn); + sys_fread(&sp, sizeof(sp), 1, fn); + sys_fread(&bs, sizeof(bs), 1, fn); + sys_fread(&p1, sizeof(p1), 1, fn); + sys_fread(&p2, sizeof(p2), 1, fn); + + sys_fread(&ac, sizeof(ac), 1, fn); + sys_fread(&cy, sizeof(cy), 1, fn); + sys_fread(&f0, sizeof(f0), 1, fn); + sys_fread(&A11, sizeof(A11), 1, fn); + sys_fread(&A11ff, sizeof(A11ff), 1, fn); + + sys_fread(&timer_on, sizeof(timer_on), 1, fn); + sys_fread(&count_on, sizeof(count_on), 1, fn); + sys_fread(®_pnt, sizeof(reg_pnt), 1, fn); + + sys_fread(&tirq_en, sizeof(tirq_en), 1, fn); + sys_fread(&xirq_en, sizeof(xirq_en), 1, fn); + sys_fread(&irq_ex, sizeof(irq_ex), 1, fn); + sys_fread(&xirq_pend, sizeof(xirq_pend), 1, fn); + sys_fread(&tirq_pend, sizeof(tirq_pend), 1, fn); + fclose(fn); + return (0); +} + +size_t sys_fread(void *ptr, size_t size, size_t nitems, FILE *stream) +{ + return fread(ptr, size, nitems, stream); +} diff --git a/clean/src/vmachine.h b/clean/src/vmachine.h new file mode 100755 index 0000000..50ce8a3 --- /dev/null +++ b/clean/src/vmachine.h @@ -0,0 +1,101 @@ +#ifndef VMACHINE_H +#define VMACHINE_H + +#include "types.h" + +#define LINECNT 21 +#define MAXLINES 500 +#define MAXSNAP 50 + +#define VBLCLK 5493 +#define EVBLCLK_NTSC 5964 +#define EVBLCLK_PAL 7259 + +#define FPS_NTSC 60 +#define FPS_PAL 50 + +extern Byte dbstick1, dbstick2; +extern int last_line; + +extern int evblclk; + +extern int master_clk; /* Master clock */ +extern int int_clk; /* counter for length of /INT pulses for JNI */ +extern int h_clk; /* horizontal clock */ +extern Byte coltab[256]; +extern int mstate; + +extern Byte rom_table[8][4096]; +extern Byte intRAM[]; +extern Byte extRAM[]; +extern Byte extROM[]; +extern Byte VDCwrite[256]; +extern Byte ColorVector[MAXLINES]; +extern Byte AudioVector[MAXLINES]; +extern Byte *rom; +extern Byte *megarom; + +extern int frame; +extern int key2[128]; +extern int key2vcnt; +extern unsigned long clk_counter; + +extern int enahirq; +extern int pendirq; +extern int useforen; +extern long regionoff; +extern int sproff; +extern int tweakedaudio; + +Byte read_P2(void); +int snapline(int pos, Byte reg, int t); +void ext_write(Byte dat, ADDRESS adr); +Byte ext_read(ADDRESS adr); +void handle_vbl(void); +void handle_evbl(void); +void handle_evbll(void); +Byte in_bus(void); +void write_p1(Byte d); +Byte read_t1(void); +void init_system(void); +void init_roms(void); +void run(void); +int savestate(char* filename); +int loadstate(char* filename); +size_t sys_fread(void * ptr, size_t size, size_t nitems, FILE * stream); + +extern struct resource { + int bank; + int debug; + int stick[2]; + int sticknumber[2]; + int limit; + int sound_en; + int speed; + int wsize; + int fullscreen; + int scanlines; + int voice; + int svolume; + int vvolume; + int exrom; + int three_k; + int filter; + int euro; + int openb; + int megaxrom; + int vpp; + int bios; + unsigned long crc; + char *window_title; + char *scshot; + int scoretype; + int scoreaddress; + int default_highscore; + int breakpoint; + char *statefile; +} app_data; + + +#endif /* VMACHINE_H */ + diff --git a/clean/src/voice.c b/clean/src/voice.c new file mode 100755 index 0000000..1c4a4e9 --- /dev/null +++ b/clean/src/voice.c @@ -0,0 +1,158 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 Voice emulation + */ + +#include +#include "vmachine.h" +#include "cpu.h" +#include "voice.h" +#include "allegro.h" + +static SAMPLE *voices[9][128]; +static int voice_bank = 0; +static int voice_num = -1; +static int voice_addr = 0; +static int voice_ok = 0; +static int voice_st = 0; +static unsigned long clk_voice_start = 0; + +void load_voice_samples(char *path) +{ + int bank, sam, i, ld = 0; + char name[MAXC]; + SAMPLE *sp = NULL; + + printf("Loading voice samples... "); + fflush(stdout); + + for (i = 0; i < 9; i++) { + for (sam = 0; sam < 128; sam++) { + if (i) + bank = 0xE8 + i - 1; + else + bank = 0xE4; + sprintf(name, "%svoice/%02x%02x.wav", path, bank, sam + 0x80); + + voices[i][sam] = load_sample(name); + + if (!voices[i][sam]) { + sprintf(name, "%svoice/%02X%02X.WAV", path, bank, sam + 0x80); + voices[i][sam] = load_sample(name); + } + + if (voices[i][sam]) { + ld++; + if (!sp) + sp = voices[i][sam]; + } + } + } + + printf("%d samples loaded\n", ld); + + if (ld > 0) { + voice_num = allocate_voice(sp); + if (voice_num != -1) + voice_ok = 1; + else { + printf(" ERROR: could not allocate sound card voice\n"); + voice_ok = 0; + } + } + +} + +void update_voice(void) +{ + if (!voice_ok) + return; + if (voice_st == 2) { + if (voice_get_position(voice_num) < 0) { + if ((voice_bank >= 0) && (voice_bank < 9) && (voice_addr >= 0x80) + && (voice_addr <= 0xff)) { + if (voices[voice_bank][voice_addr - 0x80]) { + reallocate_voice(voice_num, + voices[voice_bank][voice_addr - 0x80]); + voice_set_volume(voice_num, (255 * app_data.vvolume) / 100); + voice_start(voice_num); + clk_voice_start = clk_counter; + voice_st = 1; + } else { + voice_st = 0; + } + } + } + } else if (voice_st == 1) { + if ((voice_get_position(voice_num) < 0) + || (clk_counter - clk_voice_start > 20)) { + voice_st = 0; + } + } +} + +void trigger_voice(int addr) +{ + if (voice_ok) { + if (voice_st) + update_voice(); + if ((voice_st == 0) && (voice_bank >= 0) && (voice_bank < 9) + && (addr >= 0x80) && (addr <= 0xff)) { + voice_addr = addr; + voice_st = 2; + update_voice(); + } + } +} + +void set_voice_bank(int bank) +{ + if (!voice_ok) + return; + if ((bank >= 0) && (bank <= 8)) + voice_bank = bank; +} + +int get_voice_status(void) +{ + if (voice_ok) { + update_voice(); + if (voice_st) + return 1; + } + return 0; +} + +void reset_voice(void) +{ + if (voice_ok) { + voice_stop(voice_num); + voice_bank = 0; + voice_addr = 0; + voice_st = 0; + } +} + +void mute_voice(void) +{ + if (voice_ok) { + voice_stop(voice_num); + } +} + +void close_voice(void) +{ + reset_voice(); + voice_ok = 0; +} + diff --git a/clean/src/voice.h b/clean/src/voice.h new file mode 100755 index 0000000..62a8c06 --- /dev/null +++ b/clean/src/voice.h @@ -0,0 +1,14 @@ +#ifndef __VOICE_H +#define __VOICE_H + +void load_voice_samples(char *path); +void update_voice(void); +void trigger_voice(int addr); +void reset_voice(void); +void set_voice_bank(int bank); +void close_voice(void); +void mute_voice(void); +int get_voice_status(void); + +#endif + diff --git a/clean/src/vpp.c b/clean/src/vpp.c new file mode 100755 index 0000000..b2e9b7b --- /dev/null +++ b/clean/src/vpp.c @@ -0,0 +1,549 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Videopac+ G7400 emulation + */ + +#include +#include +#include +#include "types.h" +#include "vmachine.h" +#include "vdc.h" +#include "vpp_cset.h" +#include "vpp.h" +#include "allegro.h" + +static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext, + Byte dw, Byte dh, Byte ul); +static void vpp_update_screen(void); + +static Byte LumReg = 0xff, TraReg = 0xff; +static BITMAP *vppbmp = NULL; +static Byte *colplus = NULL; +static int vppon = 1; +static int vpp_cx = 0; +static int vpp_cy = 0; +static Byte vpp_data = 0; +static int inc_curs = 1; +static int slice = 0; +static int vpp_y0 = 0; +static Byte vpp_r = 0; +Byte dchars[2][960]; +Byte vpp_mem[40][32][4]; +static int frame_cnt = 0; +static int blink_st = 0; +static int slicemode = 0; +static int need_update = 0; + +Byte read_PB(Byte p) +{ + p &= 0x3; + switch (p) { + case 0: + return LumReg >> 4; + break; + case 1: + return LumReg & 0xf; + break; + case 2: + return TraReg >> 4; + break; + case 3: + return TraReg & 0xf; + break; + } + return 0; +} + +void write_PB(Byte p, Byte val) +{ + p &= 0x3; + val &= 0xf; + + switch (p) { + case 0: + LumReg = (val << 4) | (LumReg & 0xf); + break; + case 1: + LumReg = (LumReg & 0xf0) | val; + break; + case 2: + TraReg = (val << 4) | (TraReg & 0xf); + break; + case 3: + TraReg = (TraReg & 0xf0) | val; + break; + } + need_update = 1; +} + +Byte vpp_read(ADDRESS adr) +{ + Byte t; + static Byte ta = 0; + static Byte tb = 0; + + switch (adr) { + case 4: + return ta; + case 5: + /* get return value from last read */ + t = tb; + /* the real VPP starts a read cycle, + * the data gets returned at next read */ + if (slicemode) { + Byte ext, chr; + chr = vpp_mem[vpp_cx][vpp_cy][0]; + ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0; + if (chr < 0xA0) { + ta = 0; + fprintf(stderr, "unsupported: CHARROM read %d %d %d\n", chr, + ext, slice); + } else { + ta = dchars[ext][(chr - 0xA0) * 10 + slice]; + ta = ((ta & 0x80) >> 7) | ((ta & 0x40) >> 5) + | ((ta & 0x20) >> 3) | ((ta & 0x10) >> 1) + | ((ta & 0x08) << 1) | ((ta & 0x04) << 3) + | ((ta & 0x02) << 5) | ((ta & 0x01) << 7); + } + tb = 0xff; /* real VPP seems to return junk */ + slice = (slice + 1) % 10; + } else { + ta = vpp_mem[vpp_cx][vpp_cy][1]; + tb = vpp_mem[vpp_cx][vpp_cy][0]; + if (inc_curs) { + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) + vpp_cy = 0; + } + } + } + return t; + case 6: + return 0; + default: + return 0; + } +} + +void vpp_write(Byte dat, ADDRESS adr) +{ + static Byte ta; + + switch (adr) { + case 0: + if (!slicemode) + vpp_mem[vpp_cx][vpp_cy][1] = dat; + else + ta = dat; + break; + case 1: + if (slicemode) { + Byte ext, chr; + chr = vpp_mem[vpp_cx][vpp_cy][0]; + ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0; + if (chr >= 0xA0) + dchars[ext][(chr - 0xA0) * 10 + slice] = ((ta & 0x80) >> 7) + | ((ta & 0x40) >> 5) | ((ta & 0x20) >> 3) + | ((ta & 0x10) >> 1) | ((ta & 0x08) << 1) + | ((ta & 0x04) << 3) | ((ta & 0x02) << 5) + | ((ta & 0x01) << 7); + slice = (slice + 1) % 10; + } else { + vpp_mem[vpp_cx][vpp_cy][0] = dat; + if ((dat > 0x7f) && (dat < 0xa0) + && (!(vpp_mem[vpp_cx][vpp_cy][1] & 0x80))) { + vpp_mem[vpp_cx][vpp_cy][2] = dat; + vpp_mem[vpp_cx][vpp_cy][3] = vpp_mem[vpp_cx][vpp_cy][1]; + } else { + vpp_mem[vpp_cx][vpp_cy][2] = vpp_mem[vpp_cx][vpp_cy][3] = 0; + } + if (inc_curs) { + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) + vpp_cy = 0; + } + } + } + break; + case 2: + vpp_data = dat; + break; + case 3: + switch (dat & 0xe0) { + case 0x00: /* plus_cmd_brow */ + vpp_cy = vpp_data & 0x1f; + vpp_cx = 0; + break; + case 0x20: /* plus_cmd_loady */ + vpp_cy = vpp_data & 0x1f; + break; + case 0x40: /* plus_cmd_loadx */ + vpp_cx = (vpp_data & 0x3f) % 40; + break; + case 0x60: /* plus_cmd_incc */ + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) + vpp_cy = 0; + } + break; + case 0x80: /* plus_cmd_loadm */ + slicemode = 0; + slice = (vpp_data & 0x1f) % 10; + switch (vpp_data & 0xe0) { + case 0x00: /* plus_loadm_wr */ + inc_curs = 1; + break; + case 0x20: /* plus_loadm_rd */ + inc_curs = 1; + break; + case 0x40: /* plus_loadm_wrni */ + inc_curs = 0; + break; + case 0x60: /* plus_loadm_rdni */ + inc_curs = 0; + break; + case 0x80: /* plus_loadm_wrsl */ + slicemode = 1; + break; + case 0xA0: /* plus_loadm_rdsl */ + slicemode = 1; + break; + default: + break; + } + break; + case 0xA0: /* plus_cmd_loadr */ + vpp_r = vpp_data; + break; + case 0xC0: /* plus_cmd_loady0 */ + if (vpp_data & 0x20) + fprintf(stderr, "unsupported: global double height"); + vpp_y0 = (vpp_data & 0x1f) % 24; + break; + default: + break; + } + break; + default: + break; + } + + need_update = 1; +} + +void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, + int toth) +{ + int i, x, y, t, c, nc, clrx, clry; + int tcol[16], m[8] = { 0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80 }; + Byte *pnt, *pnt2, *pnt3; + + if (vppon) { + memset(colplus, 0, BMPW * BMPH); + vppon = 0; + } + + if (TraReg == 0xff) + return; + + vppon = 1; + + frame_cnt--; + if (frame_cnt <= 0) { + frame_cnt = 100; + blink_st = 1 - blink_st; + need_update = 1; + } + + if (need_update) + vpp_update_screen(); + + for (i = 0; i < 8; i++) + tcol[i] = tcol[i + 8] = !(TraReg & m[i]); + + if (w > totw - offx) + w = totw - offx; + if (h > toth - offy) + h = toth - offy; + + if (w > vppbmp->w) + w = vppbmp->w; + if (h > vppbmp->h) + h = vppbmp->h; + + clrx = clry = 0; + for (i = 0; (!clrx) && (i < totw); i++) + if (tcol[vmem[offy * totw + i] & 7]) + clrx = 1; + for (i = 0; (!clry) && (i < toth); i++) + if (tcol[vmem[i * totw + offx] & 7]) + clry = 1; + if (clrx) + for (y = 0; y < offy; y++) + for (x = 0; x < totw; x++) + vmem[y * totw + x] = 0; + if (clry) + for (y = 0; y < toth; y++) + for (x = 0; x < offx; x++) + vmem[y * totw + x] = 0; + + for (y = 0; y < h; y++) { + pnt = vmem + (offy + y) * totw + offx; + pnt2 = (Byte *) vppbmp->line[y]; + + x = 0; + while (x < w) { + pnt3 = pnt; + c = *pnt++; + t = x++; + + if ((((x + offx) & 3) == 0) && (sizeof(unsigned long) == 4)) { + unsigned long cccc, dddd, *p = (unsigned long*) pnt; + int t2 = x, w2 = w - 4; + cccc = (((unsigned long) c) & 0xff) + | ((((unsigned long) c) & 0xff) << 8) + | ((((unsigned long) c) & 0xff) << 16) + | ((((unsigned long) c) & 0xff) << 24); + dddd = *p++; + while ((x < w2) && (dddd == cccc)) { + x += 4; + dddd = *p++; + } + pnt += x - t2; + } + + if (c < 16) { + if (tcol[c]) { + if (app_data.openb) + for (i = 0; i < x - t; i++) + *pnt3++ = *pnt2++ & 0xf; + else { + memcpy(pnt3, pnt2, x - t); + pnt2 += x - t; + } + } else { + for (i = 0; i < x - t; i++) { + nc = *pnt2++; + if ((nc & 0x10) && app_data.openb) { + *pnt3++ = nc & 0xf; + } else if (nc & 8) { + colplus[pnt3++ - vmem] = 0x40; + } else { + pnt3++; + } + } + } + } + } + } +} + +static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext, + Byte dw, Byte dh, Byte ul) +{ + int xx, yy, d, m, k; + + if ((x > 39) || (y > 24) || (ext > 1)) + return; + + d = (dh == 2) ? 5 : 0; + + for (yy = 0; yy < 10; yy++) { + if (ul && (d == 9)) + k = 255; + else if (ch >= 0xA0) + k = dchars[ext][(ch - 0xA0) * 10 + d]; + else if (ch >= 0x80) + k = 255; + else + k = vpp_cset[ext][ch * 10 + d]; + + m = (dw == 2) ? 0x08 : 0x80; + + for (xx = 0; xx < 8; xx++) { + vppbmp->line[y * 10 + yy][x * 8 + xx] = (k & m) ? c1 : c0; + if ((xx % 2) || (dw == 0)) + m >>= 1; + } + if ((yy % 2) || (dh == 0)) + d++; + } +} + +static void vpp_update_screen(void) +{ + int i, x, y, l, chr, attr, ext, c0, c1, dw, dh, hpar, vpar, lvd, lhd, + ser_chr, ser_atr, ul, conc, box, swapcol; + int tlum[8], m[8] = { 0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80 }; + + clear(vppbmp); + + for (i = 0; i < 8; i++) + tlum[i] = (LumReg & m[i]) ? 0 : 8; + + vpar = lvd = 0; + for (y = 0; y < 25; y++) { + + vpar = (lvd == 0) ? 0 : 1 - vpar; + + l = (y == 0) ? 31 : (y - 1 + vpp_y0) % 24; + c0 = ul = conc = box = 0; + + hpar = lhd = 0; + for (x = 0; x < 40; x++) { + hpar = (lhd == 0) ? 0 : 1 - hpar; + + chr = vpp_mem[x][l][0]; + attr = vpp_mem[x][l][1]; + c1 = attr & 0x7; + c1 = ((c1 & 2) | ((c1 & 1) << 2) | ((c1 & 4) >> 2)); + ext = (attr & 0x80) ? 1 : 0; + + ser_chr = vpp_mem[x][l][2]; + ser_atr = vpp_mem[x][l][3]; + if (ser_chr) { + c0 = (ser_atr >> 4) & 0x7; + c0 = ((c0 & 2) | ((c0 & 1) << 2) | ((c0 & 4) >> 2)); + ul = ser_chr & 4; + conc = ser_chr & 1; + box = ser_chr & 2; + } + + if (ext) { + c0 = (attr >> 4) & 0x7; + c0 = ((c0 & 2) | ((c0 & 1) << 2) | ((c0 & 4) >> 2)); + dw = dh = 0; + } else { + dw = (attr & 0x20) ? (hpar ? 2 : 1) : 0; + dh = (attr & 0x10) ? (vpar ? 2 : 1) : 0; + if (dw) + lhd = 1; + if (dh) + lvd = 1; + } + + swapcol = 0; + + /* cursor display */ + if ((x == vpp_cx) && (l == vpp_cy)) { + /* on cursor position */ + if (vpp_r & 0x10) { + /* cursor display active */ + swapcol = !swapcol; + if ((vpp_r & 0x80) && blink_st) { + /* blinking active */ + swapcol = !swapcol; + } + } + } + + /* invert attribute */ + if ((!ext) && (attr & 0x40)) + swapcol = !swapcol; + + /* blinking chars */ + if ((vpp_r & 0x80) && !(attr & 8) && !blink_st) { + /* cursor handling is done already */ + if (!(vpp_r & 0x10) || (x != vpp_cx) || (l != vpp_cy)) { + c1 = c0; + } + } + + if (((y == 0) && (vpp_r & 8)) || ((y != 0) && (vpp_r & 1))) { + if ((!conc) || (!(vpp_r & 4))) { + if (box || (!(vpp_r & 2))) { + if (swapcol) + vpp_draw_char(x, y, chr, c1 | tlum[c1], + c0 | tlum[c0], ext, dw, dh, ul); + else + vpp_draw_char(x, y, chr, c0 | tlum[c0], + c1 | tlum[c1], ext, dw, dh, ul); + } else { + vpp_draw_char(x, y, 255, (app_data.openb) ? 16 : 0, 0, + 0, 0, 0, 0); + } + } + } + } + + } + + if (vpp_r & 0x20) { + for (y = vppbmp->h - 1; y >= 10; y--) + for (x = 0; x < vppbmp->w; x++) + vppbmp->line[y][x] = vppbmp->line[(y - 10) / 2 + 10][x]; + } + + need_update = 0; +} + +void load_colplus(Byte *col) +{ + if (vppon) + memcpy(col, colplus, BMPW * BMPH); + else + memset(col, 0, BMPW * BMPH); +} + +void init_vpp(void) +{ + int i, j, k; + + if (!vppbmp) + vppbmp = create_bitmap(320, 250); + if (!colplus) + colplus = (Byte *) malloc(BMPW * BMPH); + + if ((!vppbmp) || (!colplus)) { + fprintf(stderr, + "Could not allocate memory for Videopac+ screen buffer.\n"); + exit(EXIT_FAILURE); + } + + clear(vppbmp); + memset(colplus, 0, BMPW * BMPH); + + LumReg = TraReg = 0xff; + vpp_cx = 0; + vpp_cy = 0; + vpp_y0 = 0; + vpp_r = 0; + inc_curs = 1; + vpp_data = 0; + frame_cnt = 0; + blink_st = 0; + slice = 0; + slicemode = 0; + need_update = 1; + vppon = 1; + + for (i = 0; i < 2; i++) + for (j = 0; j < 960; j++) + dchars[i][j] = 0; + + for (i = 0; i < 40; i++) + for (j = 0; j < 32; j++) + for (k = 0; k < 4; k++) + vpp_mem[i][j][k] = 0; +} + diff --git a/clean/src/vpp.h b/clean/src/vpp.h new file mode 100755 index 0000000..a9e1276 --- /dev/null +++ b/clean/src/vpp.h @@ -0,0 +1,12 @@ +#ifndef __VPP_H +#define __VPP_H + +Byte read_PB(Byte p); +void write_PB(Byte p, Byte val); +Byte vpp_read(ADDRESS adr); +void vpp_write(Byte dat, ADDRESS adr); +void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth); +void init_vpp(void); +void load_colplus(Byte *col); + +#endif diff --git a/clean/src/vpp_cset.c b/clean/src/vpp_cset.c new file mode 100755 index 0000000..4ac0f91 --- /dev/null +++ b/clean/src/vpp_cset.c @@ -0,0 +1,285 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Videopac+ character table + */ + + +#include "types.h" +#include "vpp_cset.h" + + +Byte vpp_cset[2][1280] = { + { + /* Alphanumeric */ + 0x00,0x38,0x44,0x40,0x20,0x10,0x00,0x10,0x00,0x00, + 0x00,0x10,0x28,0x00,0x38,0x44,0x7c,0x44,0x00,0x00, + 0x00,0x08,0x10,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x08,0x14,0x10,0x38,0x10,0x24,0x3c,0x00,0x00, + 0x00,0x10,0x38,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10,0x20, + 0x00,0x28,0x28,0x7c,0x28,0x7c,0x28,0x28,0x00,0x00, + 0x00,0x20,0x18,0x00,0x38,0x44,0x7c,0x44,0x00,0x00, + 0x00,0x20,0x18,0x00,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x10,0x08,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x3c,0x50,0x50,0x58,0x50,0x50,0x3c,0x00,0x00, + 0x00,0x08,0x14,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x00,0x10,0x20,0x7f,0x20,0x10,0x00,0x00,0x00, + 0x00,0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10,0x10, + 0x00,0x00,0x08,0x04,0xfe,0x04,0x08,0x00,0x00,0x00, + 0x10,0x10,0x10,0x10,0x10,0x10,0x54,0x38,0x10,0x00, + 0x00,0x18,0x24,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x7c,0x00,0x00, + 0x00,0x08,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x28,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x10,0x20, + 0x00,0x10,0x28,0x00,0x44,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x20,0x10,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,0x00,0x00, + 0x00,0x20,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x52,0x5e,0x50,0x3e,0x00,0x00, + 0x00,0x10,0x28,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x40,0xc0,0x40,0x44,0x4c,0x14,0x3e,0x04,0x00, + 0x00,0x40,0xc0,0x40,0x4c,0x52,0x04,0x08,0x1e,0x00, + 0x00,0xe0,0x20,0x40,0x24,0xcc,0x14,0x3e,0x04,0x00, + 0x00,0x10,0x28,0x00,0x38,0x44,0x44,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + 0x00,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x28,0x00,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x10,0x28,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x60,0x64,0x08,0x10,0x20,0x4c,0x0c,0x00,0x00, + 0x00,0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00,0x00, + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x00, + 0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00,0x00, + 0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10,0x00,0x00, + 0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, + 0x01,0x02,0x02,0x04,0x08,0x10,0x20,0x20,0x40,0x80, + 0x00,0x10,0x28,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7c,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x18,0x04,0x44,0x38,0x00,0x00, + 0x00,0x08,0x18,0x28,0x48,0x7c,0x08,0x08,0x00,0x00, + 0x00,0x7c,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00, + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + 0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x38,0x00,0x00, + 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40,0x00, + 0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00, + 0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,0x00,0x00, + 0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00, + 0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00,0x00, + 0x00,0x38,0x44,0x5c,0x54,0x5c,0x40,0x38,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x7c,0x44,0x44,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00, + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x7c,0x00,0x00, + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x00,0x00, + 0x00,0x38,0x44,0x40,0x40,0x4c,0x44,0x3c,0x00,0x00, + 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00, + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x1c,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00, + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00, + 0x00,0x44,0x6c,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + 0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + 0x00,0x44,0x44,0x44,0x54,0x54,0x54,0x28,0x00,0x00, + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + 0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x7c,0x00,0x00, + 0x00,0x1c,0x10,0x10,0x10,0x10,0x10,0x1c,0x00,0x00, + 0x80,0x40,0x40,0x20,0x10,0x08,0x04,0x04,0x02,0x01, + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + 0x00,0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00, + 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x3c,0x00,0x00, + 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x44,0x44,0x3c,0x04,0x24,0x18, + 0x00,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30, + 0x00,0x20,0x20,0x24,0x28,0x30,0x28,0x24,0x00,0x00, + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00,0x00, + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40, + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x04, + 0x00,0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00, + 0x00,0x20,0x20,0x38,0x20,0x20,0x20,0x18,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x4c,0x34,0x04,0x44,0x38, + 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x7c,0x00,0x00, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + { + /* Separated semi-graphic */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + /* Mosaic semi-graphic */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} +}; + diff --git a/clean/src/vpp_cset.h b/clean/src/vpp_cset.h new file mode 100755 index 0000000..d0a2887 --- /dev/null +++ b/clean/src/vpp_cset.h @@ -0,0 +1,6 @@ +#ifndef __VPP_CSET_H +#define __VPP_CSET_H + +extern Byte vpp_cset[2][1280]; + +#endif diff --git a/clean/stubs/allegro.c b/clean/stubs/allegro.c new file mode 100755 index 0000000..cec10f6 --- /dev/null +++ b/clean/stubs/allegro.c @@ -0,0 +1,207 @@ + +#include "allegro.h" + +#include +#include +#include +#define abs(a) miabs(a) + +int miabs(int a){ + if((a)<0)a=-a; + return a; +} + +void upcase(char *p) +{ + while(*p != '\0') + { + if(*p >= 97 && *p <= 122) + *p -= 32; + ++p; + } +} +void downcase(char *p) +{ + while(*p != '\0') + { + if(*p >= 97-32 && *p <= 122-32) + *p += 32; + ++p; + } +} + +void clear(BITMAP *buff){ + + memset(&buff->line,0,buff->w*buff->h); +} + +BITMAP *create_bitmap(int w,int h){ + + BITMAP *buff; + + buff = malloc(sizeof (BITMAP)); + buff->line=malloc(1*w*h); + + buff->w=w; + buff->h=h; + buff->pitch=w; + buff->depth=1; + + return buff; +} + +int destroy_bitmap(BITMAP *buff){ + + if (buff->line) { + free(buff->line); + } + free(buff); + + return 0; +} + + +void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color){ + + int i,j,idx; + + int dx= abs(x2-x); + int dy= abs(y2-y); + int V_WIDTH = buff->w; + unsigned char *buffer=buff->line[0]; + + for(i=x;iw; + unsigned char *buffer=buff->line[0]; + + for(i=x;iw; + unsigned char *buffer=buff->line[0]; + + for(i=x;iw; + unsigned char *buffer=buff->line[0]; + + for(j=y;jw; + unsigned char *buffer=buff->line[0]; + + dx = x2 - x1; + dy = y2 - y1; + sx = (dx >= 0) ? 1 : -1; + sy = (dy >= 0) ? 1 : -1; + + if (dx==0) { + if (dy>0) { + DrawVline(buff, x1, y1,0, dy, color); + return; + + } else if (dy<0) { + DrawVline(buff, x1, y2,0, -dy, color); + return; + + } else { + idx=x1+y1*V_WIDTH; + buffer[idx]=color; + return ; + } + } + if (dy == 0) { + if (dx>0) { + DrawHline(buff, x1, y1, dx, 0, color); + return; + + } else if (dx<0) { + DrawHline(buff, x2, y1, -dx,0, color); + return; + } + } + + dx = sx * dx + 1; + dy = sy * dy + 1; + + pixx = 1; + pixy = V_WIDTH; + + pixx *= sx; + pixy *= sy; + + if (dx < dy) { + swaptmp = dx; + dx = dy; + dy = swaptmp; + swaptmp = pixx; + pixx = pixy; + pixy = swaptmp; + } + + x = 0; + y = 0; + + idx=x1+y1*V_WIDTH; + + for (; x < dx; x++, idx +=pixx) { + buffer[idx]=color; + y += dy; + if (y >= dx) { + y -= dx; + idx += pixy; + } + } + +} diff --git a/clean/stubs/allegro.h b/clean/stubs/allegro.h new file mode 100755 index 0000000..0295ac9 --- /dev/null +++ b/clean/stubs/allegro.h @@ -0,0 +1,81 @@ + +#ifndef ALLEGRO_H +#define ALLEGRO_H + +#define INLINE static inline +#define rest(a) usleep(a) +#define strupr upcase +#define strlwr downcase +#define keypressed() 0 +#define poll_keyboard() +#define yield_timeslice() + +typedef struct +{ + unsigned char *line; + int w; + int h; + int pitch; + int depth; + +}BITMAP; + +//typedef struct +//{ +// unsigned char r; +// unsigned char g; +// unsigned char b; +//}APALETTE; + +typedef struct RGB +{ + unsigned char r, g, b; + unsigned char filler; +} RGB; +#define PAL_SIZE 256 +typedef RGB PALETTE[PAL_SIZE]; + +struct FONT_VTABLE; +typedef struct FONT +{ + void *data; + int height; + struct FONT_VTABLE *vtable; +} FONT; + +typedef struct AUDIOSTREAM +{ +} AUDIOSTREAM; + +typedef struct DIGI_DRIVER /* driver for playing digital sfx */ +{ +} DIGI_DRIVER; + +#define DIGI_AUTODETECT -1 /* for passing to install_sound() */ +#define MIDI_NONE 0 + +#define GFX_TEXT -1 +#define GFX_AUTODETECT 0 +#define GFX_AUTODETECT_FULLSCREEN 1 +#define GFX_AUTODETECT_WINDOWED 2 +#define SWITCH_PAUSE 1 +extern BITMAP * screen; +void set_color_depth (int depth); +int set_gfx_mode (int card, int w, int h, int v_w, int v_h); +void set_palette (const PALETTE p); +void set_window_title (const char *name); +int set_display_switch_mode (int mode); +int set_gfx_mode (int card, int w, int h, int v_w, int v_h); +void acquire_screen (void); +void release_screen (void); +void clear (BITMAP *bmp); + +void stretch_blit (BITMAP *s, BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h); + +void textprintf_ex (BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *format, ...); + +extern unsigned char key[256*2]; + +#define INLINE static inline + +#endif diff --git a/src/Makefile b/src/Makefile new file mode 100755 index 0000000..81abdae --- /dev/null +++ b/src/Makefile @@ -0,0 +1,72 @@ +CC = gcc +WINDRES = windres + +CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include +LFLAGS = -mno-cygwin -s +LIBALLEG = -L/usr/local/lib -lalleg + + +all: o2em.exe dis48.exe + +clean: + del -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res o2em.exe dis48.exe + + +o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG) + +dis48.exe: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h + $(CC) $(CFLAGS) -c score.c -o score.o + +o2em.res: o2em.rc o2em.ico + $(WINDRES) -O coff -o o2em.res -i o2em.rc + diff --git a/src/Makefile.djgpp b/src/Makefile.djgpp new file mode 100755 index 0000000..e170e8a --- /dev/null +++ b/src/Makefile.djgpp @@ -0,0 +1,71 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer +LFLAGS = -s +LIBALLEG = -lalleg + + +all: o2em.exe dis48.exe + +clean: + del *.o + + +o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG) + +dis48.exe: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h + $(CC) $(CFLAGS) -c score.c -o score.o + +o2em.res: o2em.rc o2em.ico + $(WINDRES) -O coff -o o2em.res -i o2em.rc + diff --git a/src/Makefile.freebsd b/src/Makefile.freebsd new file mode 100755 index 0000000..94b49d0 --- /dev/null +++ b/src/Makefile.freebsd @@ -0,0 +1,68 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer -I${PREFIX}/include -DFREEBSD -DPREFIX=\"${PREFIX}\" +LFLAGS = -s +LIBALLEG = -L${PREFIX}/lib -lalleg -lalleg_unsharable + + +all: o2em dis48 + +clean: + rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o + + +o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG) + +dis48: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48 + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h types.h + $(CC) $(CFLAGS) -c score.c -o score.o + diff --git a/src/Makefile.linux b/src/Makefile.linux new file mode 100755 index 0000000..39f0170 --- /dev/null +++ b/src/Makefile.linux @@ -0,0 +1,68 @@ +CC = gcc + +CFLAGS = -O3 -Wall -fomit-frame-pointer -I/usr/include +LFLAGS = -s +LIBALLEG = /usr/lib/liballeg.so.4.2 -lalleg_unsharable + + +all: o2em dis48 + +clean: + rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o + + +o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG) + +dis48: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48 + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +score.o: score.c score.h vmachine.h types.h + $(CC) $(CFLAGS) -c score.c -o score.o + diff --git a/src/Makefile.mingw b/src/Makefile.mingw new file mode 100755 index 0000000..3f25bda --- /dev/null +++ b/src/Makefile.mingw @@ -0,0 +1,69 @@ +CC = gcc +WINDRES = windres + +CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include +LFLAGS = -mno-cygwin -s +LIBALLEG = -L/usr/local/lib -lalleg + + +all: o2em.exe dis48.exe + +clean: + rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res + + +o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res + $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res -o o2em.exe $(LIBALLEG) + +dis48.exe: dis48.o table.o + $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe + + +audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h + $(CC) $(CFLAGS) -c audio.c -o audio.o + +cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h + $(CC) $(CFLAGS) -c cpu.c -o cpu.o + +cset.o: cset.c cset.h types.h + $(CC) $(CFLAGS) -c cset.c -o cset.o + +debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h + $(CC) $(CFLAGS) -c debug.c -o debug.o + +dis48.o: dis48.c types.h table.h + $(CC) $(CFLAGS) -c dis48.c -o dis48.o + +keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h + $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o + +main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h + $(CC) $(CFLAGS) -c main.c -o main.o + +table.o: table.c table.h cpu.h + $(CC) $(CFLAGS) -c table.c -o table.o + +vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h + $(CC) $(CFLAGS) -c vdc.c -o vdc.o + +vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h + $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o + +timefunc.o: timefunc.c timefunc.h + $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o + +voice.o: voice.c voice.h vmachine.h cpu.h + $(CC) $(CFLAGS) -c voice.c -o voice.o + +crc32.o: crc32.c crc32.h + $(CC) $(CFLAGS) -c crc32.c -o crc32.o + +vpp_cset.o: vpp_cset.c vpp_cset.h + $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o + +vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h + $(CC) $(CFLAGS) -c vpp.c -o vpp.o + +o2em.res: o2em.rc o2em.ico + $(WINDRES) -O coff -o o2em.res -i o2em.rc + diff --git a/src/Makefile.win b/src/Makefile.win new file mode 100755 index 0000000..08ae56b --- /dev/null +++ b/src/Makefile.win @@ -0,0 +1,35 @@ +# Project: Project1 +# Makefile created by Dev-C++ 4.9.9.1 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = ../OBJ/file_private.res +OBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES) +LINKOBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES) +LIBS = -L"C:/Dev-Cpp/lib" -L"C:/Dev-Cpp/lib" +INCS = -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include" +CXXINCS = -I"C:/Dev-Cpp/include/c++/3.3.1" -I"C:/Dev-Cpp/include/c++/3.3.1/mingw32" -I"C:/Dev-Cpp/include/c++/3.3.1/backward" -I"C:/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include" +BIN = file.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) + +.PHONY: all all-before all-after clean clean-custom + +all: all-before file.exe all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o "file.exe" $(LIBS) + +../OBJ/get_file.o: get_file.cpp + $(CPP) -c get_file.cpp -o ../OBJ/get_file.o $(CXXFLAGS) + +../OBJ/crc32.o: crc32.c + $(CPP) -c crc32.c -o ../OBJ/crc32.o $(CXXFLAGS) + +../OBJ/file_private.res: file_private.rc + $(WINDRES) -i file_private.rc --input-format=rc -o ../OBJ/file_private.res -O coff --include-dir C:/Dev-Cpp/Projetos/o2em-win diff --git a/src/O2EM.ICO b/src/O2EM.ICO new file mode 100755 index 0000000000000000000000000000000000000000..f867aace5da69bc5f51112fc8e3bfb24694f3bfb GIT binary patch literal 5694 zcmeI0L2kn^5Ci2~&pqS~d4_*xJud%JckRxF0OJ)3}d*7cf{+IkN z%{jlCTm034_NBAy$@zD@a?DQIPoF!#np^zUfcB-c>&f|5UUO^yj0W`YMrT@3pBZ&I z=fj~c=X^NS<(v+Cpu%`@wBX4K`J4~M#(^WjjJb3PpEa?XcCUC#M%sLMGY4s|)_ z!=ZOMo>!H9(JDs{4#lr399reb!J+t7g+r?xIXD!*s&HtPBL_FmuMLketvz?@$7m-z zt^NFFGHyri6SrAS> + +allegro_icon ICON DISCARDABLE "o2em.ico" diff --git a/src/O2EM.RES b/src/O2EM.RES new file mode 100755 index 0000000000000000000000000000000000000000..6c5d4e16f1c50a4171f60f2c70f467ed599b6d84 GIT binary patch literal 5982 zcmeI0F-{yo5JhX)l@=t+0YW$>a6sh9fddC?EQBo~K)wJ02{Asv_Cb6EAHjhG2R;ag zARAZB_#vjef44_+#xzX7t>6FmvC$G7f@ zvE$Fu?5D$;->*-Cq0W3hGAl2gS5C*1^`_hZ-5PywZuTwAKG-kLQvCZ?_`m!53;ST_ z{&i|+_Qfvk+CJMy=Y_BR@aNdi&A9i^2Ncd@f0q6fe;V8M*~fm5Jh#8HGSyQDrVc#E z4m4ZFww`Q>_kV&nY%=9HcVI*7x~0wOzyA!^Y(j3$(m+x^r4PbhD4)`&{ICP6Pf8!A z|LuRyQ7f`vURQdpZ_4)_$oXXuI^Vv7m&!YqR_a@hLA?wso`IJr$DxcEHLFH3A zIjDR}CkK^J>ExjDDV-ctKBbe(#IKnBxmG#!?9Vkm#q7_u%Asd}uJI{mf38&yJ^OQw zPci#*t#atuPo3APq4Fu698^A~lY`2qbaGJnluiyRpVG-eSt3_fZJ!;@(%nq@w2FOv z8q0|NhvDascgOihvc%iR_pObX_qznU{*8QZf6ijQQ5*g9Bg7AHEW217Cho15%eK2E ajvM9X@veGdaSI(|F}O32OPra_ef|TLo!mYE literal 0 HcmV?d00001 diff --git a/src/O2EM116_private.h b/src/O2EM116_private.h new file mode 100755 index 0000000..9bdaf83 --- /dev/null +++ b/src/O2EM116_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef O2EM116_PRIVATE_H +#define O2EM116_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*O2EM116_PRIVATE_H*/ diff --git a/src/O2EM116_private.rc b/src/O2EM116_private.rc new file mode 100755 index 0000000..c87d7f0 --- /dev/null +++ b/src/O2EM116_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "o2em.rc" + diff --git a/src/O2em118.dev b/src/O2em118.dev new file mode 100755 index 0000000..c2a7d33 --- /dev/null +++ b/src/O2em118.dev @@ -0,0 +1,378 @@ +[Project] +FileName=O2em118.dev +Name=O2EM118 +UnitCount=33 +Type=1 +Ver=1 +ObjFiles= +Includes=C:\Dev-Cpp\include +Libs=C:\Dev-Cpp\lib +PrivateResource=O2EM116_private.rc +ResourceIncludes=C:\Dev-Cpp\Projetos\Res +MakeIncludes= +Compiler= +CppCompiler= +Linker=../../lib/liballeg.a_@@_ +IsCpp=1 +Icon= +ExeOutput=..\Exe +ObjectOutput=..\OBJ +OverrideOutput=1 +OverrideOutputName=O2EM.exe +HostApplication= +Folders=Resource +CommandLine= +UseCustomMakefile=1 +CustomMakefile=Makefile.djgpp +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=vpp_cset.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=audio.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=cpu.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=crc32.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=cset.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=debug.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=dis48.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=keyboard.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=main.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=table.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=timefunc.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=vdc.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=vmachine.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=voice.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=vpp.c +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=vpp_cset.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=audio.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=config.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=cpu.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=crc32.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=cset.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=debug.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=keyboard.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=table.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=timefunc.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=types.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=vdc.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=vmachine.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=voice.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=vpp.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=o2em.rc +Folder=Resource +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit32] +FileName=..\..\..\..\O2EM-WIN\SCORE.C +CompileCpp=1 +Folder=O2EM118 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\..\..\..\O2EM-WIN\SCORE.H +CompileCpp=1 +Folder=O2EM118 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/src/O2em118.layout b/src/O2em118.layout new file mode 100755 index 0000000..897ad19 --- /dev/null +++ b/src/O2em118.layout @@ -0,0 +1,267 @@ +[Editor_8] +CursorCol=20 +CursorRow=310 +TopLine=301 +LeftChar=1 +Open=1 +Top=0 + +[Editors] +Order=8,1,16,2,-1 +Focused=-1 + +[Editor_0] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=266 +LeftChar=1 + +[Editor_1] +Open=1 +Top=0 +CursorCol=19 +CursorRow=18 +TopLine=1 +LeftChar=1 + +[Editor_2] +Open=1 +Top=0 +CursorCol=1 +CursorRow=1568 +TopLine=28 +LeftChar=1 + +[Editor_3] +Open=0 +Top=0 +CursorCol=1 +CursorRow=79 +TopLine=94 +LeftChar=1 + +[Editor_4] +Open=0 +Top=0 +CursorCol=8 +CursorRow=82 +TopLine=67 +LeftChar=1 + +[Editor_5] +Open=0 +Top=0 +CursorCol=5 +CursorRow=814 +TopLine=1026 +LeftChar=1 + +[Editor_6] +Open=0 +Top=0 +CursorCol=2 +CursorRow=134 +TopLine=132 +LeftChar=1 + +[Editor_7] +Open=0 +Top=0 +CursorCol=21 +CursorRow=255 +TopLine=238 +LeftChar=1 + +[Editor_9] +Open=0 +Top=0 +CursorCol=27 +CursorRow=59 +TopLine=322 +LeftChar=1 + +[Editor_10] +Open=0 +Top=0 +CursorCol=3 +CursorRow=11 +TopLine=1 +LeftChar=1 + +[Editor_11] +Open=0 +Top=0 +CursorCol=33 +CursorRow=601 +TopLine=583 +LeftChar=1 + +[Editor_12] +Open=0 +Top=0 +CursorCol=21 +CursorRow=79 +TopLine=67 +LeftChar=1 + +[Editor_13] +Open=0 +Top=0 +CursorCol=2 +CursorRow=41 +TopLine=137 +LeftChar=1 + +[Editor_14] +Open=0 +Top=0 +CursorCol=9 +CursorRow=38 +TopLine=481 +LeftChar=1 + +[Editor_15] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_16] +Open=1 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_17] +Open=0 +Top=0 +CursorCol=27 +CursorRow=5 +TopLine=1 +LeftChar=1 + +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=62 +TopLine=1 +LeftChar=1 + +[Editor_19] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_20] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_21] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_22] +Open=0 +Top=0 +CursorCol=15 +CursorRow=22 +TopLine=11 +LeftChar=1 + +[Editor_23] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_24] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_25] +Open=0 +Top=0 +CursorCol=18 +CursorRow=6 +TopLine=1 +LeftChar=1 + +[Editor_26] +Open=0 +Top=0 +CursorCol=1 +CursorRow=31 +TopLine=26 +LeftChar=1 + +[Editor_27] +Open=0 +Top=0 +CursorCol=1 +CursorRow=3 +TopLine=1 +LeftChar=1 + +[Editor_28] +Open=0 +Top=0 +CursorCol=30 +CursorRow=6 +TopLine=1 +LeftChar=1 + +[Editor_29] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 + +[Editor_30] +Open=0 +Top=0 +CursorCol=1 +CursorRow=4 +TopLine=1 +LeftChar=1 + +[Editor_31] +Open=1 +Top=1 +CursorCol=1 +CursorRow=123 +TopLine=114 +LeftChar=1 + +[Editor_32] +Open=1 +Top=0 +CursorCol=9 +CursorRow=4 +TopLine=1 +LeftChar=1 diff --git a/src/audio.c b/src/audio.c new file mode 100755 index 0000000..433d5d0 --- /dev/null +++ b/src/audio.c @@ -0,0 +1,219 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 audio emulation + */ + + +#include +#include +#include +#include +#include "cpu.h" +#include "types.h" +#include "config.h" +#include "vmachine.h" +#include "audio.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +extern int SND; +extern uint8_t soundBuffer[1056]; +#endif + +#define SAMPLE_RATE 44100 +#define PERIOD1 11 +#define PERIOD2 44 + +#define SOUND_BUFFER_LEN 1056 + +#define AUD_CTRL 0xAA +#define AUD_D0 0xA7 +#define AUD_D1 0xA8 +#define AUD_D2 0xA9 + + +int sound_IRQ; +#ifndef __LIBRETRO__ +static AUDIOSTREAM *stream=NULL; +#endif +FILE *sndlog=NULL; + +static double flt_a=0.0, flt_b=0.0; +static unsigned char flt_prv = 0; + + +static void filter(unsigned char *buf, unsigned long len); + + +void audio_process(unsigned char *buffer){ + unsigned long aud_data; + int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos; + + aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16)); + + intena = VDCwrite[0xA0] & 0x04; + + pnt = cnt = 0; + + noise = VDCwrite[AUD_CTRL] & 0x10; + enabled = VDCwrite[AUD_CTRL] & 0x80; + rndbit = (enabled && noise) ? (rand()%2) : 0; + + while (pnt < SOUND_BUFFER_LEN) { + pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1); + volume = AudioVector[pos] & 0x0F; + enabled = AudioVector[pos] & 0x80; + period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2; + re_circ = AudioVector[pos] & 0x40; + + buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0; + cnt++; + + if (cnt >= period) { + cnt=0; + aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1); + rndbit = (enabled && noise) ? (rand()%2) : 0; + + if (enabled && intena && (!sound_IRQ)) { + sound_IRQ = 1; + ext_IRQ(); + } + } + } + + if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN); +} + + + +void update_audio(void) { +#ifndef __LIBRETRO__ + unsigned char *p; + if (app_data.sound_en) { + p = (unsigned char *)get_audio_stream_buffer(stream); + if (p) { + audio_process(p); + if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog); + free_audio_stream_buffer(stream); + } + } +#else + //unsigned char *p; + //p = (unsigned char *)SNDBUF; + //if (p) { + // audio_process(p); + audio_process(soundBuffer); + //} +#endif +} + + +void init_audio(void) { + int i; + + sound_IRQ=0; + if ((app_data.sound_en) || (app_data.voice)) { + printf("Initializing sound system...\n"); +#ifndef __LIBRETRO__ + i = install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); + if (i != 0) { + printf(" ERROR: could not initialize sound card\n %s\n",allegro_error); + printf(" Sound system disabled\n"); + app_data.sound_en = 0; + app_data.voice = 0; + } + else { + if (digi_driver->name && (strlen(digi_driver->name)>0)){ + printf(" Sound system initialized ok\n"); + printf(" Sound driver [%s] detected\n",digi_driver->name); + set_volume(-1,-1); + init_sound_stream(); + } else { + printf(" ERROR: could not initialize sound card\n"); + printf(" Sound system disabled\n"); + app_data.sound_en = 0; + app_data.voice = 0; + } + } +#else + init_sound_stream(); +#endif + } + + sndlog = NULL; +} + + +void init_sound_stream(void){ + int vol; + if (app_data.sound_en){ + if (app_data.filter) + vol = (255*app_data.svolume)/100; + else + vol = (255*app_data.svolume)/200; +#ifndef __LIBRETRO__ + stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128); + if (!stream) { + printf("Error creating audio stream!\n"); + app_data.sound_en=0; + } +#endif + flt_a = flt_b = 0.0; + flt_prv = 0; + } +} + + +void mute_audio(void){ +#ifndef __LIBRETRO__ + if (app_data.sound_en && stream){ + stop_audio_stream(stream); + stream=NULL; + } +#else + SND=0; +#endif +} + + +void close_audio(void) { +#ifndef __LIBRETRO__ + if (app_data.sound_en && stream) { + stop_audio_stream(stream); + } +#endif + if (sndlog) fclose(sndlog); + app_data.sound_en=0; +} + + +static void filter(unsigned char *buffer, unsigned long len){ + static unsigned char buf[SOUND_BUFFER_LEN]; + int t; + unsigned long i; + if (len>SOUND_BUFFER_LEN) return; + memcpy(buf,buffer,len); + for (i=0; i255.0)||(flt_a<-255.0)) flt_a=0.0; + buffer[i] = (unsigned char)((flt_a+255.0)/2.0); + } + flt_prv = buf[len-1]; +} + + diff --git a/src/audio.h b/src/audio.h new file mode 100755 index 0000000..1ce60a6 --- /dev/null +++ b/src/audio.h @@ -0,0 +1,17 @@ +#ifndef __AUDIO_H +#define __AUDIO_H + +void update_audio(void); +void init_audio(void); +void close_audio(void); +void init_sound_stream(void); +void mute_audio(void); + + +extern int sound_IRQ; +extern FILE *sndlog; + + +#endif + + diff --git a/src/config.h b/src/config.h new file mode 100755 index 0000000..eec37a7 --- /dev/null +++ b/src/config.h @@ -0,0 +1,14 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define O2EM_VERSION "1.18" +#define RELEASE_DATE "(Jan/2007)" + +#define ROM_O2 1 +#define ROM_G7400 2 +#define ROM_C52 3 +#define ROM_JOPAC 4 +#define ROM_UNKNOWN 99 + +#endif + diff --git a/src/cpu.c b/src/cpu.c new file mode 100755 index 0000000..235956e --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,1586 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + ** Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * 8048 microcontroller emulation + */ + + +#include +#include "types.h" +#include "vmachine.h" +#include "keyboard.h" +#include "voice.h" +#include "vdc.h" +#include "vpp.h" +#include "cpu.h" + +#define push(d) {intRAM[sp++] = (d); if (sp > 23) sp = 8;} +#define pull() (sp--, (sp < 8)?(sp=23):0, intRAM[sp]) +#define make_psw() {psw = (cy << 7) | ac | f0 | bs | 0x08; psw = psw | ((sp - 8) >> 1);} +#define illegal(o) {} +#define undef(i) {printf("** unimplemented instruction %x, %x**\n",i,pc);} +#define ROM(adr) (rom[(adr) & 0xfff]) + + +void init_cpu(void){ + pc=0; + sp=8; + bs=0; + p1=p2=0xFF; + ac=cy=f0=0; + A11=A11ff=0; + timer_on=0; + count_on=0; + reg_pnt=0; + tirq_en=xirq_en=irq_ex=xirq_pend=tirq_pend=0; +} + + +void ext_IRQ(void){ + int_clk = 5; /* length of pulse on /INT */ + if (xirq_en && !irq_ex) { + irq_ex=1; + xirq_pend=0; + clk+=2; + make_psw(); + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = 0x03; + A11ff=A11; + A11=0; + } + if (pendirq && (!xirq_en)) xirq_pend=1; +} + + +void tim_IRQ(void){ + if (tirq_en && !irq_ex) { + irq_ex=2; + tirq_pend=0; + clk+=2; + make_psw(); + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = 0x07; + A11ff=A11; + A11=0; + } + if (pendirq && (!tirq_en)) tirq_pend=1; +} + + +void make_psw_debug(void){ + make_psw(); +} + +#ifdef __LIBRETRO__ +extern int RLOOP; +#endif + +void cpu_exec(void) { + Byte op; + ADDRESS adr; + Byte dat; + int temp; + + #ifndef __LIBRETRO__ + for (;;) + #else + while(RLOOP==1) + #endif + { + + clk=0; + + lastpc=pc; + op=ROM(pc++); + + switch (op) { + case 0x00: /* NOP */ + clk++; + break; + case 0x01: /* ILL */ + illegal(op); + clk++; + break; + case 0x02: /* OUTL BUS,A */ + clk+=2; + undef(0x02); + break; + case 0x03: /* ADD A,#data */ + clk+=2; + cy=ac=0; + dat=ROM(pc++); + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x04: /* JMP */ + pc=ROM(pc) | A11; + clk+=2; + break; + case 0x05: /* EN I */ + xirq_en=1; + clk++; + break; + case 0x06: /* ILL */ + clk++; + illegal(op); + break; + case 0x07: /* DEC A */ + acc--; + clk++; + break; + case 0x08: /* INS A,BUS*/ + clk+=2; + acc=in_bus(); + break; + case 0x09: /* IN A,Pp */ + acc=p1; + clk+=2; + break; + case 0x0A: /* IN A,Pp */ + acc=read_P2(); + clk+=2; + break; + case 0x0B: /* ILL */ + clk++; + illegal(op); + break; + case 0x0C: /* MOVD A,P4 */ + clk+=2; + acc=read_PB(0); + break; + case 0x0D: /* MOVD A,P5 */ + clk+=2; + acc=read_PB(1); + break; + case 0x0E: /* MOVD A,P6 */ + clk+=2; + acc=read_PB(2); + break; + case 0x0F: /* MOVD A,P7 */ + clk+=2; + acc=read_PB(3); + break; + case 0x10: /* INC @Ri */ + intRAM[intRAM[reg_pnt] & 0x3F]++; + clk++; + break; + case 0x11: /* INC @Ri */ + intRAM[intRAM[reg_pnt+1] & 0x3F]++; + clk++; + break; + case 0x12: /* JBb address */ + clk+=2; + dat = ROM(pc); + if (acc & 0x01) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x13: /* ADDC A,#data */ + clk+=2; + dat=ROM(pc++); + ac=0; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x14: /* CALL */ + make_psw(); + adr = ROM(pc) | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x15: /* DIS I */ + xirq_en=0; + clk++; + break; + case 0x16: /* JTF */ + clk+=2; + dat = ROM(pc); + if (t_flag) + pc=(pc & 0xF00) | dat; + else + pc++; + t_flag=0; + break; + case 0x17: /* INC A */ + acc++; + clk++; + break; + case 0x18: /* INC Rr */ + intRAM[reg_pnt]++; + clk++; + break; + case 0x19: /* INC Rr */ + intRAM[reg_pnt+1]++; + clk++; + break; + case 0x1A: /* INC Rr */ + intRAM[reg_pnt+2]++; + clk++; + break; + case 0x1B: /* INC Rr */ + intRAM[reg_pnt+3]++; + clk++; + break; + case 0x1C: /* INC Rr */ + intRAM[reg_pnt+4]++; + clk++; + break; + case 0x1D: /* INC Rr */ + intRAM[reg_pnt+5]++; + clk++; + break; + case 0x1E: /* INC Rr */ + intRAM[reg_pnt+6]++; + clk++; + break; + case 0x1F: /* INC Rr */ + intRAM[reg_pnt+7]++; + clk++; + break; + case 0x20: /* XCH A,@Ri */ + clk++; + dat=acc; + acc=intRAM[intRAM[reg_pnt] & 0x3F]; + intRAM[intRAM[reg_pnt] & 0x3F] = dat; + break; + case 0x21: /* XCH A,@Ri */ + clk++; + dat=acc; + acc=intRAM[intRAM[reg_pnt+1] & 0x3F]; + intRAM[intRAM[reg_pnt+1] & 0x3F] = dat; + break; + case 0x22: /* ILL */ + clk++; + illegal(op); + break; + case 0x23: /* MOV a,#data */ + clk+=2; + acc = ROM(pc++); + break; + + case 0x24: /* JMP */ + pc=ROM(pc) | 0x100 | A11; + clk+=2; + break; + case 0x25: /* EN TCNTI */ + tirq_en=1; + clk++; + break; + case 0x26: /* JNT0 */ + clk+=2; + dat = ROM(pc); + if (!get_voice_status()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x27: /* CLR A */ + clk++; + acc=0; + break; + case 0x28: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt]; + intRAM[reg_pnt]=dat; + clk++; + break; + case 0x29: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+1]; + intRAM[reg_pnt+1]=dat; + clk++; + break; + case 0x2A: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+2]; + intRAM[reg_pnt+2]=dat; + clk++; + break; + case 0x2B: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+3]; + intRAM[reg_pnt+3]=dat; + clk++; + break; + case 0x2C: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+4]; + intRAM[reg_pnt+4]=dat; + clk++; + break; + case 0x2D: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+5]; + intRAM[reg_pnt+5]=dat; + clk++; + break; + case 0x2E: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+6]; + intRAM[reg_pnt+6]=dat; + clk++; + break; + case 0x2F: /* XCH A,Rr */ + dat=acc; + acc=intRAM[reg_pnt+7]; + intRAM[reg_pnt+7]=dat; + clk++; + break; + case 0x30: /* XCHD A,@Ri */ + clk++; + adr=intRAM[reg_pnt] & 0x3F; + dat=acc & 0x0F; + acc=acc & 0xF0; + acc=acc | (intRAM[adr] & 0x0F); + intRAM[adr] &= 0xF0; + intRAM[adr] |= dat; + break; + case 0x31: /* XCHD A,@Ri */ + clk++; + adr=intRAM[reg_pnt+1] & 0x3F; + dat=acc & 0x0F; + acc=acc & 0xF0; + acc=acc | (intRAM[adr] & 0x0F); + intRAM[adr] &= 0xF0; + intRAM[adr] |= dat; + break; + case 0x32: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x02) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x33: /* ILL */ + clk++; + illegal(op); + break; + case 0x34: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x100 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x35: /* DIS TCNTI */ + tirq_en=0; + tirq_pend=0; + clk++; + break; + case 0x36: /* JT0 */ + clk+=2; + dat=ROM(pc); + if (get_voice_status()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x37: /* CPL A */ + acc = acc ^ 0xFF; + clk++; + break; + case 0x38: /* ILL */ + clk++; + illegal(op); + break; + case 0x39: /* OUTL P1,A */ + clk+=2; + write_p1(acc); + break; + case 0x3A: /* OUTL P2,A */ + clk+=2; + p2=acc; + break; + case 0x3B: /* ILL */ + clk++; + illegal(op); + break; + case 0x3C: /* MOVD P4,A */ + clk+=2; + write_PB(0,acc); + break; + case 0x3D: /* MOVD P5,A */ + clk+=2; + write_PB(1,acc); + break; + case 0x3E: /* MOVD P6,A */ + clk+=2; + write_PB(2,acc); + break; + case 0x3F: /* MOVD P7,A */ + clk+=2; + write_PB(3,acc); + break; + case 0x40: /* ORL A,@Ri */ + clk++; + acc = acc | intRAM[intRAM[reg_pnt] & 0x3F]; + break; + case 0x41: /* ORL A,@Ri */ + clk++; + acc = acc | intRAM[intRAM[reg_pnt+1] & 0x3F]; + break; + case 0x42: /* MOV A,T */ + clk++; + acc = itimer; + break; + case 0x43: /* ORL A,#data */ + clk+=2; + acc = acc | ROM(pc++); + break; + case 0x44: /* JMP */ + pc=ROM(pc) | 0x200 | A11; + clk+=2; + break; + case 0x45: /* STRT CNT */ + /* printf("START: %d=%d\n",master_clk/22,itimer); */ + count_on=1; + clk++; + break; + case 0x46: /* JNT1 */ + clk+=2; + dat = ROM(pc); + if (!read_t1()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x47: /* SWAP A */ + clk++; + dat=(acc & 0xF0) >> 4; + acc = acc << 4; + acc = acc | dat; + break; + case 0x48: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt]; + break; + case 0x49: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+1]; + break; + case 0x4A: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+2]; + break; + case 0x4B: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+3]; + break; + case 0x4C: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+4]; + break; + case 0x4D: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+5]; + break; + case 0x4E: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+6]; + break; + case 0x4F: /* ORL A,Rr */ + clk++; + acc = acc | intRAM[reg_pnt+7]; + break; + + case 0x50: /* ANL A,@Ri */ + acc = acc & intRAM[intRAM[reg_pnt] & 0x3F]; + clk++; + break; + case 0x51: /* ANL A,@Ri */ + acc = acc & intRAM[intRAM[reg_pnt+1] & 0x3F]; + clk++; + break; + case 0x52: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x04) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x53: /* ANL A,#data */ + clk+=2; + acc = acc & ROM(pc++); + break; + case 0x54: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x200 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x55: /* STRT T */ + timer_on=1; + clk++; + break; + case 0x56: /* JT1 */ + clk+=2; + dat = ROM(pc); + if (read_t1()) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x57: /* DA A */ + clk++; + if (((acc & 0x0F) > 0x09) || ac) { + if (acc>0xf9) cy=1; + acc += 6; + } + dat = (acc & 0xF0) >> 4; + if ((dat > 9) || cy) { + dat+=6; + cy=1; + } + acc = (acc & 0x0F) | (dat << 4); + break; + case 0x58: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt]; + break; + case 0x59: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+1]; + break; + case 0x5A: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+2]; + break; + case 0x5B: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+3]; + break; + case 0x5C: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+4]; + break; + case 0x5D: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+5]; + break; + case 0x5E: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+6]; + break; + case 0x5F: /* ANL A,Rr */ + clk++; + acc = acc & intRAM[reg_pnt+7]; + break; + + case 0x60: /* ADD A,@Ri */ + clk++; + cy=ac=0; + dat=intRAM[intRAM[reg_pnt] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x61: /* ADD A,@Ri */ + clk++; + cy=ac=0; + dat=intRAM[intRAM[reg_pnt+1] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x62: /* MOV T,A */ + clk++; + itimer=acc; + break; + case 0x63: /* ILL */ + clk++; + illegal(op); + break; + case 0x64: /* JMP */ + pc=ROM(pc) | 0x300 | A11; + clk+=2; + break; + case 0x65: /* STOP TCNT */ + clk++; + /* printf("STOP %d\n",master_clk/22); */ + count_on=timer_on=0; + break; + case 0x66: /* ILL */ + clk++; + illegal(op); + break; + case 0x67: /* RRC A */ + dat=cy; + cy=acc & 0x01; + acc = acc >> 1; + if (dat) + acc = acc | 0x80; + else + acc = acc & 0x7F; + clk++; + break; + case 0x68: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x69: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+1]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6A: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+2]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6B: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+3]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6C: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+4]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6D: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+5]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6E: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+6]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x6F: /* ADD A,Rr */ + clk++; + cy=ac=0; + dat=intRAM[reg_pnt+7]; + if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40; + temp=acc+dat; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x70: /* ADDC A,@Ri */ + clk++; + ac=0; + dat=intRAM[intRAM[reg_pnt] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x71: /* ADDC A,@Ri */ + clk++; + ac=0; + dat=intRAM[intRAM[reg_pnt+1] & 0x3F]; + if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x72: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x08) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x73: /* ILL */ + clk++; + illegal(op); + break; + case 0x74: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x300 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x75: /* EN CLK */ + clk++; + undef(op); + break; + case 0x76: /* JF1 address */ + clk+=2; + dat=ROM(pc); + if (f1) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x77: /* RR A */ + clk++; + dat=acc & 0x01; + acc = acc >> 1; + if (dat) + acc = acc | 0x80; + else + acc = acc & 0x7f; + break; + + case 0x78: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x79: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+1]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7A: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+2]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7B: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+3]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7C: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+4]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7D: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+5]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7E: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+6]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + case 0x7F: /* ADDC A,Rr */ + clk++; + ac=0; + dat=intRAM[reg_pnt+7]; + if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40; + temp=acc+dat+cy; + cy=0; + if (temp > 0xFF) cy=1; + acc=(temp & 0xFF); + break; + + case 0x80: /* MOVX A,@Ri */ + acc=ext_read(intRAM[reg_pnt]); + clk+=2; + break; + case 0x81: /* MOVX A,@Ri */ + acc=ext_read(intRAM[reg_pnt+1]); + clk+=2; + break; + case 0x82: /* ILL */ + clk++; + illegal(op); + break; + case 0x83: /* RET */ + clk+=2; + pc = ((pull() & 0x0F) << 8); + pc = pc | pull(); + break; + case 0x84: /* JMP */ + pc=ROM(pc) | 0x400 | A11; + clk+=2; + break; + case 0x85: /* CLR F0 */ + clk++; + f0=0; + break; + case 0x86: /* JNI address */ + clk+=2; + dat=ROM(pc); + if (int_clk > 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x87: /* ILL */ + illegal(op); + clk++; + break; + case 0x88: /* BUS,#data */ + clk+=2; + undef(op); + break; + case 0x89: /* ORL Pp,#data */ + write_p1(p1 | ROM(pc++)); + clk+=2; + break; + case 0x8A: /* ORL Pp,#data */ + p2 = p2 | ROM(pc++); + clk+=2; + break; + case 0x8B: /* ILL */ + illegal(op); + clk++; + break; + case 0x8C: /* ORLD P4,A */ + write_PB(0,read_PB(0)|acc); + clk+=2; + break; + case 0x8D: /* ORLD P5,A */ + write_PB(1,read_PB(1)|acc); + clk+=2; + break; + case 0x8E: /* ORLD P6,A */ + write_PB(2,read_PB(2)|acc); + clk+=2; + break; + case 0x8F: /* ORLD P7,A */ + write_PB(3,read_PB(3)|acc); + clk+=2; + break; + case 0x90: /* MOVX @Ri,A */ + ext_write(acc,intRAM[reg_pnt]); + clk+=2; + break; + case 0x91: /* MOVX @Ri,A */ + ext_write(acc,intRAM[reg_pnt+1]); + clk+=2; + break; + case 0x92: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x10) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x93: /* RETR*/ + /* printf("RETR %d\n",master_clk/22); */ + clk+=2; + dat=pull(); + pc = (dat & 0x0F) << 8; + cy = (dat & 0x80) >> 7; + ac = dat & 0x40; + f0 = dat & 0x20; + bs = dat & 0x10; + if (bs) + reg_pnt=24; + else + reg_pnt=0; + pc = pc | pull(); + irq_ex=0; + A11=A11ff; + break; + case 0x94: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x400 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0x95: /* CPL F0 */ + f0 = f0 ^ 0x20; + clk++; + break; + case 0x96: /* JNZ address */ + clk+=2; + dat=ROM(pc); + if (acc != 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0x97: /* CLR C */ + cy=0; + clk++; + break; + case 0x98: /* ANL BUS,#data */ + clk+=2; + undef(op); + break; + case 0x99: /* ANL Pp,#data */ + write_p1(p1 & ROM(pc++)); + clk+=2; + break; + case 0x9A: /* ANL Pp,#data */ + p2 = p2 & ROM(pc++); + clk+=2; + break; + case 0x9B: /* ILL */ + illegal(op); + clk++; + break; + case 0x9C: /* ANLD P4,A */ + write_PB(0,read_PB(0)&acc); + clk+=2; + break; + case 0x9D: /* ANLD P5,A */ + write_PB(1,read_PB(1)&acc); + clk+=2; + break; + case 0x9E: /* ANLD P6,A */ + write_PB(2,read_PB(2)&acc); + clk+=2; + break; + case 0x9F: /* ANLD P7,A */ + write_PB(3,read_PB(3)&acc); + clk+=2; + break; + case 0xA0: /* MOV @Ri,A */ + intRAM[intRAM[reg_pnt] & 0x3F]=acc; + clk++; + break; + case 0xA1: /* MOV @Ri,A */ + intRAM[intRAM[reg_pnt+1] & 0x3F]=acc; + clk++; + break; + case 0xA2: /* ILL */ + clk++; + illegal(op); + break; + case 0xA3: /* MOVP A,@A */ + acc=ROM((pc & 0xF00) | acc); + clk+=2; + break; + case 0xA4: /* JMP */ + pc=ROM(pc) | 0x500 | A11; + clk+=2; + break; + case 0xA5: /* CLR F1 */ + clk++; + f1=0; + break; + case 0xA6: /* ILL */ + illegal(op); + clk++; + break; + case 0xA7: /* CPL C */ + cy = cy ^ 0x01; + clk++; + break; + case 0xA8: /* MOV Rr,A */ + intRAM[reg_pnt] = acc; + clk++; + break; + case 0xA9: /* MOV Rr,A */ + intRAM[reg_pnt+1] = acc; + clk++; + break; + case 0xAA: /* MOV Rr,A */ + intRAM[reg_pnt+2] = acc; + clk++; + break; + case 0xAB: /* MOV Rr,A */ + intRAM[reg_pnt+3] = acc; + clk++; + break; + case 0xAC: /* MOV Rr,A */ + intRAM[reg_pnt+4] = acc; + clk++; + break; + case 0xAD: /* MOV Rr,A */ + intRAM[reg_pnt+5] = acc; + clk++; + break; + case 0xAE: /* MOV Rr,A */ + intRAM[reg_pnt+6] = acc; + clk++; + break; + case 0xAF: /* MOV Rr,A */ + intRAM[reg_pnt+7] = acc; + clk++; + break; + case 0xB0: /* MOV @Ri,#data */ + intRAM[intRAM[reg_pnt] & 0x3F]=ROM(pc++); + clk+=2; + break; + case 0xB1: /* MOV @Ri,#data */ + intRAM[intRAM[reg_pnt+1] & 0x3F]=ROM(pc++); + clk+=2; + break; + case 0xB2: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x20) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xB3: /* JMPP @A */ + adr = (pc & 0xF00) | acc; + pc=(pc & 0xF00) | ROM(adr); + clk+=2; + break; + case 0xB4: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x500 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xB5: /* CPL F1 */ + f1 = f1 ^ 0x01; + clk++; + break; + case 0xB6: /* JF0 address */ + clk+=2; + dat=ROM(pc); + if (f0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xB7: /* ILL */ + clk++; + illegal(op); + break; + case 0xB8: /* MOV Rr,#data */ + intRAM[reg_pnt]=ROM(pc++); + clk+=2; + break; + case 0xB9: /* MOV Rr,#data */ + intRAM[reg_pnt+1]=ROM(pc++); + clk+=2; + break; + case 0xBA: /* MOV Rr,#data */ + intRAM[reg_pnt+2]=ROM(pc++); + clk+=2; + break; + case 0xBB: /* MOV Rr,#data */ + intRAM[reg_pnt+3]=ROM(pc++); + clk+=2; + break; + case 0xBC: /* MOV Rr,#data */ + intRAM[reg_pnt+4]=ROM(pc++); + clk+=2; + break; + case 0xBD: /* MOV Rr,#data */ + intRAM[reg_pnt+5]=ROM(pc++); + clk+=2; + break; + case 0xBE: /* MOV Rr,#data */ + intRAM[reg_pnt+6]=ROM(pc++); + clk+=2; + break; + case 0xBF: /* MOV Rr,#data */ + intRAM[reg_pnt+7]=ROM(pc++); + clk+=2; + break; + case 0xC0: /* ILL */ + illegal(op); + clk++; + break; + case 0xC1: /* ILL */ + illegal(op); + clk++; + break; + case 0xC2: /* ILL */ + illegal(op); + clk++; + break; + case 0xC3: /* ILL */ + illegal(op); + clk++; + break; + case 0xC4: /* JMP */ + pc=ROM(pc) | 0x600 | A11; + clk+=2; + break; + case 0xC5: /* SEL RB0 */ + bs=reg_pnt=0; + clk++; + break; + case 0xC6: /* JZ address */ + clk+=2; + dat=ROM(pc); + if (acc == 0) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xC7: /* MOV A,PSW */ + clk++; + make_psw(); + acc=psw; + break; + case 0xC8: /* DEC Rr */ + intRAM[reg_pnt]--; + clk++; + break; + case 0xC9: /* DEC Rr */ + intRAM[reg_pnt+1]--; + clk++; + break; + case 0xCA: /* DEC Rr */ + intRAM[reg_pnt+2]--; + clk++; + break; + case 0xCB: /* DEC Rr */ + intRAM[reg_pnt+3]--; + clk++; + break; + case 0xCC: /* DEC Rr */ + intRAM[reg_pnt+4]--; + clk++; + break; + case 0xCD: /* DEC Rr */ + intRAM[reg_pnt+5]--; + clk++; + break; + case 0xCE: /* DEC Rr */ + intRAM[reg_pnt+6]--; + clk++; + break; + case 0xCF: /* DEC Rr */ + intRAM[reg_pnt+7]--; + clk++; + break; + case 0xD0: /* XRL A,@Ri */ + acc = acc ^ intRAM[intRAM[reg_pnt] & 0x3F]; + clk++; + break; + case 0xD1: /* XRL A,@Ri */ + acc = acc ^ intRAM[intRAM[reg_pnt+1] & 0x3F]; + clk++; + break; + case 0xD2: /* JBb address */ + clk+=2; + dat = ROM(pc); + if (acc & 0x40) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xD3: /* XRL A,#data */ + clk+=2; + acc = acc ^ ROM(pc++); + break; + case 0xD4: /* CALL */ + make_psw(); + adr = ROM(pc) | 0x600 | A11; + pc++; + clk+=2; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xD5: /* SEL RB1 */ + bs=0x10; + reg_pnt=24; + clk++; + break; + case 0xD6: /* ILL */ + illegal(op); + clk++; + break; + case 0xD7: /* MOV PSW,A */ + psw=acc; + clk++; + cy = (psw & 0x80) >> 7; + ac = psw & 0x40; + f0 = psw & 0x20; + bs = psw & 0x10; + if (bs) + reg_pnt = 24; + else + reg_pnt = 0; + sp = (psw & 0x07) << 1; + sp+=8; + break; + case 0xD8: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt]; + clk++; + break; + case 0xD9: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+1]; + clk++; + break; + case 0xDA: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+2]; + clk++; + break; + case 0xDB: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+3]; + clk++; + break; + case 0xDC: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+4]; + clk++; + break; + case 0xDD: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+5]; + clk++; + break; + case 0xDE: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+6]; + clk++; + break; + case 0xDF: /* XRL A,Rr */ + acc = acc ^ intRAM[reg_pnt+7]; + clk++; + break; + case 0xE0: /* ILL */ + clk++; + illegal(op); + break; + case 0xE1: /* ILL */ + clk++; + illegal(op); + break; + case 0xE2: /* ILL */ + clk++; + illegal(op); + break; + case 0xE3: /* MOVP3 A,@A */ + + adr = 0x300 | acc; + acc=ROM(adr); + clk+=2; + break; + case 0xE4: /* JMP */ + pc=ROM(pc) | 0x700 | A11; + clk+=2; + break; + case 0xE5: /* SEL MB0 */ + A11=0; + A11ff = 0; + clk++; + break; + case 0xE6: /* JNC address */ + clk+=2; + dat=ROM(pc); + if (!cy) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xE7: /* RL A */ + clk++; + dat=acc & 0x80; + acc = acc << 1; + if (dat) + acc = acc | 0x01; + else + acc = acc & 0xFE; + break; + case 0xE8: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt]--; + dat=ROM(pc); + if (intRAM[reg_pnt] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xE9: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+1]--; + dat=ROM(pc); + if (intRAM[reg_pnt+1] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEA: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+2]--; + dat=ROM(pc); + if (intRAM[reg_pnt+2] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEB: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+3]--; + dat=ROM(pc); + if (intRAM[reg_pnt+3] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEC: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+4]--; + dat=ROM(pc); + if (intRAM[reg_pnt+4] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xED: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+5]--; + dat=ROM(pc); + if (intRAM[reg_pnt+5] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEE: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+6]--; + dat=ROM(pc); + if (intRAM[reg_pnt+6] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xEF: /* DJNZ Rr,address */ + clk+=2; + intRAM[reg_pnt+7]--; + dat=ROM(pc); + if (intRAM[reg_pnt+7] != 0) { + pc = pc & 0xF00; + pc = pc | dat; + } else pc++; + break; + case 0xF0: /* MOV A,@Ri */ + clk++; + acc=intRAM[intRAM[reg_pnt] & 0x3F]; + break; + case 0xF1: /* MOV A,@Ri */ + clk++; + acc=intRAM[intRAM[reg_pnt + 1] & 0x3F]; + break; + case 0xF2: /* JBb address */ + clk+=2; + dat=ROM(pc); + if (acc & 0x80) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xF3: /* ILL */ + illegal(op); + clk++; + break; + case 0xF4: /* CALL */ + clk+=2; + make_psw(); + adr = ROM(pc) | 0x700 | A11; + pc++; + push(pc & 0xFF); + push(((pc & 0xF00) >> 8) | (psw & 0xF0)); + pc = adr; + break; + case 0xF5: /* SEL MB1 */ + if (irq_ex) { + A11ff = 0x800; + } + else + { + A11=0x800; + A11ff = 0x800; + } + clk++; + break; + case 0xF6: /* JC address */ + clk+=2; + dat=ROM(pc); + if (cy) + pc=(pc & 0xF00) | dat; + else + pc++; + break; + case 0xF7: /* RLC A */ + dat=cy; + cy=(acc & 0x80) >> 7; + acc = acc << 1; + if (dat) + acc = acc | 0x01; + else + acc = acc & 0xFE; + clk++; + break; + case 0xF8: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt]; + break; + case 0xF9: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 1]; + break; + case 0xFA: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 2]; + break; + case 0xFB: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 3]; + break; + case 0xFC: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 4]; + break; + case 0xFD: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 5]; + break; + case 0xFE: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 6]; + break; + case 0xFF: /* MOV A,Rr */ + clk++; + acc = intRAM[reg_pnt + 7]; + break; + } + + + master_clk+=clk; + h_clk+=clk; + clk_counter+=clk; + + /* flag for JNI */ + if (int_clk > clk) + int_clk -= clk; + else + int_clk = 0; + + /* pending IRQs */ + if (xirq_pend) ext_IRQ(); + if (tirq_pend) tim_IRQ(); + + if (h_clk > LINECNT-1) { + h_clk-=LINECNT; + if (enahirq && (VDCwrite[0xA0] & 0x01)) ext_IRQ(); + if (count_on && mstate == 0) { + itimer++; + if (itimer == 0) { + t_flag=1; + tim_IRQ(); + draw_region(); + } + } + } + + if (timer_on) { + master_count+=clk; + if (master_count > 31) { + master_count-=31; + itimer++; + if (itimer == 0) { + t_flag=1; + tim_IRQ(); + } + } + } + + if ((mstate==0) && (master_clk > VBLCLK)){ + handle_vbl(); + } + if ((mstate==1) && (master_clk > evblclk)) { + handle_evbl(); +#ifdef __LIBRETRO__ + RLOOP=0; +#endif + if (app_data.crc == 0xA7344D1F) handle_evbll(); /* Atlantis */ + break; + } + +#ifndef __LIBRETRO__ + if (app_data.debug) break; + + if (pc==app_data.breakpoint) break; +#endif + } + +} + diff --git a/src/cpu.h b/src/cpu.h new file mode 100755 index 0000000..ef0c5f0 --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,65 @@ +#ifndef CPU_H +#define CPU_H + +#include "types.h" + +extern Byte acc; /* Accumulator */ +extern ADDRESS pc; /* Program counter */ +extern long clk; /* clock */ + +extern Byte itimer; /* Internal timer */ +extern Byte reg_pnt; /* pointer to register bank */ +extern Byte timer_on; /* 0=timer off/1=timer on */ +extern Byte count_on; /* 0=count off/1=count on */ + +extern Byte t_flag; /* Timer flag */ + +extern Byte psw; /* Processor status word */ +extern Byte sp; /* Stack pointer (part of psw) */ + +extern Byte p1; /* I/O port 1 */ +extern Byte p2; /* I/O port 2 */ + +extern Byte xirq_pend; +extern Byte tirq_pend; + +void init_cpu(void); +void cpu_exec(void); +void ext_IRQ(void); +void tim_IRQ(void); +void make_psw_debug(void); + +Byte acc; /* Accumulator */ +ADDRESS pc; /* Program counter */ +long clk; /* clock */ + +Byte itimer; /* Internal timer */ +Byte reg_pnt; /* pointer to register bank */ +Byte timer_on; /* 0=timer off/1=timer on */ +Byte count_on; /* 0=count off/1=count on */ +Byte psw; /* Processor status word */ +Byte sp; /* Stack pointer (part of psw) */ + +Byte p1; /* I/O port 1 */ +Byte p2; /* I/O port 2 */ +Byte xirq_pend; /* external IRQ pending */ +Byte tirq_pend; /* timer IRQ pending */ +Byte t_flag; /* Timer flag */ + +ADDRESS lastpc; +ADDRESS A11; /* PC bit 11 */ +ADDRESS A11ff; +Byte bs; /* Register Bank (part of psw) */ +Byte f0; /* Flag Bit (part of psw) */ +Byte f1; /* Flag Bit 1 */ +Byte ac; /* Aux Carry (part of psw) */ +Byte cy; /* Carry flag (part of psw) */ +Byte xirq_en; /* external IRQ's enabled */ +Byte tirq_en; /* Timer IRQ enabled */ +Byte irq_ex; /* IRQ executing */ + +int master_count; + + +#endif /* CPU_H */ + diff --git a/src/crc32.c b/src/crc32.c new file mode 100755 index 0000000..0baebeb --- /dev/null +++ b/src/crc32.c @@ -0,0 +1,110 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * CRC32 functions used to identify files + */ + + +#include +#include +#include "crc32.h" + +static unsigned long crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +unsigned long crc32_buf(const void *buf, long len){ + unsigned /*long*/ crc = crc ^ 0xffffffffUL;//~0; + unsigned char *p = (unsigned char*)buf; + + while (len--) crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xff]; + return ~crc; +} + + +unsigned long crc32_file(const char *filename){ + unsigned /*long*/ crc = crc ^ 0xffffffffUL;//crc = ~0; + FILE *f; + int c; + f = fopen(filename,"rb"); + if (f){ + while ((c=fgetc(f)) != EOF) crc = (crc >> 8) ^ crc32tab[(crc ^ c) & 0xff]; + fclose(f); + + } + return ~crc; + } + diff --git a/src/crc32.h b/src/crc32.h new file mode 100755 index 0000000..e00c9a2 --- /dev/null +++ b/src/crc32.h @@ -0,0 +1,7 @@ +#ifndef __CRC32_H +#define __CRC32_H + +unsigned long crc32_buf(const void *buf, long len); +unsigned long crc32_file(const char *filename); + +#endif diff --git a/src/cset.c b/src/cset.c new file mode 100755 index 0000000..bab86cf --- /dev/null +++ b/src/cset.c @@ -0,0 +1,86 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 character table + */ + + +#include "types.h" +#include "cset.h" + + +Byte cset[512]= { +0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00, +0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00, +0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00, +0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00, +0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00, +0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00, +0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00, +0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00, +0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00, +0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00, +0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00, +0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00, +0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00, +0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, +0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00, +0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00, +0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00, +0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00, +0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, +0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, +0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00, +0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00, +0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00, +0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00, +0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00, +0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, +0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00, +0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00, +0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00, +0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00, +0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00, +0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00, +0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00, +0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00, +0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00, +0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00, +0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, +0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00, +0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00, +0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00, +0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00, +0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00, +0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, +0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00, +0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00, +0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00, +0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00, +0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00, +0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00, +0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00, +0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00, +0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00, +0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00, +0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00, +0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00, +0x00,0x00,0x0C,0x08,0x08,0xFF,0x7E,0x00, +0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00, +0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00, +0x00,0x00,0x00,0x06,0x6E,0xFF,0x7E,0x00}; + diff --git a/src/cset.h b/src/cset.h new file mode 100755 index 0000000..90ff411 --- /dev/null +++ b/src/cset.h @@ -0,0 +1,6 @@ +#ifndef __CSET_H +#define __CSET_H + +extern Byte cset[512]; + +#endif diff --git a/src/debug.c b/src/debug.c new file mode 100755 index 0000000..7d4cfd0 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,1056 @@ +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2EM built-in debugger + */ + + +#include +#include +#include "cpu.h" +#include "keyboard.h" +#include "vmachine.h" +#include "audio.h" +#include "vdc.h" +#include "table.h" +#include "debug.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "wrapalleg.h" +#include +#endif + +#include "vpp.h" +#include "score.h" + +#if defined(ALLEGRO_WINDOWS) +#include "winalleg.h" +#include +#define KBHIT _kbhit +#elif defined(ALLEGRO_DOS) +#include +#define KBHIT kbhit +#else +#define KBHIT() 0 +#endif + +static int assemble(char *opcode, int p); +static int disasm(ADDRESS p); +static int spriteprint(ADDRESS p); +static void show_reg(void); +int nMemDump; +int nDisAsm; +int nSprite; +void decimal2binary(int decimal_value, char binary_value[32], short digits); + + +void debug(void) { + int done,i,go,j; + char inp[80]; + char *tok; + ADDRESS ad,run_to; + char cr[2],ff[2]; + Byte d,a; + + dbstick1=dbstick2=0; + cr[0]=13; + cr[1]=0; + ff[0]=0x0c; + ff[1]=0; + + done=go=0; + +#ifndef __LIBRETRO__ + set_display_switch_mode(SWITCH_BACKGROUND); +#endif + if (sndlog) fclose(sndlog); + + #ifdef ALLEGRO_WINDOWS + FreeConsole(); + AllocConsole(); + #endif + + printf("\nDebug mode\n\n"); + + if (pc==app_data.breakpoint) + { + printf("Breakpoint reached at %x\n",pc); + } + + nMemDump=pc; + nDisAsm=pc; + nSprite=0; + show_reg(); + + while (!done) { + while (go > 0) { + disasm(pc); + cpu_exec(); + go--; + if (KBHIT()) { + go=0; + cpu_exec(); + show_reg(); + } + } + printf("> "); + fgets(inp,76,stdin); + if ((strlen(inp)>0) && (inp[strlen(inp)-1]=='\n')) inp[strlen(inp)-1]=0; + strlwr(inp); + strcat(inp," \n"); + tok=strtok(inp," "); + if (!tok) tok=""; + if (!strcmp(tok,"h") || !strcmp(tok,"?") || !strcmp(tok,"help")) { + printf("display - show display\n"); + printf("viewsprite # - show memory # as sprite\n"); +// printf("editsprite # - edit memory # as sprite\n"); + printf("showfps - display the number of frames per second\n"); + + #ifdef ALLEGRO_DOS + printf("cls - clear screen\n"); + #endif + + printf("clrkey - clear keypresses\n"); + printf("setkey n - set key n pressed\n"); + printf("stick1 # - set stick1 to #\n"); + printf("stick2 # - set stick2 to #\n"); + + printf("reg - display registers\n"); + printf("stack - display stack\n"); + printf("col - display collision table\n"); + printf("video (a d) - display VDC registers (or write data d to a)\n"); + printf("extram (a d) - display external RAM (or write data d to a)\n"); + printf("intram (a d) - display internal ram (or write data d to a)\n"); + + printf("s - step\n"); + printf("so - step over\n"); + printf("go # - execute # instructions\n"); + printf("run # - run to address #\n"); + printf("runvb - run to VBL\n"); + printf("runnvb - run to no VBL\n"); + printf("bp # - breakpoint at address #\n"); + printf("bpc - clear breakpoint\n"); + printf("reset - reset the machine\n"); + + printf("load file a - load file to memory to address\n"); + printf("save file a n - save memory to file from address n Bytes\n"); + printf("savedatah file a n - save memory to file from address a n Bytes format hex\n"); + printf("savedatab file a n - save memory to file from address a n Bytes format binary\n"); + printf("savevdc file a n - save VDC to file from address a n Bytes format hex\n"); + printf("saveext file a n - save ExtRam to file from address a n Bytes format hex\n"); + printf("savevpp file - save the VPP to file\n"); + + printf("as # - assemble memory #\n"); + printf("di # - disassemble memory #\n"); + printf("md # - display memory #\n"); + printf("c # - change memory from location #\n"); + + printf("sndlog [file] - log raw sound to file\n"); + printf("ss [file] - save state [to file]\n"); + printf("ls [file] - load state [from file]\n"); + + printf("q - quit debugger and return to emulation\n"); + printf("\n"); + } else if (!strcmp(tok,"display")) { + grmode(); + clip_low = 0; + clip_high = 85000; + draw_display(); + finish_display(); + init_keyboard(); + do { + rest(1); + } while((key_done==0) && (!keypressed())); + set_textmode(); +#ifndef __LIBRETRO__ + set_display_switch_mode(SWITCH_BACKGROUND); +#endif + } else if (!strcmp(tok,"viewsprite")) { + if (tok){ + tok=strtok(NULL," "); + ad=65535; + sscanf(tok,"%hx",&ad); + if (ad==65535) ad=nSprite; + + for(i=0; i<8; i++) + { + if (ad<32768) ad = ad + spriteprint(ad); else ad=0; + } + nSprite=ad; + printf("\n"); + } +//TODO !!!! ---------------------------------------------------------------------------------------------------- + } else if (!strcmp(tok,"editsprite")) { + if (tok){ + tok=strtok(NULL," "); + ad=65535; + sscanf(tok,"%hx",&ad); + if (ad!=65535) + { + for(i=0; i<8; i++) + { + if (ad<32768) ad = ad + spriteprint(ad); else ad=0; + } + printf("\n"); + } + } +//---------------------------------------------------------------------------------------------------- + } else if (!strcmp(tok,"cls")) { + #ifdef ALLEGRO_DOS + clrscr(); + #endif + } else if (!strcmp(tok,"clrkey")) { + for(i=0; i<128; i++) key2[i]=0; + } else if (!strcmp(tok,"setkey")) { + tok=strtok(NULL," "); + if (tok){ + sscanf(tok,"%d",&i); + if ((i>0) && (i<128)){ + printf("Key %d set to pressed\n",i); + key2[i]=1; + } + key2vcnt=0; + } + } else if (!strcmp(tok,"stick1")) { + tok=strtok(NULL," "); + if (tok) { + i=0; + sscanf(tok,"%x",&i); + printf("Stick 1 set to %d\n",i); + dbstick1=i; + key2vcnt=0; + } + } else if (!strcmp(tok,"stick2")) { + tok=strtok(NULL," "); + if (tok) { + i=0; + sscanf(tok,"%x",&i); + printf("Stick 2 set to %d\n",i); + dbstick2=i; + key2vcnt=0; + } + } else if (!strcmp(tok,"s")) { + cpu_exec(); + show_reg(); + } else if (!strcmp(tok,"so")) { + run_to = pc+lookup[rom[pc]].bytes; + printf("%hx\n",run_to); + while (pc != run_to) { + cpu_exec(); + if (KBHIT()) break; + } + show_reg(); + } else if (!strcmp(tok,"reset")) { + init_cpu(); + init_roms(); + init_vpp(); + } else if (!strcmp(tok,"reg")) { + show_reg(); + } else if (!strcmp(tok,"stack")) { + for(i=8; i<24; i+=2) { + ad = intRAM[i]; + d = intRAM[i+1]; + ad = ad | ((d & 0x0F) << 8); + printf("%x: PC=%x PSW=%x",i,ad,d); + if (i == sp) printf(" <0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%i",&t); + fn = fopen(file,"wb"); + if (fn==NULL) { + fprintf(stderr,"Error opening save-file %s: %i\n",file,errno); + } + else + { + fwrite ((rom+adr),t,1,fn); + fclose(fn); + printf("File %s saved: %i bytes from address:%x\n",file,t,adr); + } + } + } + + } + } + } else if (!strcmp(tok,"savedatah")) + { + int t; + int adr; + FILE *fn; + tok=strtok(NULL," "); + if (tok){ + char file[80]=""; + sscanf(tok,"%79s",file); + if (strlen(file)>0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%i",&t); + fn = fopen(file,"wt"); + if (fn==NULL) { + fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno); + } + else + { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j=0; + for (i=0; i<((int) ((t-1)/8))+1; i++) + { + fprintf(fn,"db "); + for (j=0;j<8 && i*8+j0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%i",&t); + fn = fopen(file,"wt"); + if (fn==NULL) { + fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno); + } + else + { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j=0; + for (i=0; i<((int) ((t-1)/8))+1; i++) + { + fprintf(fn,"db "); + for (j=0;j<8 && i*8+j0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%i",&t); + fn = fopen(file,"wt"); + if (fn==NULL) { + fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno); + } + else + { + // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile + int j=0; + for (i=0; i<((int) ((t-1)/8))+1; i++) + { + fprintf(fn,"db "); + for (j=0;j<8 && i*8+j0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%i",&t); + fn = fopen(file,"wt"); + if (fn==NULL) { + fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno); + } + else + { + char binary_value[32]; + // write format "db xxxxxxxxb" 1 Zeichen pro Zeile + for (i=0; i0) { + fn = fopen(file,"wt"); + if (fn==NULL) { + fprintf(stderr,"Error opening vpp data file %s: %i\n",file,errno); + } else { + /* write char/attribute data */ + for(i = 0; i < 25; i++) { + /* service row is 24 in file, 31 in memory */ + if (i == 24) i = 31; + for(j = 0; j < 40; j++) { + if (fwrite(&vpp_mem[j][i][0], 1, 1, fn) != 1) { + fprintf(stderr,"Error writing vpp data file %s: %i\n",file,errno); + break; + } + if (fwrite(&vpp_mem[j][i][1], 1, 1, fn) != 1) { + fprintf(stderr,"Error writing vpp data file %s: %i\n",file,errno); + break; + } + } + /* mirror slice bits */ + for(i = 0; i < 2; i++) for(j = 0; j < 960; j++) { + mchars[i][j] = ((dchars[i][j] & 0x80) >> 7) | ((dchars[i][j] & 0x40) >> 5) | ((dchars[i][j] & 0x20) >> 3) | ((dchars[i][j] & 0x10) >> 1) | ((dchars[i][j] & 0x08) << 1) | ((dchars[i][j] & 0x04) << 3) | ((dchars[i][j] & 0x02) << 5) | ((dchars[i][j] & 0x01) << 7); + } + /* write slice data */ + if (fwrite(mchars, 960, 2, fn) != 2) { + fprintf(stderr,"Error Writing vpp data file %s: %i\n",file,errno); + break; + } + fclose(fn); + } + + } + } + } + } else if (!strcmp(tok,"load")) + { + int adr; + FILE *fn; + tok=strtok(NULL," "); + if (tok){ + char file[80]=""; + sscanf(tok,"%79s",file); + if (strlen(file)>0) + { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&adr); + fn = fopen(file,"rb"); + if (fn==NULL) { + fprintf(stderr,"Error opening load-file %s: %i\n",file,errno); + } + else + { + int length; + fseek(fn,0L,SEEK_END); + length = ftell(fn); + rewind(fn); + fread ((rom+adr),length,1,fn); + fclose(fn); + printf("File %s loaded to address:%x (%i bytes)\n",file,adr,length); + } + } + + } + } + } else if (!strcmp(tok,"keys")) { + j=0; + printf("%02x:",0); + for(i=0; i<128; i++) { + printf("%02x,",key2[i]); + j++; + if (j == 16) { + printf("\n"); + printf("%02x:",i+1); + + j=0; + } + } + printf("\n"); + } else if (!strcmp(tok,"col")) { + j=0; + printf("%02x:",0); + for(i=0; i<256; i++) { + printf("%02x,",coltab[i]); + j++; + if (j == 16) { + printf("\n"); + printf("%02x:",i+1); + j=0; + } + } + printf("\n"); + printf("Colreg: %x\n ",ext_read(0xA2)); + } else if (!strcmp(tok,"extram")) { + int t; + tok=strtok(NULL," "); + if (tok){ + sscanf(tok,"%x",&t); + a = (Byte)t; + tok=strtok(NULL," "); + if (tok){ + sscanf(tok,"%x",&t); + d = (Byte)t; + extRAM[a] = d; + } + else + { + j=0; + printf("%02x:",0); + for(i=0; i<256; i++) { + printf("%02x",extRAM[i]); + if (j < 15) printf(","); + j++; + if (j == 16 && i !=255) { + printf("\n"); + printf("%02x:",i+1); + + j=0; + } + } +} +} + printf("\n\n"); + } else if (!strcmp(tok,"intram")) { + int t; + tok=strtok(NULL," "); + if (tok){ + sscanf(tok,"%x",&t); + a = (Byte)t; + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%x",&t); + d = (Byte)t; + intRAM[a] = d; + } + else + { + j=0; + printf("%02x:",0); + for(i=0; i<64; i++) { + printf("%02x",intRAM[i]); + if (j < 15) printf(","); + j++; + if (j == 16 && i != 63) { + printf("\n"); + printf("%02x:",i+1); + j=0; + } + } + printf("\n\n"); + } + } + } else if (!strcmp(tok,"run")) { + tok=strtok(NULL," "); + if (tok){ + sscanf(tok,"%hx",&run_to); + printf("Run to %x\n",run_to); + while (pc != run_to) { + cpu_exec(); + if (KBHIT()) break; + } + show_reg(); + } + } else if (!strcmp(tok,"bp")) { + int bp; + tok=strtok(NULL," "); + bp=65535; + sscanf(tok,"%x",&bp); + if (bp==65535) + { + if (app_data.breakpoint==65535) + printf("No Breakpoint set.\n"); + else printf("Breakpoint at %x\n",app_data.breakpoint); + } + else + { + sscanf(tok,"%x",&bp); + app_data.breakpoint = bp; + printf("Breakpoint set to %x\n",app_data.breakpoint); + } + } else if (!strcmp(tok,"bpc")) { + if (app_data.breakpoint==65535) + printf("No Breakpoint set.\n"); + else + { + app_data.breakpoint = 65535; + printf("Breakpoint cleared.\n"); + } + } else if (!strcmp(tok,"runvb")) { + printf("Run to VBL\n"); + while (master_clk < 5500) { + cpu_exec(); + if (KBHIT()) break; + } + show_reg(); + } else if (!strcmp(tok,"runnvb")) { + printf("Run to no VBL\n"); + while (master_clk > 5500) { + cpu_exec(); + if (KBHIT()) break; + } + show_reg(); + } else if (!strcmp(tok,"go")) { + tok=strtok(NULL," "); + if (tok) sscanf(tok,"%d",&go); + } else if (!strcmp(tok,"di")) { + if (tok){ + tok=strtok(NULL," "); + ad=65535; + sscanf(tok,"%hx",&ad); + if (ad==65535) ad=nDisAsm; + + for(i=0; i<20; i++) + { + if (ad<32768) ad = ad + disasm(ad); else ad=0; + } + nDisAsm=ad; + printf("\n"); + } + } else if (!strcmp(tok,"md")) { + tok=strtok(NULL," "); + if (tok){ + ad=65535; + sscanf(tok,"%hx",&ad); + if (ad==65535) ad=nMemDump; + printf("\n"); + + for (j=0; j<10; j++){ + if (ad+j*16<32768) { + printf("%04x : ",ad+j*16); + for (i=0; i<16; i++) printf("%02x ",rom[ad+j*16+i]); + printf("\n"); + } + else + { + ad = 0; + } + } + nMemDump = ad+10*16; + printf("\n\n"); + } + } else if (!strcmp(tok,"sndlog")) { + if (app_data.sound_en) { + tok=strtok(NULL," "); + if (tok){ + char file[80]=""; + sscanf(tok,"%79s",file); + if (strlen(file)>0){ + sndlog = fopen(file,"wb"); + if (sndlog) + printf("Sound log file created\n"); + else + printf("Sound log file creation failed\n"); + } + } + printf("\n"); + } else printf("Sound emulation disabled\n\n"); + + } else if (!strcmp(tok,"ss")) { + tok=strtok(NULL," "); + if (tok){ + char file[80]=""; + sscanf(tok,"%79s",file); + if (strlen(file)>0){ + savestate(file); + } + } + printf("\n"); + + } else if (!strcmp(tok,"ls")) { + tok=strtok(NULL," "); + if (tok){ + char file[80]=""; + sscanf(tok,"%79s",file); + if (strlen(file)>0){ + loadstate(file); + } + } + printf("\n"); + + } else if (!strcmp(tok,"showfps")) { + show_fps=1; + + } else if (!strcmp(tok,"c")) + { + int t; + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%hx",&ad); + printf("Addr Old New (enter to exit)\n"); // Header + + do + { + printf("%.4X %.2X ?",ad,rom[ad]); // Memory Position, Old Value + + fgets(inp,80,stdin); + if (inp[0]!=10) + { + t=65535; + sscanf(inp,"%x",&t); + if (t<256) + { + d = (Byte) t; + rom[ad]=d; + ad=(ad==32768)?0:ad+1; + } + else + { + printf("wrong value, try again\n"); + } + } + } + while (inp[0]!=10); + } + printf("\n"); + + } else if (!strcmp(tok,"as")) { + tok=strtok(NULL," "); + if (tok) + { + sscanf(tok,"%hx",&ad); + + printf("Addr Instruction (enter to exit)\n"); // Header + do + { + printf("%.4X ",ad); // Memory Position + fgets(inp,80,stdin); + + if (inp[0]!=10) + { + ad = ad + assemble(inp,ad); + } + } + while (inp[0]!=10); + } + printf("\n"); + + + } else if ((strlen(tok)>0) && (strcmp(tok,"\n"))) { + printf("Unknown command\n\n"); + } + + } + + #ifdef ALLEGRO_WINDOWS + FreeConsole(); + #endif + +} + + +static void show_reg(void) { + int i; + + make_psw_debug(); + printf("PC=%.3X A=%.2X PSW=%.2X P1=%.2X P2=%.2X",pc,acc,psw,p1,p2); + printf(" clk: %d reg:%d count:%x f:%x\n",master_clk,reg_pnt,itimer,frame); + disasm(pc); + printf("\n"); + + printf("R%d: %02x R%d': %02x PSW: ",0,intRAM[0],0,intRAM[24]); + printf("%sC %sAC %sF0 %sF1 SP:%.2X\n",psw&0x80?"":"!",psw&0x40?"":"!",psw&0x20?"":"!",psw&0x10?"":"!",psw&0x07); + + printf("R%d: %02x R%d': %02x P1: ",1,intRAM[1],1,intRAM[25]); + printf("%sLum %sCopy %sVP+ %sExtRam %sVDC %sKeyB Bank:%i\n",p1&0x80?"":"!",p1&0x40?"":"!",p1&0x20?"":"!",p1&0x10?"":"!",p1&0x08?"":"!",p1&0x04?"":"!",p1&0x03); + + printf("R%d: %02x R%d': %02x ",2,intRAM[2],2,intRAM[26]); + printf("MB%i RB%i\n",A11ff>>11,reg_pnt>4); + + for (i=3; i<8; i++) { + printf("R%d: %02x R%d': %02x\n",i,intRAM[i],i,intRAM[i+24]); + } +} + + +static int disasm(ADDRESS p) { + Byte op,d; + ADDRESS adr; + + op=rom[p++]; + printf("%04x %02x",p-1,op); + if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" "); + printf(" %s",lookup[op].mnemonic); + switch(lookup[op].type) { + case 0: + printf("\n"); + break; + case 1: + d=rom[p]; + printf(" #%02x\n",d); + break; + case 2: + adr=rom[p]; + adr = adr | ((op & 0xE0) << 3); + printf(" $%03x\n",adr); + break; + case 3: + printf(" $%02x\n",rom[p]); + break; + } + return lookup[op].bytes; +} + +static int assemble(char *opcode, int p) +{ + char *str_value; + int op=0; + int value; + int t; + + while((op<256)&&(strncasecmp(opcode,lookup[op].mnemonic,strlen(lookup[op].mnemonic))!=0)) op++; + + if (op==256) + { + printf("Wrong opcode, please try again.\n"); + return(0); + } + + str_value = opcode+strlen(lookup[op].mnemonic); + while (str_value[0]==' ') str_value++; + + switch(lookup[op].type) + { + case 0: // no other value needed + rom[p]=op; + break; + case 1: // #value needed + if (str_value[0]!='#') + { + printf("Error: #xx expected\n"); + return(0); + } + t=65335; + sscanf(str_value+1,"%2x",&t); + if (t>=256) + { + printf("Error: #xx expected (value #00-#FF)\n"); + return(0); + } + else value = (Byte) t; + rom[p]=op; + rom[p+1]=value; + break; + case 2: // $addresss needed (max. 7FF) + if (str_value[0]!='$') + { + printf("Error: $xxx expected %s\n",str_value); + return(0); + } + t=65335; + sscanf(str_value+1,"%x",&t); + if (t>=2048) + { + printf("Error: $xxx expected (value below $800)\n"); + return(0); + } + else value = (Byte) t; + rom[p]=op | ((t&1792)>>3); + rom[p+1]=value; + break; + + case 3: // $address needed (max. FF) + if (str_value[0]!='$') + { + printf("Error: $xx expected\n"); + return(0); + } + t=65335; + sscanf(str_value+1,"%x",&t); + if (t>=256) + { + printf("Error: $xx expected (value $00-$FF)\n"); + return(0); + } + else value = (Byte) t; + rom[p]=op; + rom[p+1]=value; + break; + + } + return lookup[op].bytes; +} + +void decimal2binary(int decimal_value, char binary_value[32], short digits) +{ + short i; + for(i=digits;i>=0;i--) + { + binary_value[i]=(char)('0'+(int) (decimal_value/(1<=0;i--) + { + if (binary_value[i]=='0') printf(" "); + else printf("%c",178); + } + + printf("\n"); + return 1; +} diff --git a/src/debug.h b/src/debug.h new file mode 100755 index 0000000..00bad38 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,14 @@ +#ifndef DEBUG_H +#define DEBUG_H + +void debug(void); + +#endif /* DEBUG_H */ + + + + + + + + diff --git a/src/dis48.c b/src/dis48.c new file mode 100755 index 0000000..b08e530 --- /dev/null +++ b/src/dis48.c @@ -0,0 +1,151 @@ + +/* + * O2/8048 disassembler + */ + + +#include +#include +#include +#include +#include "types.h" +#include "table.h" +#include "debug.h" + +#define BIOSLEN 1024 +#define MAXLEN 8192 + + +Byte rom[MAXLEN+BIOSLEN]; +ADDRESS pc; + +int parse_option(char *attr, char *val); + +static int disasm(ADDRESS p) { + Byte op,d; + ADDRESS adr; + + op=rom[p++]; + printf("%04x %02x",p-1,op); + if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" "); + printf(" %s",lookup[op].mnemonic); + switch(lookup[op].type) { + case 0: + printf("\n"); + break; + case 1: + d=rom[p]; + printf(" #%02x\n",d); + break; + case 2: + adr=rom[p]; + adr = adr | ((op & 0xE0) << 3); + printf(" $%03x\n",adr); + break; + case 3: + printf(" $%02x\n",rom[p]); + break; + } + if (op == 0x83 || op == 0x93 || (((p-2+lookup[op].bytes) & 0xff) == 0xff)) printf("\n"); // Linebreak after ret, retr and end of page + return lookup[op].bytes; +} + + +int main(int argc, char **argv){ + int n; + int i,j; + int start; + long len; + FILE *fn; + static char file[MAXC], attr[MAXC], val[MAXC], *p; + pc = BIOSLEN; + if (argc<2) { + printf("Usage: dis48 [file] [-bios]\n"); + exit(0); + } + + /* load image */ + + for(i=1; iMAXLEN) { + printf("Invalid image size"); + fclose(fn); + exit(0); + } + + rewind(fn); + if (fread(&rom[pc],1,len,fn) != (size_t)len) { + printf("Error loading %s\n",argv[1]); + fclose(fn); + exit(0); + } + fclose(fn); + + start = pc; + while (pc < start+len) { + n = disasm(pc); + pc = pc + n; + } + exit(0); +} + +int parse_option(char *attr, char *val){ + + if (!strcmp(attr,"bios")) + { + pc = 0; + } + else + { + fprintf(stderr,"Invalid option : %s\n",attr); + return 0; + } + return 1; +} + + + diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100755 index 0000000..fc4a50e --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,583 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Keyboard emulation + */ + + +#include +#include +#include +#include "types.h" +#include "cpu.h" +#include "config.h" +#include "vmachine.h" +#include "vdc.h" +#include "audio.h" +#include "voice.h" +#include "vpp.h" +#include "keyboard.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "libretro.h" +#include "wrapalleg.h" +#endif + +#include "score.h" + +int NeedsPoll = 0; + +Byte keycode; +Byte last_key; +Byte new_int=0; /* Is new interrupt installed */ + +Byte key_done=0; +Byte key_debug=0; +#ifndef __LIBRETRO__ + +struct keyb keybtab[] = { + {KEY_A,"A"}, + {KEY_B,"B"}, + {KEY_C,"C"}, + {KEY_D,"D"}, + {KEY_E,"E"}, + {KEY_F,"F"}, + {KEY_G,"G"}, + {KEY_H,"H"}, + {KEY_I,"I"}, + {KEY_J,"J"}, + {KEY_K,"K"}, + {KEY_L,"L"}, + {KEY_M,"M"}, + {KEY_N,"N"}, + {KEY_O,"O"}, + {KEY_P,"P"}, + {KEY_Q,"Q"}, + {KEY_R,"R"}, + {KEY_S,"S"}, + {KEY_T,"T"}, + {KEY_U,"U"}, + {KEY_V,"V"}, + {KEY_W,"W"}, + {KEY_X,"X"}, + {KEY_Y,"Y"}, + {KEY_Z,"Z"}, + {KEY_0,"0"}, + {KEY_1,"1"}, + {KEY_2,"2"}, + {KEY_3,"3"}, + {KEY_4,"4"}, + {KEY_5,"5"}, + {KEY_6,"6"}, + {KEY_7,"7"}, + {KEY_8,"8"}, + {KEY_9,"9"}, + {KEY_0_PAD,"0_PAD"}, + {KEY_1_PAD,"1_PAD"}, + {KEY_2_PAD,"2_PAD"}, + {KEY_3_PAD,"3_PAD"}, + {KEY_4_PAD,"4_PAD"}, + {KEY_5_PAD,"5_PAD"}, + {KEY_6_PAD,"6_PAD"}, + {KEY_7_PAD,"7_PAD"}, + {KEY_8_PAD,"8_PAD"}, + {KEY_9_PAD,"9_PAD"}, + {KEY_TILDE,"TILDE"}, + {KEY_MINUS,"MINUS"}, + {KEY_EQUALS,"EQUALS"}, + {KEY_BACKSPACE,"BACKSPACE"}, + {KEY_TAB,"TAB"}, + {KEY_OPENBRACE,"OPENBRACE"}, + {KEY_CLOSEBRACE,"CLOSEBRACE"}, + {KEY_ENTER,"ENTER"}, + {KEY_COLON,"COLON"}, + {KEY_QUOTE,"QUOTE"}, + {KEY_BACKSLASH,"BACKSLASH"}, + {KEY_BACKSLASH2,"BACKSLASH2"}, + {KEY_COMMA,"COMMA"}, + {KEY_STOP,"STOP"}, + {KEY_SLASH,"SLASH"}, + {KEY_SPACE,"SPACE"}, + {KEY_INSERT,"INSERT"}, + {KEY_DEL,"DEL"}, + {KEY_HOME,"HOME"}, + {KEY_END,"END"}, + {KEY_PGUP,"PGUP"}, + {KEY_PGDN,"PGDN"}, + {KEY_LEFT,"LEFT"}, + {KEY_RIGHT,"RIGHT"}, + {KEY_UP,"UP"}, + {KEY_DOWN,"DOWN"}, + {KEY_SLASH_PAD,"SLASH_PAD"}, + {KEY_ASTERISK,"ASTERISK"}, + {KEY_MINUS_PAD,"MINUS_PAD"}, + {KEY_PLUS_PAD,"PLUS_PAD"}, + {KEY_DEL_PAD,"DEL_PAD"}, + {KEY_ENTER_PAD,"ENTER_PAD"}, + {KEY_PRTSCR,"PRTSCR"}, + {KEY_PAUSE,"PAUSE"}, + {KEY_ABNT_C1,"ABNT_C1"}, + {KEY_YEN,"YEN"}, + {KEY_KANA,"KANA"}, + {KEY_AT,"AT"}, + {KEY_CIRCUMFLEX,"CIRCUMFLEX"}, + {KEY_COLON2,"COLON2"}, + {KEY_KANJI,"KANJI"}, + {KEY_LSHIFT,"LSHIFT"}, + {KEY_RSHIFT,"RSHIFT"}, + {KEY_LCONTROL,"LCONTROL"}, + {KEY_RCONTROL,"RCONTROL"}, + {KEY_ALT,"ALT"}, + {KEY_ALTGR,"ALTGR"}, + {KEY_LWIN,"LWIN"}, + {KEY_RWIN,"RWIN"}, + {KEY_MENU,"MENU"}, + {KEY_SCRLOCK,"SCRLOCK"}, + {KEY_NUMLOCK,"NUMLOCK"}, + {KEY_F1,"F1"}, + {KEY_F2,"F2"}, + {KEY_F3,"F3"}, + {KEY_F4,"F4"}, + {KEY_F5,"F5"}, + {KEY_F6,"F6"}, + {KEY_F7,"F7"}, + {KEY_F8,"F8"}, + {KEY_F9,"F9"}, + {KEY_F10,"F10"}, + {KEY_F11,"F11"}, + {KEY_F12,"F12"}, + {KEY_ESC,"ESC"}, + {0,""} +}; +#else +#define RETROK_TILDE 178 + +struct keyb keybtab[] = { + {RETROK_a,"A"}, + {RETROK_b,"B"}, + {RETROK_c,"C"}, + {RETROK_d,"D"}, + {RETROK_e,"E"}, + {RETROK_f,"F"}, + {RETROK_g,"G"}, + {RETROK_h,"H"}, + {RETROK_i,"I"}, + {RETROK_j,"J"}, + {RETROK_k,"K"}, + {RETROK_l,"L"}, + {RETROK_m,"M"}, + {RETROK_n,"N"}, + {RETROK_o,"O"}, + {RETROK_p,"P"}, + {RETROK_q,"Q"}, + {RETROK_r,"R"}, + {RETROK_s,"S"}, + {RETROK_t,"T"}, + {RETROK_u,"U"}, + {RETROK_v,"V"}, + {RETROK_w,"W"}, + {RETROK_x,"X"}, + {RETROK_y,"Y"}, + {RETROK_z,"Z"}, + {RETROK_0,"0"}, + {RETROK_1,"1"}, + {RETROK_2,"2"}, + {RETROK_3,"3"}, + {RETROK_4,"4"}, + {RETROK_5,"5"}, + {RETROK_6,"6"}, + {RETROK_7,"7"}, + {RETROK_8,"8"}, + {RETROK_9,"9"}, + {RETROK_KP0,"0_PAD"}, + {RETROK_KP1,"1_PAD"}, + {RETROK_KP2,"2_PAD"}, + {RETROK_KP3,"3_PAD"}, + {RETROK_KP4,"4_PAD"}, + {RETROK_KP5,"5_PAD"}, + {RETROK_KP6,"6_PAD"}, + {RETROK_KP7,"7_PAD"}, + {RETROK_KP8,"8_PAD"}, + {RETROK_KP9,"9_PAD"}, + {RETROK_TILDE,"TILDE"}, + {RETROK_MINUS,"MINUS"}, + {RETROK_EQUALS,"EQUALS"}, + {RETROK_BACKSPACE,"BACKSPACE"}, + {RETROK_TAB,"TAB"}, + {RETROK_LEFTBRACKET,"OPENBRACE"}, + {RETROK_RIGHTBRACKET,"CLOSEBRACE"}, + {RETROK_RETURN,"ENTER"}, + {RETROK_COLON,"COLON"}, + {RETROK_QUOTE,"QUOTE"}, + {RETROK_BACKSLASH,"BACKSLASH"}, +// {RETROK_BACKSLASH2,"BACKSLASH2"}, + {RETROK_COMMA,"COMMA"}, +// {RETROK_STOP,"STOP"}, + {RETROK_SLASH,"SLASH"}, + {RETROK_SPACE,"SPACE"}, + {RETROK_INSERT,"INSERT"}, + {RETROK_DELETE,"DEL"}, + {RETROK_HOME,"HOME"}, + {RETROK_END,"END"}, + {RETROK_PAGEUP,"PGUP"}, + {RETROK_PAGEDOWN,"PGDN"}, + {RETROK_LEFT,"LEFT"}, + {RETROK_RIGHT,"RIGHT"}, + {RETROK_UP,"UP"}, + {RETROK_DOWN,"DOWN"}, + {RETROK_KP_DIVIDE,"SLASH_PAD"}, + {RETROK_KP_MULTIPLY,"ASTERISK"}, + {RETROK_KP_MINUS,"MINUS_PAD"}, + {RETROK_KP_PLUS,"PLUS_PAD"}, + {RETROK_KP_PERIOD,"DEL_PAD"}, + {RETROK_KP_ENTER,"ENTER_PAD"}, + {RETROK_PRINT,"PRTSCR"}, + {RETROK_PAUSE,"PAUSE"}, +// {RETROK_ABNT_C1,"ABNT_C1"}, +// {RETROK_YEN,"YEN"}, +// {RETROK_KANA,"KANA"}, + {RETROK_AT,"AT"}, + {RETROK_CARET,"CIRCUMFLEX"}, +// {RETROK_COLON2,"COLON2"}, +// {RETROK_KANJI,"KANJI"}, + {RETROK_LSHIFT,"LSHIFT"}, + {RETROK_RSHIFT,"RSHIFT"}, + {RETROK_LCTRL,"LCONTROL"}, + {RETROK_RCTRL,"RCONTROL"}, + {RETROK_LALT,"ALT"}, + {RETROK_RALT,"ALTGR"}, + {RETROK_LMETA,"LWIN"}, + {RETROK_RMETA,"RWIN"}, + {RETROK_MENU,"MENU"}, + {RETROK_SCROLLOCK,"SCRLOCK"}, + {RETROK_NUMLOCK,"NUMLOCK"}, + {RETROK_F1,"F1"}, + {RETROK_F2,"F2"}, + {RETROK_F3,"F3"}, + {RETROK_F4,"F4"}, + {RETROK_F5,"F5"}, + {RETROK_F6,"F6"}, + {RETROK_F7,"F7"}, + {RETROK_F8,"F8"}, + {RETROK_F9,"F9"}, + {RETROK_F10,"F10"}, + {RETROK_F11,"F11"}, + {RETROK_F12,"F12"}, + {RETROK_ESCAPE,"ESC"}, + {0,""} +}; +#endif + +int joykeys[2][5] = {{0,0,0,0,0},{0,0,0,0,0}}; +int joykeystab[128]; +int syskeys[8] = {0,0,0,0,0,0,0,0}; + + +void set_defjoykeys(int jn, int sc){ + //if (sc) + // set_joykeys(jn,RETROK_w,RETROK_s,RETROK_a,RETROK_d,RETROK_SPACE); + //else + // set_joykeys(jn,RETROK_UP,RETROK_DOWN,RETROK_LEFT,RETROK_RIGHT,RETROK_l); +} + + +void set_defsystemkeys(void){ + set_systemkeys(RETROK_F12,RETROK_F1,RETROK_F4,RETROK_F5,RETROK_F8,RETROK_F2,RETROK_F3,RETROK_F6); +} + + + +void set_joykeys(int jn, int up, int down, int left, int right, int fire){ + int i,j; + if ((jn<0) || (jn>1)) return; + joykeys[jn][0] = up; + joykeys[jn][1] = down; + joykeys[jn][2] = left; + joykeys[jn][3] = right; + joykeys[jn][4] = fire; + + for (i=0; i<128; i++) joykeystab[i]=0; + + for (j=0; j<2; j++) + for (i=0; i<5; i++) { + if ((joykeys[j][i]<1) || (joykeys[j][i]>127)) + joykeys[j][i] = 0; + else + joykeystab[joykeys[j][i]] = 1; + } +} + +void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject) +{ + syskeys[0] = k_quit; + syskeys[1] = k_pause; + syskeys[2] = k_debug; + syskeys[3] = k_reset; + syskeys[4] = k_screencap; + syskeys[5] = k_save; + syskeys[6] = k_load; + syskeys[7] = k_inject; +} + +#ifdef __LIBRETRO__ +unsigned char key[256*2]; + +void rloadstate(){ + + int stateError; + if ((stateError=loadstate(app_data.statefile))==0) + { + printf("Savefile loaded.\n"); + } + else if (stateError>=199) + { + if (stateError==199) printf("Wrong ROM-File for Savefile.\n"); + else if (stateError==200+ROM_O2) printf("Wrong BIOS for Savefile: O2ROM needed.\n"); + else if (stateError==200+ROM_G7400) printf("Wrong BIOS for Savefile: G7400 ROM needed.\n"); + else if (stateError==200+ROM_C52) printf("Wrong BIOS for Savefile: C52 ROM needed.\n"); + else if (stateError==200+ROM_JOPAC) printf("Wrong BIOS for Savefile: JOPAC ROM needed.\n"); + else printf("Wrong BIOS for Savefile: UNKNOWN ROM needed.\n"); + } + +} + +void rsavestate(){ + + if (savestate(app_data.statefile)==0) + { + printf("Savefile saved.\n"); + } +} + +void rscore(){ + + set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore); +} + +#endif + +void handle_key(void){ + + if (NeedsPoll) + poll_keyboard(); + + if (key[syskeys[0]] || key[RETROK_ESCAPE]) { + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[0]] || key[RETROK_ESCAPE]); + key_done=1; + } + + if (key[syskeys[1]]) { + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[1]]); + + mute_audio(); + mute_voice(); + abaut(); + + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + if (key[RETROK_LALT] && key[RETROK_RETURN]) { + app_data.fullscreen = app_data.fullscreen ? 0 : 1; + grmode(); + abaut(); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[RETROK_RETURN]); + } + + } while ((!key[syskeys[1]]) && (!key[RETROK_ESCAPE]) && (!key[syskeys[0]])); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[1]]); + + init_sound_stream(); + } + + if (key[syskeys[5]]) + { + if (savestate(app_data.statefile)==0) + { + display_msg("Savefile saved.",5); + } + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[5]]); + + } + + /* LOAD STATE */ + if (key[syskeys[6]]) + { + int stateError; + if ((stateError=loadstate(app_data.statefile))==0) + { + display_msg("Savefile loaded.",5); + } + else if (stateError>=199) + { + if (stateError==199) display_msg("Wrong ROM-File for Savefile.",5); + else if (stateError==200+ROM_O2) display_msg("Wrong BIOS for Savefile: O2ROM needed.",5); + else if (stateError==200+ROM_G7400) display_msg("Wrong BIOS for Savefile: G7400 ROM needed.",5); + else if (stateError==200+ROM_C52) display_msg("Wrong BIOS for Savefile: C52 ROM needed.",5); + else if (stateError==200+ROM_JOPAC) display_msg("Wrong BIOS for Savefile: JOPAC ROM needed.",5); + else display_msg("Wrong BIOS for Savefile: UNKNOWN ROM needed.",5); + } + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[6]]); + } + + if (key[syskeys[2]]) key_debug=1; + + if (key[syskeys[3]]) { + init_cpu(); + init_roms(); + init_vpp(); + clearscr(); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[3]]); + } + + /* SET HIGHSCORE */ + if (key[syskeys[7]]) + { + set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore); + } + + + if (key[syskeys[4]]) { +#ifndef __LIBRETRO__ + BITMAP *bmp; + PALETTE pal; + char *p; + static char name[1024]; + static int scshot_counter = 0; + + if (strlen(app_data.scshot)>0){ + if ((p=strchr(app_data.scshot,'@'))) { + *p = 0; + sprintf(name, "%s%02d%s", app_data.scshot, scshot_counter++, p+1); + *p = '@'; + } else { + strcpy(name, app_data.scshot); + } + get_palette(pal); + bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H); + save_bitmap(name, bmp, pal); + destroy_bitmap(bmp); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[syskeys[4]]); + } +#endif + } + + + if (key[RETROK_LALT] && key[RETROK_RETURN]) { + app_data.fullscreen = app_data.fullscreen ? 0 : 1; + grmode(); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[RETROK_RETURN]); + } + +} + +extern int joystick_data[2][5]; //Up, Down, Left, Right, "Action" + +Byte keyjoy(int jn){ + Byte d; + d=0xFF; + if ((jn>=0) && (jn<=1)){ +#ifdef __LIBRETRO__ + if (joystick_data[jn][0]) d &= 0xFE; + if (joystick_data[jn][1]) d &= 0xFB; + if (joystick_data[jn][2]) d &= 0xF7; + if (joystick_data[jn][3]) d &= 0xFD; + if (joystick_data[jn][4]) d &= 0xEF; +#else + if (NeedsPoll) + poll_keyboard(); + + if (key[joykeys[jn][0]]) d &= 0xFE; + if (key[joykeys[jn][1]]) d &= 0xFB; + if (key[joykeys[jn][2]]) d &= 0xF7; + if (key[joykeys[jn][3]]) d &= 0xFD; + if (key[joykeys[jn][4]]) d &= 0xEF; +#endif + } + return d; +} + + +void init_keyboard(void){ + key_done=0; + key_debug=0; + +#ifndef __LIBRETRO__ + install_keyboard(); +#else + memset(key,0,512); +#endif + new_int=1; +#ifndef __LIBRETRO__ + NeedsPoll = keyboard_needs_poll(); +#else + NeedsPoll = 1; +#endif +} + + +void Set_Old_Int9(void){ +#ifndef __LIBRETRO__ + remove_keyboard(); +#endif + new_int=0; +} + diff --git a/src/keyboard.h b/src/keyboard.h new file mode 100755 index 0000000..da8daca --- /dev/null +++ b/src/keyboard.h @@ -0,0 +1,29 @@ +#ifndef __KEYBOARD_H +#define __KEYBOARD_H + +void Set_Old_Int9(void); +void init_keyboard(void); +void handle_key(void); +void set_joykeys(int joy, int up, int down, int left, int right, int fire); +void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject); +void set_defjoykeys(int joy, int sc); +void set_defsystemkeys(void); +Byte keyjoy(int jn); + +extern Byte new_int; +extern int NeedsPoll; +extern Byte key_done; +extern Byte key_debug; +extern int joykeys[2][5]; +extern int joykeystab[128]; +extern int syskeys[8]; + +struct keyb{ + int keybcode; + char *keybname; +}; + +extern struct keyb keybtab[]; + +#endif + diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..ebfeda9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,962 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + */ +#include +#include +#include +#include +#include +#include +#include "crc32.h" +#include "audio.h" +#include "vmachine.h" +#include "config.h" +#include "vdc.h" +#include "cpu.h" +#include "debug.h" +#include "keyboard.h" +#include "voice.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "wrapalleg.h" + +#ifdef AND +#warning android log +#include +#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__) +#endif + +#endif + +#include "score.h" +#ifdef ALLEGRO_WINDOWS +#include "winalleg.h" +#endif +static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC], + biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC], + odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC], bios_l[MAXC], + file_v[MAXC],scorefile[MAXC], statefile[MAXC], path[MAXC]; +FILE *f; +char name_f, rom_f, c_j; +char pathx, *k, *launcher_flag_r, *launcher_flag_b, identify; +int file_name(char *pathx); +int suck_bios(); +int suck_roms(); +int identify_bios(char *identify); +int contax, o2flag, g74flag, c52flag, jopflag, helpflag; +int j; +unsigned long crcx = ~0; +static long filesize(FILE *stream); +static void load_bios(const char *biosname); +static void load_cart(char *file); +static void helpus(void); +int parse_option(char *attr, char *val); +void read_default_config(void); +/********************* Main*/ +int omain(int argc, char *argv[]){ + int i, cnt, cntt, cnttt, way; + static char file[MAXC], attr[MAXC], val[MAXC], *p, *binver; + #if defined(ALLEGRO_WINDOWS) + binver = "Windows binary"; + #elif defined(ALLEGRO_DOS) + binver = "DOS binary"; + #elif defined(ALLEGRO_LINUX) + binver = "Linux binary"; + #elif defined(ALLEGRO_BEOS) + binver = "BEOS binary"; + #elif defined(ALLEGRO_QNX) + binver = "QNX binary"; + #elif defined(ALLEGRO_UNIX) + binver = "UNIX binary"; + #elif defined(ALLEGRO_MPW) + binver = "MacOS binary"; + #else + binver = "Unknown binary"; + #endif + printf("%s %s\n","\nO2EM v" O2EM_VERSION " " RELEASE_DATE " - ", binver); + printf("Free Odyssey2 / Videopac+ Emulator - http://o2em.sourceforge.net\n"); + printf("Created by Daniel Boris (c)1996/1998\n"); + printf("Developed by:\n"); + printf(" Andre de la Rocha since version 0.80\n"); + printf(" Arlindo M. de Oliveira since version 1.16\n"); + printf("\n"); + + app_data.debug = 0; + app_data.stick[0] = app_data.stick[1] = 1; + app_data.sticknumber[0] = app_data.sticknumber[1] = 0; + set_defjoykeys(0,0); + set_defjoykeys(1,1); + set_defsystemkeys(); + app_data.bank = 0; + app_data.limit = 1; + app_data.sound_en = 1; + app_data.speed = 100; + app_data.wsize = 2; + #ifdef ALLEGRO_DOS + app_data.fullscreen = 1; + #else + app_data.fullscreen = 0; + #endif + app_data.scanlines = 0; + app_data.voice = 1; + app_data.window_title = "O2EM v" O2EM_VERSION; + app_data.svolume = 100; + app_data.vvolume = 100; + app_data.filter = 0; + app_data.exrom = 0; + app_data.three_k = 0; + app_data.crc = 0; + app_data.scshot = scshot; + app_data.statefile = statefile; + app_data.euro = 0; + app_data.openb = 0; + app_data.vpp = 0; + app_data.bios = 0; + app_data.scoretype = 0; + app_data.scoreaddress = 0; + app_data.default_highscore = 0; + app_data.breakpoint = 65535; + app_data.megaxrom = 0; + strcpy(file,""); + strcpy(file_l,""); + strcpy(bios_l,""); + strcpy(bios,""); + strcpy(scshot,""); + strcpy(statefile,""); + strcpy(xrom,""); + strcpy(scorefile,"highscore.txt"); + read_default_config(); + if (argc >= 2){ + for(i=1; i=199) + { + if (stateError==199) fprintf(stderr,"Wrong ROM-File for Savefile."); + else if (stateError==200+ROM_O2) fprintf(stderr,"Wrong BIOS for Savefile: O2ROM needed."); + else if (stateError==200+ROM_G7400) fprintf(stderr,"Wrong BIOS for Savefile: G7400 ROM needed."); + else if (stateError==200+ROM_C52) fprintf(stderr,"Wrong BIOS for Savefile: C52 ROM needed."); + else if (stateError==200+ROM_JOPAC) fprintf(stderr,"Wrong BIOS for Savefile: JOPAC ROM needed."); + else fprintf(stderr,"Wrong BIOS for Savefile: UNKNOWN ROM needed."); + return(0); + } + if (app_data.debug) key_debug=1; + #ifndef _DEBUG + #ifdef ALLEGRO_WINDOWS + FreeConsole(); + #endif + #endif + +#ifdef __LIBRETRO__ +return 1; +#endif + run(); + + if (app_data.scoretype!=0) save_highscore(get_score(app_data.scoretype, app_data.scoreaddress), scorefile); + exit(EXIT_SUCCESS); + } +if (!strcmp(attr,"help")||!strcmp(attr,"HELP")) helpus(); +printf("type o2em -help"); +exit(EXIT_SUCCESS); +} +END_OF_MAIN(); +/******************************************************/ +int parse_option(char *attr, char *val){ + int t; + if (!strcmp(attr,"nolimit")) { + app_data.limit = !(val[0]!='0'); + } else if (!strcmp(attr,"nosound")) { + app_data.sound_en = !(val[0]!='0'); + } else if (!strcmp(attr,"novoice")) { + app_data.voice = !(val[0]!='0'); + } else if (!strcmp(attr,"filter")) { + app_data.filter = (val[0]!='0'); + } else if (!strcmp(attr,"debug")) { + app_data.debug = (val[0]!='0'); + } else if ((!strcmp(attr,"s1")) || (!strcmp(attr,"s2"))) { + int sn; + sn = (!strcmp(attr,"s1"))? 0 : 1; + if (strlen(val)<2){ + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=3)) { + if ((t==1)||(t==2)){ + app_data.stick[sn] = 1; + set_defjoykeys(sn,t-1); + } else { + app_data.stick[sn] = (t==0) ? 0 : 2; + if (t==3) + { + app_data.sticknumber[sn] = app_data.sticknumber[0]+app_data.sticknumber[1]+1; + } + set_joykeys(sn,0,0,0,0,0); + } + } else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else { + char *p,*s; + int i,k,code,nk,codes[5]; + strupr(val); + nk = 0; + p = strtok(val,","); + while (p) { + i = code = 0; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + while (k && (code==0)) { + if (strcmp(s,p)==0) code = k; + i++; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + } + if (!code) { + fprintf(stderr,"Invalid value for option %s : key %s unknown\n",attr,p); + return 0; + } + codes[nk] = code; + p = strtok(NULL,","); + nk++; + if (nk>5) { + fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr); + return 0; + } + } + if (nk != 5) { + fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr); + return 0; + } + app_data.stick[sn] = 1; + set_joykeys(sn,codes[0],codes[1],codes[2],codes[3],codes[4]); + } + + + + + } else if (!strcmp(attr,"s0")) { + char *p,*s; + int i,k,code,nk,codes[8]; + strupr(val); + nk = 0; + p = strtok(val,","); + while (p) { + i = code = 0; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + while (k && (code==0)) { + if (strcmp(s,p)==0) code = k; + i++; + k = keybtab[i].keybcode; + s = keybtab[i].keybname; + } + if (!code) { + fprintf(stderr,"Invalid value for option %s : key %s unknown\n",attr,p); + return 0; + } + codes[nk] = code; + p = strtok(NULL,","); + nk++; + if (nk>8) { + fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr); + return 0; + } + } + if (nk != 8) { + fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr); + return 0; + } + set_systemkeys(codes[0],codes[1],codes[2],codes[3],codes[4],codes[5],codes[6],codes[7]); + +} else if (!strcmp(attr,"speed")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>0) && (t<=10000)) + app_data.speed = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else if (!strcmp(attr,"svolume")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=100)) + app_data.svolume = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + if (t==0) app_data.sound_en=0; + } else if (!strcmp(attr,"vvolume")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=100)) + app_data.vvolume = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + if (t==0) app_data.voice=0; + } else if (!strcmp(attr,"wsize")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>0) && (t<5)) { + app_data.wsize = t; + app_data.fullscreen = 0; + } else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else if (!strcmp(attr,"fullscreen")) { + app_data.fullscreen = (val[0]!='0'); + } else if (!strcmp(attr,"scanlines")) { + app_data.scanlines = (val[0]!='0'); + } else if (!strcmp(attr,"scshot")) { + strcpy(scshot,val); + } else if (!strcmp(attr,"savefile")) { + strcpy(statefile,val); + } else if (!strcmp(attr,"biosdir")) { + strcpy(xbios,val); + } else if (!strcmp(attr,"bios")) { + strcpy(bios,val); + } else if (!strcmp(attr,"romdir")) { + strcpy(xrom,val); + } else if (!strcmp(attr,"help")) { + helpflag = 1; + } else if (!strcmp(attr,"euro")) { + app_data.euro = (val[0]!='0'); + } else if (!strcmp(attr,"exrom")) { + app_data.exrom = (val[0]!='0'); + } else if (!strcmp(attr,"3k")) { + app_data.three_k = (val[0]!='0'); + } else if (!strcmp(attr,"g7400")){ + strcpy(bios,"g7400"); + } else if (!strcmp(attr,"c52")) { + strcpy(bios,"c52"); + } else if (!strcmp(attr,"jopac")) { + strcpy(bios,"jopac"); + } else if (!strcmp(attr,"o2rom")) { + strcpy(bios,"o2rom"); + } else if (!strcmp(attr,"scorefile")) { + strcpy(scorefile,val); + } else if (!strcmp(attr,"scoreadr")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=255)) + app_data.scoreaddress = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else if (!strcmp(attr,"scoretype")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=9999)) + app_data.scoretype = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else if (!strcmp(attr,"score")) { + t = -1; + sscanf(val,"%d",&t); + if ((t>=0) && (t<=999999)) + app_data.default_highscore = t; + else { + fprintf(stderr,"Invalid value for option %s\n",attr); + return 0; + } + } else { + if (!helpflag){ + fprintf(stderr,"Invalid option : %s\n",attr); + return 0; + } + } + return 1; +} +/****************************************************/ +void read_default_config(void){ + FILE *f; + static char attr[MAXC], val[MAXC], s[MAXC]; + char *p, *fn; + int i,l; + fn = "o2em_def.cfg"; + f = fopen(fn,"r"); + if (!f) { + fn = "O2EM_DEF.CFG"; + f = fopen(fn,"r"); + } + if (!f) return; + + l=0; + while (fgets(s,MAXC-1,f)){ + l++; + p=s; + while (*p && (isspace(*p))) p++; + if (*p && (*p != '#')) { + i=0; + while (*p && (!isspace(*p)) && (*p != '=')) attr[i++] = *p++; + attr[i]=0; + while (*p && (isspace(*p))) p++; + i=0; + if (*p == '='){ + p++; + while (*p && (isspace(*p))) p++; + if (*p == '"'){ + p++; + while (*p && (*p != '"') && (*p != '\n') && (*p != '\r')) val[i++] = *p++; + } else { + while (*p && (!isspace(*p))) val[i++] = *p++; + } + } + val[i]=0; + if (strlen(attr)>0) { + strlwr(attr); + if (!parse_option(attr,val)) { + printf("Error in the %s file at line number %d !\n\n",fn,l); + } + } + } + } + fclose(f); +} +/****************************************************/ +static long filesize(FILE *stream){ + long curpos, length; + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + fseek(stream, curpos, SEEK_SET); + return length; +} +/****************************************************/ +static void load_bios(const char *biosname){ + FILE *fn; + static char s[MAXC+10]; + unsigned long crc; + int i; + + if ((biosname[strlen(biosname)-1]=='/') || + (biosname[strlen(biosname)-1]=='\\') || + (biosname[strlen(biosname)-1]==':')) { + strcpy(s,biosname); + strcat(s,odyssey2); + fn = fopen(s,"rb"); + + if (!fn) { + strcpy(s,biosname); + strcat(s,odyssey2); + fn = fopen(s,"rb"); + } + } else { + + strcpy(s,biosname); + fn = fopen(biosname,"rb"); + } + + if (!fn) { + fprintf(stderr,"Error loading bios ROM (%s)\n",s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0],1024,1,fn) != 1) { + fprintf(stderr,"Error loading bios ROM %s\n",odyssey2); + exit(EXIT_FAILURE); + } + + strcpy(s,biosname); + fn = fopen(biosname,"rb"); + if (!fn) { + fprintf(stderr,"Error loading bios ROM (%s)\n",s); + exit(EXIT_FAILURE); + } + if (fread(rom_table[0],1024,1,fn) != 1) { + fprintf(stderr,"Error loading bios ROM %s\n",odyssey2); + exit(EXIT_FAILURE); + } + fclose(fn); + for (i=1; i<8; i++) memcpy(rom_table[i],rom_table[0],1024); + crc = crc32_buf(rom_table[0],1024); + if (crc==0x8016A315) { + printf("Odyssey2 bios ROM loaded\n"); + app_data.vpp = 0; + app_data.bios = ROM_O2; + } else if (crc==0xE20A9F41) { + printf("Videopac+ G7400 bios ROM loaded\n"); + app_data.vpp = 1; + app_data.bios = ROM_G7400; + } else if (crc==0xA318E8D6) { + if (!((!o2flag)&&(c52flag))) printf("C52 bios ROM loaded\n"); else printf("Ok\n"); + app_data.vpp = 0; + app_data.bios = ROM_C52; + + } else if (crc==0x11647CA5) { + if (g74flag) printf("Jopac bios ROM loaded\n"); else printf(" Ok\n"); + app_data.vpp = 1; + app_data.bios = ROM_JOPAC; + } else { + printf("Bios ROM loaded (unknown version)\n"); + app_data.vpp = 0; + app_data.bios = ROM_UNKNOWN; + } +} +/****************************************************/ +static void load_cart(char *file){ + FILE *fn; + long l; + int i, nb; + + app_data.crc = crc32_file(file); + if (app_data.crc == 0xAFB23F89) app_data.exrom = 1; /* Musician */ + if (app_data.crc == 0x3BFEF56B) app_data.exrom = 1; /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) app_data.exrom = 1; /* Four in 1 Row! (french) */ + + if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) && (!app_data.debug)) { + fprintf(stderr,"Error: file %s is an incomplete ROM dump\n",file_v); + exit(EXIT_FAILURE); + } + + fn=fopen(file,"rb"); + if (!fn) { + fprintf(stderr,"Error loading %s\n",file_v); + exit(EXIT_FAILURE); + } + printf("Loading: \"%s\" Size: ",file_v); + l = filesize(fn); + + if ((l % 1024) != 0) { + fprintf(stderr,"Error: file %s is an invalid ROM dump\n",file_v); + exit(EXIT_FAILURE); + } + + /* special MegaCART design by Soeren Gust */ + if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144) || (l == 524288) || (l == 1048576)) { + app_data.megaxrom = 1; + app_data.bank = 1; + megarom = malloc(1048576); + if (megarom == NULL) { + fprintf(stderr, "Out of memory loading %s\n", file); + exit(EXIT_FAILURE); + } + if (fread(megarom, l, 1, fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + + /* mirror shorter files into full megabyte */ + if (l < 65536) memcpy(megarom+32768,megarom,32768); + if (l < 131072) memcpy(megarom+65536,megarom,65536); + if (l < 262144) memcpy(megarom+131072,megarom,131072); + if (l < 524288) memcpy(megarom+262144,megarom,262144); + if (l < 1048576) memcpy(megarom+524288,megarom,524288); + /* start in bank 0xff */ + memcpy(&rom_table[0][1024], megarom + 4096*255 + 1024, 3072); + printf("MegaCart %ldK", l / 1024); + nb = 1; + } else if (((l % 3072) == 0)) + { + app_data.three_k = 1; + nb = l/3072; + + for (i=nb-1; i>=0; i--) { + if (fread(&rom_table[i][1024],3072,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + } + printf("%dK",nb*3); + + } else { + + nb = l/2048; + + if ((nb == 2) && (app_data.exrom)) { + + if (fread(&extROM[0], 1024,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + if (fread(&rom_table[0][1024],3072,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + printf("3K EXROM"); + + } else { + + for (i=nb-1; i>=0; i--) { + if (fread(&rom_table[i][1024],2048,1,fn) != 1) { + fprintf(stderr,"Error loading %s\n",file); + exit(EXIT_FAILURE); + } + memcpy(&rom_table[i][3072],&rom_table[i][2048],1024); /* simulate missing A10 */ + } + printf("%dK",nb*2); + + } + } + fclose(fn); + rom = rom_table[0]; + if (nb==1) + app_data.bank = 1; + else if (nb==2) + app_data.bank = app_data.exrom ? 1 : 2; + else if (nb==4) + app_data.bank = 3; + else + app_data.bank = 4; + + if ((rom_table[nb-1][1024+12]=='O') && (rom_table[nb-1][1024+13]=='P') && (rom_table[nb-1][1024+14]=='N') && (rom_table[nb-1][1024+15]=='B')) app_data.openb=1; + + printf(" CRC: %08lX\n",app_data.crc); +} +/*************************** Helpus*/ +void helpus(void){ +#ifndef __LIBRETRO__ +allegro_init(); +install_timer(); +#endif +printf("here helpus\n"); +init_display(); +printf("here after init disp\n"); +init_system(); +#ifdef ALLEGRO_WINDOWS +FreeConsole(); +#endif +help(); +exit(EXIT_SUCCESS); +} +/*********************Open the directory `pathxŽ*/ +int file_name(char *pathx) +{ + DIR *dir_p; + struct dirent *dir_entry_p; + contax=0; + dir_p = opendir(pathx); + + if (dir_p == NULL) { fprintf(stderr,"dir '%s' not found !\n", pathx); exit(-1); } +while(0 != (dir_entry_p = readdir(dir_p))) + { +#ifndef __LIBRETRO__ + strcpy(arkivo[contax], dir_entry_p->d_name); +#else + sprintf(arkivo[contax],"%s\0",dir_entry_p->d_name); +#endif + contax++; + } + closedir(dir_p); + return(0); +} +/********************* Search BIOS */ +int suck_bios() +{ + int i; + for (i=0; ia=-le(Yxo;x+3Iho zVS>vs|IWRwKF9TF`dQ&u%mSgZ=ML(hniW2Q8LT%UU;e?lw?CO61~D*1gzl0p`~C5v z(c|jF^^DqfMG%QMw)_E07v;aRTQ4%}2!4LtEc28G7mvv4FO#liofBygg literal 0 HcmV?d00001 diff --git a/src/score.c b/src/score.c new file mode 100755 index 0000000..72ea97a --- /dev/null +++ b/src/score.c @@ -0,0 +1,152 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * + * http://o2em.sourceforge.net + * + * + * + * Score loading/saving by manopac + */ + +#include +#include +#include +#include +#include +#include +#include "vmachine.h" +#include "types.h" +#include "score.h" + +#ifdef __LIBRETRO__ +#include +#endif + +/*-------------------------------------------------- + Calculate Score from given Values + Scoretype = abcd: + ramtype a = 1: ext ram / 2: int ram + valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit + directíon c = 1: higher value digits first / 2: low value digits first + count d = number of digits + --------------------------------------------------*/ +int get_score(int scoretype, int scoreaddress) +{ + int score=0; + + if (scoretype!=0) + { + int position; + int i; + Byte *RAM; + + int count = scoretype%10; + int direction = ((scoretype/10)%10)==1?1:-1; + float valuetype = (float) (3-((scoretype/100)%10))/2; + int ramtype = scoretype/1000; + + position = scoreaddress+ (direction==1?0:(count*valuetype-1)); + RAM = ramtype==1?extRAM:intRAM; + + for(i=0;i>(((i+1)%2)*4)*(abs((int) ((valuetype-1)*2))))&15); + } + } + + return(score); +} + +/*-------------------------------------------------- + Set HighScore into Memory + Scoretype = abcd: + ramtype a = 1: ext ram / 2: int ram + valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit + directíon c = 1: higher value digits first / 2: low value digits first + count d = number of digits + --------------------------------------------------*/ + +void set_score(int scoretype, int scoreaddress, int score) +{ + + if (scoretype!=0 && score>0) + { + int position; + int i; + Byte *RAM; + int digit; + + int count = scoretype%10; + int direction = ((scoretype/10)%10)==1?-1:1; + float valuetype = (float) (3-((scoretype/100)%10))/2; + int ramtype = scoretype/1000; + + position = scoreaddress+ (direction==1?0:(count*valuetype-1)); + RAM = ramtype==1?extRAM:intRAM; + + for(i=count-1;i>=0;i--) + { + digit = score / power(10,i); + RAM[position+(int)(valuetype*i*direction)]=((valuetype==0.5)&&(i%2==0))?(RAM[position+(int)(valuetype*i*direction)]<<4)+digit:digit; + score = score - digit*power(10,i); + } + } +} + + + +/*----------------------------------------------------- + Save Highscore to File +-------------------------------------------------------*/ +void save_highscore(int highscore,char *scorefile) +{ + FILE *fn; + + highscore = highscore==app_data.default_highscore?0:highscore; + + fn = fopen(scorefile,"w"); + if (fn==NULL) { + fprintf(stderr,"Error opening highscore-file %s: %i\n",scorefile,errno); + exit(EXIT_FAILURE); + } + + if (fprintf(fn,"%i",highscore)<=0) + { + fprintf(stderr,"Error writing to highscore-file %s: %i\n",scorefile,errno); + exit(EXIT_FAILURE); + } + + fclose(fn); +} + + +/*********************************** + Integer-Implementation of pow + ***********************************/ +int power(int base, int higher) +{ + if (higher==0) + { + return(1); + } + else if (higher==1) + { + return(base); + } + else + { + int i; + int value=base; + + for (i=2;i<=higher;i++) + { + value = value*base; + } + return(value); + } +} diff --git a/src/score.h b/src/score.h new file mode 100755 index 0000000..14351ef --- /dev/null +++ b/src/score.h @@ -0,0 +1,10 @@ +#ifndef __SCORE_H +#define __SCORE_H + +int get_score(int scoretype, int scoreaddress); +void set_score(int scoretype, int scoreaddress, int highscore); +void save_highscore(int highscore,char *scorefile); +int power(int base, int higher); + +#endif + diff --git a/src/system.c b/src/system.c new file mode 100755 index 0000000..f6b0b91 --- /dev/null +++ b/src/system.c @@ -0,0 +1,501 @@ +/****************************************************************************** + + driver.c + + The list of all available drivers. Drivers have to be included here to be + recognized by the executable. + + To save some typing, we use a hack here. This file is recursively #included + twice, with different definitions of the DRIVER() macro. The first one + declares external references to the drivers; the second one builds an array + storing all the drivers. + +******************************************************************************/ + +#include "driver.h" + + +#ifndef DRIVER_RECURSIVE + +/* The "root" driver, defined so we can have &driver_##NAME in macros. */ +struct GameDriver driver_0 = +{ + __FILE__, + 0, + "root", + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + NOT_A_DRIVER, +}; + +#endif + +#ifdef TINY_COMPILE +extern struct GameDriver TINY_NAME; + +const struct GameDriver *drivers[] = +{ + &TINY_NAME, + 0 /* end of array */ +}; + +#else + +#ifndef DRIVER_RECURSIVE + +#define DRIVER_RECURSIVE + +/* step 1: declare all external references */ +#define DRIVER(NAME) extern struct GameDriver driver_##NAME; +#define TESTDRIVER(NAME) extern struct GameDriver driver_##NAME; +#include "system.c" + +/* step 2: define the drivers[] array */ +#undef DRIVER +#undef TESTDRIVER +#define DRIVER(NAME) &driver_##NAME, +#if 0 +//#ifdef DEBUG +#define TESTDRIVER(NAME) &driver_##NAME, +#else +#define TESTDRIVER(NAME) +#endif +const struct GameDriver *drivers[] = +{ +#include "system.c" + 0 /* end of array */ +}; + +#else /* DRIVER_RECURSIVE */ + +#ifndef NEOMAME + +/****************CONSOLES****************************************************/ + +/* + pong games + first done in discret logic + later pong in a chip by several firms (atari, ge, ...) + + ay-3-8500-7 6(7) games in this chip + nothing known about its internal design + */ + + /* ATARI */ + DRIVER( a2600 ) /* Atari 2600 */ + DRIVER( a5200 ) /* Atari 5200 */ + DRIVER( a7800 ) /* Atari 7800 */ +/* DRIVER( jaguar )*/ /* Atari Jaguar */ +/* DRIVER( lynx )*/ /* Atari Lynx Handheld */ +//!!TESTDRIVER( atarist ) + /* BALLY */ + DRIVER( astrocde ) /* Bally Astrocade */ + + /* RCA */ + DRIVER( studio2 ) /* Studio II */ +/* DRIVER( cstudio2 )*//* Colour Studio II */ + + /* FAIRCHILD */ + DRIVER( channelf ) /* Fairchild Channel F VES - 1976 */ + + /* COLECO */ + DRIVER( coleco ) /* ColecoVision (Original BIOS ) */ +#if 0 /* Please dont include these next 2 in a distribution, they are Hacks */ + DRIVER( colecofb ) /* ColecoVision (Fast BIOS load) */ + DRIVER( coleconb ) /* ColecoVision (No BIOS load) */ +#endif + + /* NINTENDO */ + DRIVER( nes ) /* Nintendo Entertainment System */ + DRIVER( nespal ) /* Nintendo Entertainment System */ + DRIVER( famicom ) + DRIVER( gameboy ) /* Nintendo GameBoy Handheld */ + DRIVER (snes) /* Nintendo Super Nintendo */ +/* DRIVER (vboy) */ /* Nintendo Virtual Boy */ + + /* NEC */ + DRIVER( pce ) /* PC/Engine - Turbo Graphics-16 NEC 1989-1993 */ + + /* SEGA */ + DRIVER( gamegear ) /* Sega Game Gear Handheld */ + DRIVER( sms ) /* Sega Sega Master System */ + DRIVER( genesis ) /* Sega Genesis/MegaDrive */ + DRIVER( saturn ) /* Sega Saturn */ + + /* GCE */ + DRIVER( vectrex ) /* General Consumer Electric Vectrex - 1982-1984 */ + /* (aka Milton-Bradley Vectrex) */ + DRIVER( raaspec ) /* RA+A Spectrum - Modified Vectrex */ + + /* ENTEX */ + DRIVER( advision ) /* Adventurevision */ + + /* Magnavox */ +/* DRIVER( odyssey )*/ /* Magnavox Odyssey - analogue (1972) */ +TESTDRIVER( odyssey2 ) /* Magnavox Odyssey 2 - 1978-1983 */ + +/* DRIVER( arcadia )*/ /* Arcadia 2001 */ + +/* DRIVER( intv )*/ /* Mattel Intellivision - 1979 AKA INTV */ + + /* CAPCOM */ + DRIVER( sfzch ) /* CPS Changer (Street Fighter ZERO) */ + +/****************COMPUTERS****************************************************/ + + /* APPLE */ +/* + * CPU Model Month Year + * ------------- ----- ---- + * + * Apple I July 1976 + * Apple II April 1977 + * Apple II Plus June 1979 + * Apple III May 1980 + * Apple IIe January 1983 + * Apple III Plus December 1983 + * Apple IIe Enhanced March 1985 + * Apple IIc April 1984 + * Apple IIc ROM 0 ? 1985 + * Apple IIc ROM 3 September 1986 + * Apple IIgs September 1986 + * Apple IIe Platinum January 1987 + * Apple IIgs ROM 01 September 1987 + * Apple IIc ROM 4 ? 198? + * Apple IIc Plus September 1988 + * Apple IIgs ROM 3 August 1989 + */ + DRIVER( apple1 ) /* 1976 Apple 1 */ + DRIVER( apple2c ) /* 1984 Apple //c */ + DRIVER( apple2c0 ) /* 1986 Apple //c (3.5 ROM) */ + DRIVER( apple2cp ) /* 1988 Apple //c+ */ + DRIVER( apple2e ) /* 1983 Apple //e */ + DRIVER( apple2ee ) /* 1985 Apple //e Enhanced */ + DRIVER( apple2ep ) /* 1987 Apple //e Platinum */ + + DRIVER( lisa2 ) /* */ + +/* DRIVER( mac512k )*/ /* 1984 Apple Macintosh 512k */ + DRIVER( mac512ke ) /* 1986 Apple Macintosh 512ke */ + DRIVER( macplus ) /* 1986 Apple Macintosh Plus */ +/* DRIVER( mac2 )*/ /* 1987 Apple Macintosh II */ + + /* ATARI */ + DRIVER( a400 ) /* 1979 Atari 400 */ + DRIVER( a400pal ) /* 1979 Atari 400 PAL */ + DRIVER( a800 ) /* 1979 Atari 800 */ + DRIVER( a800pal ) /* 1979 Atari 800 PAL */ + DRIVER( a800xl ) /* 1983 Atari 800 XL */ + +/* DRIVER( atarist )*/ /* Atari ST */ + +#ifndef MESS_EXCLUDE_CBM + /* COMMODORE */ + DRIVER( kim1 ) /* Commodore (MOS) KIM-1 1975 */ +/* DRIVER( sym1 )*/ /* Synertek SYM1 */ +/* DRIVER( aim65 )*/ /* Rockwell AIM65 */ + + DRIVER( pet ) /* PET2001/CBM20xx Series (Basic 1) */ + DRIVER( cbm30 ) /* Commodore 30xx (Basic 2) */ + DRIVER( cbm30b ) /* Commodore 30xx (Basic 2) (business keyboard) */ + DRIVER( cbm40 ) /* Commodore 40xx FAT (CRTC) 60Hz */ + DRIVER( cbm40pal ) /* Commodore 40xx FAT (CRTC) 50Hz */ + DRIVER( cbm40b ) /* Commodore 40xx THIN (business keyboard) */ + DRIVER( cbm80 ) /* Commodore 80xx 60Hz */ + DRIVER( cbm80pal ) /* Commodore 80xx 50Hz */ + DRIVER( cbm80ger ) /* Commodore 80xx German (50Hz) */ + DRIVER( cbm80swe ) /* Commodore 80xx Swedish (50Hz) */ + DRIVER( superpet ) /* Commodore SP9000/MMF9000 (50Hz) */ + + DRIVER( vic20 ) /* Commodore Vic-20 NTSC */ +/* DRIVER( vic1001 )*/ /* Commodore VIC-1001 (VIC20 Japan) */ + DRIVER( vc20 ) /* Commodore Vic-20 PAL */ + DRIVER( vic20swe ) /* Commodore Vic-20 Sweden */ + DRIVER( vic20i ) /* Commodore Vic-20 IEEE488 Interface */ + + DRIVER( max ) /* Max (Japan)/Ultimax (US)/VC10 (German) */ + DRIVER( c64 ) /* Commodore 64 - NTSC */ +/* DRIVER( j64 )*/ /* Commodore 64 - NTSC (Japan) */ + DRIVER( c64pal ) /* Commodore 64 - PAL */ + DRIVER( vic64s ) /* Commodore VIC64S (Swedish) */ + DRIVER( cbm4064 ) /* Commodore CBM4064 */ +TESTDRIVER( sx64 ) /* Commodore SX 64 - PAL */ +/* DRIVER( vip64 )*/ /* Commodore VIP64 (SX64, PAL, Swedish) */ + DRIVER( c64gs ) /* Commodore 64 Games System */ + + DRIVER( cbm500 ) /* Commodore 500/P128-40 */ + DRIVER( cbm610 ) /* Commodore 610/B128LP */ + DRIVER( cbm620 ) /* Commodore 620/B256LP */ +/* DRIVER( cbm630 )*/ /* Commodore 630 */ + DRIVER( cbm710 ) /* Commodore 710/B128HP */ + DRIVER( cbm720 ) /* Commodore 620/B256HP */ +/* DRIVER( cbm730 )*/ /* Commodore 730 */ + + DRIVER( c16 ) /* Commodore 16 */ + DRIVER( c16hun ) /* Commodore 16 Hungarian Character Set Hack */ + DRIVER( c16c ) /* Commodore 16 c1551 */ +TESTDRIVER( c16v ) /* Commodore 16 vc1541 */ + DRIVER( plus4 ) /* Commodore +4 c1551 */ + DRIVER( plus4c ) /* Commodore +4 vc1541 */ +TESTDRIVER( plus4v ) /* Commodore +4 */ + DRIVER( c364 ) /* Commodore 364 - Prototype */ + + DRIVER( c128 ) /* Commodore 128 - NTSC */ + DRIVER( c128ger ) /* Commodore 128 - PAL (german) */ + DRIVER( c128fra ) /* Commodore 128 - PAL (french) */ + DRIVER( c128ita ) /* Commodore 128 - PAL (italian) */ + +/* DRIVER( cbm900 )*/ /* Commodore 900 Prototype */ + +//!! DRIVER( amiga ) /* Commodore Amiga */ + + DRIVER( c65 ) /* C65 / C64DX (Prototype, NTSC, 911001) */ + DRIVER( c65e ) /* C65 / C64DX (Prototype, NTSC, 910828) */ + DRIVER( c65d ) /* C65 / C64DX (Prototype, NTSC, 910626) */ + DRIVER( c65c ) /* C65 / C64DX (Prototype, NTSC, 910523) */ + DRIVER( c65ger ) /* C65 / C64DX (Prototype, German PAL, 910429) */ + DRIVER( c65a ) /* C65 / C64DX (Prototype, NTSC, 910111) */ + +#endif + +#ifndef MESS_EXCLUDE_AMSTRAD + DRIVER( cpc464 ) /* Amstrad (Schneider in Germany) 1984 */ + DRIVER( cpc664 ) /* Amstrad (Schneider in Germany) 1985 */ + DRIVER( cpc6128 ) /* Amstrad (Schneider in Germany) 1985 */ +/* DRIVER( cpc464p )*/ /* Amstrad CPC464 Plus - 1987 */ +/* DRIVER( cpc6128p )*//* Amstrad CPC6128 Plus - 1987 */ + + DRIVER( pcw8256 ) /* 198? PCW8256 */ + DRIVER( pcw8512 ) /* 198? PCW8512 */ + DRIVER( pcw9256 ) /* 198? PCW9256 */ + DRIVER( pcw9512 ) /* 198? PCW9512 (+) */ + DRIVER( pcw10 ) /* 198? PCW10 */ + + DRIVER( pcw16 ) /* 1995 PCW16 */ + + DRIVER( nc100 ) /* 19?? NC100 */ + DRIVER( nc200 ) /* 19?? NC200 */ +#endif +#ifndef MESS_EXCLUDE_ACORN +TESTDRIVER( z88 ) /* */ +TESTDRIVER( avigo ) /* */ +#endif +#ifndef MESS_EXCLUDE_AMSTRAD + /* VEB MIKROELEKTRONIK */ + DRIVER( kccomp ) /* KC compact */ + DRIVER( kc85_4 ) /* KC 85/4 */ +#endif + + /* CANTAB */ + DRIVER( jupiter ) /* Jupiter Ace */ + + /* INTELLIGENT SOFTWARE */ + DRIVER( ep128 ) /* Enterprise 128 k */ + DRIVER( ep128a ) /* Enterprise 128 k */ + + /* NON LINEAR SYSTEMS */ + DRIVER( kaypro ) /* Kaypro 2X */ + + /* MICROBEE SYSTEMS */ + DRIVER( mbee ) /* Microbee */ + DRIVER( mbee56k ) /* Microbee 56K (CP/M) */ + + /* TANDY RADIO SHACK */ + DRIVER( trs80l1 ) /* TRS-80 Model I - Radio Shack Level I BASIC */ + DRIVER( trs80 ) /* TRS-80 Model I - Radio Shack Level II BASIC */ + DRIVER( trs80alt ) /* TRS-80 Model I - R/S L2 BASIC */ +/* DRIVER( trs80m2 )*/ /* TRS-80 Model II - */ +TESTDRIVER( trs80m3 ) /* TRS-80 Model III - Radio Shack/Tandy */ + + DRIVER( coco ) /* Color Computer */ +/* DRIVER( coco2 )*/ /* Color Computer 2 */ + DRIVER( coco3 ) /* Color Computer 3 */ + DRIVER( coco3h ) /* Hacked Color Computer 3 (6309) */ + DRIVER( cp400 ) /* Prologica CP400 */ + DRIVER( mc10 ) /* MC-10 */ + + /* DRAGON DATA LTD */ + DRIVER( dragon32 ) /* Dragon32 */ + + /* EACA */ + DRIVER( cgenie ) /* Colour Genie */ + DRIVER( sys80 ) /* System 80 */ + + /* VIDEO TECHNOLOGY */ + DRIVER( laser110 ) /* 1983 Laser 110 */ + DRIVER( laser200 ) /* 1983 Laser 200 */ + DRIVER( laser210 ) /* 1983 Laser 210 (indentical to Laser 200 ?) */ + DRIVER( laser310 ) /* 1983 Laser 310 (210 with diff. keyboard and RAM) */ + DRIVER( vz200 ) /* 1983 Dick Smith Electronics / Sanyo VZ200 */ + DRIVER( vz300 ) /* 1983 Dick Smith Electronics / Sanyo VZ300 */ + DRIVER( fellow ) /* 1983 Salora Fellow (Finland) */ + DRIVER( tx8000 ) /* 1983 Texet TX-8000 (U.K.) */ + DRIVER( laser350 ) /* 1984? Laser 350 */ + DRIVER( laser500 ) /* 1984? Laser 500 */ + DRIVER( laser700 ) /* 1984? Laser 700 */ + + /* TANGERINE */ + DRIVER( microtan ) /* 1979 Microtan 65 */ + DRIVER( oric1 ) /* 1983 Oric 1 */ + DRIVER( orica ) /* 1984 Oric Atmos */ +TESTDRIVER( telestrat ) /* ??? Oric Telestrat/Stratos */ + /* TEXAS INSTRUMENTS */ +TESTDRIVER( ti990_4 ) /* 197? TI 990/4 */ +TESTDRIVER( ti99_224 ) /* 1983 TI 99/2 */ +TESTDRIVER( ti99_232 ) /* 1983 TI 99/2 */ + DRIVER( ti99_4 ) /* 1978 TI 99/4 */ + DRIVER( ti99_4e ) /* 1980 TI 99/4E */ + DRIVER( ti99_4a ) /* 1981 TI 99/4A */ + DRIVER( ti99_4ae ) /* 1981 TI 99/4AE */ + +#ifndef MESS_EXCLUDE_IBMPC + /* IBM & Clones */ + DRIVER( pc ) /* 1982 PC */ + DRIVER( pcmda ) /* 1983 PC/XT with MDA (MGA aka Hercules) */ + DRIVER( pccga ) /* 1983 PC/XT with CGA */ + + DRIVER( t1000hx ) /* 1987 Tandy 1000HX (similiar to PCJr) */ + + DRIVER( pc1512 ) /* 1986 Amstrad PC1512 (XT, CGA compatible) */ + DRIVER( pc1640 ) /* 1987 Amstrad PC1640 (XT, EGA compatible) */ + +TESTDRIVER( xtcga ) /* 1983 PC-XT (CGA, MF2 Keyboard) */ + DRIVER( xtvga ) /* 198? PC-XT (VGA, MF2 Keyboard) */ + + DRIVER( atcga ) /* 1984 PC-AT (CGA, MF2 Keyboard) */ +TESTDRIVER( atvga ) /* */ +#endif + + /* PHILIPS */ + DRIVER( p2000t ) /* 1980 P2000T */ + DRIVER( p2000m ) /* 1980 P2000M */ + + /* COMPUKIT */ + DRIVER( uk101 ) /* 1979 UK101 */ + + /* OHIO SCIENTIFIC */ + DRIVER( superbrd ) /* 1979 Superboard II */ + +#ifndef MESS_EXCLUDE_SINCLAIR + /* SINCLAIR */ + DRIVER( zx80 ) /* Sinclair ZX-80 */ + DRIVER( zx81 ) /* Sinclair ZX-81 */ + DRIVER( ts1000 ) /* Timex Sinclair 1000 */ + DRIVER( aszmic ) /* ASZMIC ZX-81 ROM swap */ + DRIVER( pc8300 ) /* Your Computer - PC8300 */ + DRIVER( pow3000 ) /* Creon Enterprises - Power 3000 */ + + DRIVER( spectrum ) /* 1982 ZX Spectrum */ + DRIVER( specpls4 ) /* 2000 ZX Spectrum +4 */ + DRIVER( specbusy ) /* 1994 ZX Spectrum (BusySoft Upgrade) */ + DRIVER( specgrot ) /* ???? ZX Spectrum (De Groot's Upgrade) */ + DRIVER( specimc ) /* 1985 ZX Spectrum (Collier's Upgrade) */ + DRIVER( speclec ) /* 1987 ZX Spectrum (LEC Upgrade) */ + DRIVER( inves ) /* 1986 Inves Spectrum 48K+ */ + DRIVER( tk90x ) /* 1985 TK90x Color Computer */ + DRIVER( tk95 ) /* 1986 TK95 Color Computer */ + DRIVER( tc2048 ) /* 198? TC2048 */ + DRIVER( ts2068 ) /* 1983 TS2068 */ + + DRIVER( spec128 ) /* 1986 ZX Spectrum 128" */ + DRIVER( spec128s ) /* 1985 ZX Spectrum 128 (Spain) */ + DRIVER( specpls2 ) /* 1986 ZX Spectrum +2 */ + DRIVER( specpl2a ) /* 1987 ZX Spectrum +2a */ + DRIVER( specpls3 ) /* 1987 ZX Spectrum +3 */ + + DRIVER( specp2fr ) /* 1986 ZX Spectrum +2 (France) */ + DRIVER( specp2sp ) /* 1986 ZX Spectrum +2 (Spain) */ + DRIVER( specp3sp ) /* 1987 ZX Spectrum +3 (Spain) */ + DRIVER( specpl3e ) /* 2000 ZX Spectrum +3e */ +#endif + + /* ASCII & MICROSOFT */ + DRIVER( msx ) /* 1983 MSX */ + DRIVER( msxj ) /* 1983 MSX Jap */ + DRIVER( msxkr ) /* 1983 MSX Korean */ + DRIVER( msxuk ) /* 1983 MSX UK */ + + /* NASCOM MICROCOMPUTERS */ + DRIVER( nascom1 ) /* 1978 Nascom 1 */ + DRIVER( nascom2 ) /* 1979 Nascom 2 */ + + /* ACORN */ +#ifndef MESS_EXCLUDE_ACORN + DRIVER( atom ) /* 1979 Acorn Atom */ + DRIVER( bbca ) /* 1981 BBC Micro */ + DRIVER( bbcb ) /* 1981 BBC Micro */ +TESTDRIVER( a310 ) /* 1988 Acorn Archimedes 310 */ +#endif + + /* MILES GORDON TECHNOLOGY */ + DRIVER( coupe ) /* 1989 Sam Coupe 256K RAM */ + DRIVER( coupe512 ) /* 1989 Sam Coupe 512K RAM */ + +#ifndef MESS_EXCLUDE_SHARP + /* SHARP */ + DRIVER( pc1251 ) /* Pocket Computer 1251 */ + DRIVER( pc1401 ) /* Pocket Computer 1401 */ + DRIVER( pc1402 ) /* Pocket Computer 1402 */ + DRIVER( pc1350 ) /* Pocket Computer 1350 */ + + DRIVER( mz700 ) /* 1982 Sharp MZ700 */ + DRIVER( mz700j ) /* 1982 Sharp MZ700 Japan */ +TESTDRIVER( mz800 ) /* 1982 Sharp MZ800 */ + +/* DRIVER( x68000 )*/ /* X68000 */ +#endif + + /* MOTOROLA */ +TESTDRIVER( mekd2 ) /* 1977 Motorola Evaluation Kit */ + + /* DEC */ + DRIVER( pdp1 ) /* 1962 DEC PDP1 for SPACEWAR! - 1962 */ + + /* MEMOTECH */ + DRIVER( mtx512 ) /* 1983 Memotech MTX512 */ + + /* MATTEL */ +TESTDRIVER( intvkbd ) /* 1981 - Mattel Intellivision Keyboard Component */ + /* (Test marketed, later recalled ) */ + DRIVER( aquarius ) /* 1983 Aquarius */ + + /* Team Concepts */ + /* CPU not known, else should be easy, look into systems/comquest.c */ +TESTDRIVER( comquest ) /* Comquest Plus German */ + + +/****************OTHERS******************************************************/ + +#if 0 + /* Hewlett Packard */ + DRIVER( hp48s ) /* HP48 S/SX */ + DRIVER( hp48g ) /* HP48 G/GX */ +#endif + +/****************Games*******************************************************/ + + /* The Ideal Game Corp. */ + /* distributed by ARXON in Germany/Austria */ + /* PIC1655A (NMOS, not CMOS 16C55) dumping problems */ +/* DRIVER( maniac )*/ /* Maniac */ + + /* Quelle International */ +TESTDRIVER( mk1 ) /* Chess Champion MK I */ +TESTDRIVER( mk2 ) /* Chess Champion MK II */ + + /* tchibo */ + /* single chip with ram, rom, io without label, how to dump? */ +/* DRIVER( partner3)*/ /* Chess Partner 3 - Kasparov */ + +#endif /* NEOMAME */ + +#endif /* DRIVER_RECURSIVE */ + +#endif /* TINY_COMPILE */ + diff --git a/src/table.c b/src/table.c new file mode 100755 index 0000000..904b969 --- /dev/null +++ b/src/table.c @@ -0,0 +1,341 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * 8048 Mnemonics + */ + + +#include "cpu.h" +#include "table.h" + + +struct lookup_tag lookup[] = { + + /* 00 */ {"NOP",1,0}, + /* 01 */ {"ILL",1,0}, + /* 02 */ {"OUTL BUS,A",1,0}, + /* 03 */ {"ADD A,",2,1}, + + /* 04 */ {"JMP",2,2}, + /* 05 */ {"EN I",1,0}, + /* 06 */ {"ILL",1,0}, + /* 07 */ {"DEC A",1,0}, + + /* 08 */ {"INS A,BUS",1,0}, + /* 09 */ {"IN A,P1",1,0}, + /* 0A */ {"IN A,P2",1,0}, + /* 0B */ {"ILL",1,0}, + + /* 0C */ {"MOVD A,P4",1,0}, + /* 0D */ {"MOVD A,P5",1,0}, + /* 0E */ {"MOVD A,P6",1,0}, + /* 0F */ {"MOVD A,P7",1,0}, + + /* 10 */ {"INC @R0",1,0}, + /* 11 */ {"INC @R1",1,0}, + /* 12 */ {"JB0",2,3}, + /* 13 */ {"ADDC A,",2,1}, + + /* 14 */ {"CALL",2,2}, + /* 15 */ {"DIS I",1,0}, + /* 16 */ {"JTF",2,3}, + /* 17 */ {"INC A",1,0}, + + /* 18 */ {"INC R0",1,0}, + /* 19 */ {"INC R1",1,0}, + /* 1A */ {"INC R2",1,0}, + /* 1B */ {"INC R3",1,0}, + + /* 1C */ {"INC R4",1,0}, + /* 1D */ {"INC R5",1,0}, + /* 1E */ {"INC R6",1,0}, + /* 1F */ {"INC R7",1,0}, + + /* 20 */ {"XCH A,@R0",1,0}, + /* 21 */ {"XCH A,@R1",1,0}, + /* 22 */ {"ILL",1,0}, + /* 23 */ {"MOV A,",2,1}, + + /* 24 */ {"JMP",2,2}, + /* 25 */ {"EN TCNTI",1,0}, + /* 26 */ {"JNT0",2,3}, + /* 27 */ {"CLR A",1,0}, + + /* 28 */ {"XCH A,R0",1,0}, + /* 29 */ {"XCH A,R1",1,0}, + /* 2A */ {"XCH A,R2",1,0}, + /* 2B */ {"XCH A,R3",1,0}, + + /* 2C */ {"XCH A,R4",1,0}, + /* 2D */ {"XCH A,R5",1,0}, + /* 2E */ {"XCH A,R6",1,0}, + /* 2F */ {"XCH A,R7",1,0}, + + /* 30 */ {"XCHD A,@R0",1,0}, + /* 31 */ {"XCHD A,@R1",1,0}, + /* 32 */ {"JB1",2,3}, + /* 33 */ {"ILL",1,0}, + + /* 34 */ {"CALL",2,2}, + /* 35 */ {"DIS TCNTI",1,0}, + /* 36 */ {"JT0",2,3}, + /* 37 */ {"CPL A",1,0}, + + /* 38 */ {"ILL",1,0}, + /* 39 */ {"OUTL P1,A",1,0}, + /* 3A */ {"OUTL P2,A",1,0}, + /* 3B */ {"ILL",1,0}, + + /* 3C */ {"MOVD P4,A",1,0}, + /* 3D */ {"MOVD P5,A",1,0}, + /* 3E */ {"MOVD P6,A",1,0}, + /* 3F */ {"MOVD P7,A",1,0}, + + /* 40 */ {"ORL A,@R0",1,0}, + /* 41 */ {"ORL A,@R1",1,0}, + /* 42 */ {"MOV A,T",1,0}, + /* 43 */ {"ORL A,",2,1}, + + /* 44 */ {"JMP",2,2}, + /* 45 */ {"STRT CNT",1,0}, + /* 46 */ {"JNT1",2,3}, + /* 47 */ {"SWAP",1,0}, + + /* 48 */ {"ORL A,R0",1,0}, + /* 49 */ {"ORL A,R1",1,0}, + /* 4A */ {"ORL A,R2",1,0}, + /* 4B */ {"ORL A,R3",1,0}, + + /* 4C */ {"ORL A,R4",1,0}, + /* 4D */ {"ORL A,R5",1,0}, + /* 4E */ {"ORL A,R6",1,0}, + /* 4F */ {"ORL A,R7",1,0}, + + /* 50 */ {"ANL A,@R0",1,0}, + /* 51 */ {"ANL A,@R1",1,0}, + /* 52 */ {"JB2",2,3}, + /* 53 */ {"ANL A,",2,1}, + + /* 54 */ {"CALL",2,2}, + /* 55 */ {"STRT T",1,0}, + /* 56 */ {"JT1",2,3}, + /* 57 */ {"ILL",1,0}, + + /* 58 */ {"ANL A,R0",1,0}, + /* 59 */ {"ANL A,R1",1,0}, + /* 5A */ {"ANL A,R2",1,0}, + /* 5B */ {"ANL A,R3",1,0}, + + /* 5C */ {"ANL A,R4",1,0}, + /* 5D */ {"ANL A,R5",1,0}, + /* 5E */ {"ANL A,R6",1,0}, + /* 5F */ {"ANL A,R7",1,0}, + + /* 60 */ {"ADD A,@R0",1,0}, + /* 61 */ {"ADD A,@R1",1,0}, + /* 62 */ {"MOV T,A",1,0}, + /* 63 */ {"ILL",1,0}, + + /* 64 */ {"JMP",2,2}, + /* 65 */ {"STOP TCNT",1,0}, + /* 66 */ {"ILL",1,0}, + /* 67 */ {"RRC A",1,0}, + + /* 68 */ {"ADD A,R0",1,0}, + /* 69 */ {"ADD A,R1",1,0}, + /* 6A */ {"ADD A,R2",1,0}, + /* 6B */ {"ADD A,R3",1,0}, + + /* 6C */ {"ADD A,R4",1,0}, + /* 6D */ {"ADD A,R5",1,0}, + /* 6E */ {"ADD A,R6",1,0}, + /* 6F */ {"ADD A,R7",1,0}, + + /* 70 */ {"ADDC A,@R0",1,0}, + /* 71 */ {"ADDC A,@R1",1,0}, + /* 72 */ {"JB3",2,3}, + /* 73 */ {"ILL",1,0}, + + /* 74 */ {"CALL",2,2}, + /* 75 */ {"ENT0 CLK",1,0}, + /* 76 */ {"JF1",2,3}, + /* 77 */ {"RR A",1,0}, + + /* 78 */ {"ADDC A,R0",1,0}, + /* 79 */ {"ADDC A,R1",1,0}, + /* 7A */ {"ADDC A,R2",1,0}, + /* 7B */ {"ADDC A,R3",1,0}, + + /* 7C */ {"ADDC A,R4",1,0}, + /* 7D */ {"ADDC A,R5",1,0}, + /* 7E */ {"ADDC A,R6",1,0}, + /* 7F */ {"ADDC A,R7",1,0}, + + /* 80 */ {"MOVX A,@R0",1,0}, + /* 81 */ {"MOVX A,@R1",1,0}, + /* 82 */ {"ILL",1,0}, + /* 83 */ {"RET",1,0}, + + /* 84 */ {"JMP",2,2}, + /* 85 */ {"CLR F0",1,0}, + /* 86 */ {"JNI",2,3}, + /* 87 */ {"ILL",1,0}, + + /* 88 */ {"ORL BUS,",2,1}, + /* 89 */ {"ORL P1,",2,1}, + /* 8A */ {"ORL P2,",2,1}, + /* 8B */ {"ILL",1,0}, + + /* 8C */ {"ORLD P4,A",1,0}, + /* 8D */ {"ORLD P5,A",1,0}, + /* 8E */ {"ORLD P6,A",1,0}, + /* 8F */ {"ORLD P7,A",1,0}, + + /* 90 */ {"MOVX @R0,A",1,0}, + /* 91 */ {"MOVX @R1,A",1,0}, + /* 92 */ {"JB4",2,3}, + /* 93 */ {"RETR",1,0}, + + /* 94 */ {"CALL",2,2}, + /* 95 */ {"CPL F0",1,0}, + /* 96 */ {"JNZ",2,3}, + /* 97 */ {"CLR C",1,0}, + + /* 98 */ {"ANL BUS,",2,1}, + /* 99 */ {"ANL P1,",2,1}, + /* 9A */ {"ANL P2,",2,1}, + /* 9B */ {"ILL",1,0}, + + /* 9C */ {"ANLD P4,A",1,0}, + /* 9D */ {"ANLD P5,A",1,0}, + /* 9E */ {"ANLD P6,A",1,0}, + /* 9F */ {"ANLD P7,A",1,0}, + + /* A0 */ {"MOV @R0,A",1,0}, + /* A1 */ {"MOV @R1,A",1,0}, + /* A2 */ {"ILL",1,0}, + /* A3 */ {"MOVP A,@A",1,0}, + + /* A4 */ {"JMP",2,2}, + /* A5 */ {"CLR F1",1,0}, + /* A6 */ {"ILL",1,0}, + /* A7 */ {"CPL C",1,0}, + + /* A8 */ {"MOV R0,A",1,0}, + /* A9 */ {"MOV R1,A",1,0}, + /* AA */ {"MOV R2,A",1,0}, + /* AB */ {"MOV R3,A",1,0}, + /* AC */ {"MOV R4,A",1,0}, + /* AD */ {"MOV R5,A",1,0}, + /* AE */ {"MOV R6,A",1,0}, + /* AF */ {"MOV R7,A",1,0}, + + /* B0 */ {"MOV @R0,",2,1}, + /* B1 */ {"MOV @R1,",2,1}, + /* B2 */ {"JB5",2,3}, + /* B3 */ {"JMPP @A",1,0}, + + /* B4 */ {"CALL",2,2}, + /* B5 */ {"CPL F1",1,0}, + /* B6 */ {"JF0",2,3}, + /* B7 */ {"ILL",1,0}, + + /* B8 */ {"MOV R0,",2,1}, + /* B9 */ {"MOV R1,",2,1}, + /* BA */ {"MOV R2,",2,1}, + /* BB */ {"MOV R3,",2,1}, + + /* BC */ {"MOV R4,",2,1}, + /* BD */ {"MOV R5,",2,1}, + /* BE */ {"MOV R6,",2,1}, + /* BF */ {"MOV R7,",2,1}, + + /* C0 */ {"ILL",1,0}, + /* C1 */ {"ILL",1,0}, + /* C2 */ {"ILL",1,0}, + /* C3 */ {"ILL",1,0}, + + /* C4 */ {"JMP",2,2}, + /* C5 */ {"SEL RB0",1,0}, + /* C6 */ {"JZ",2,3}, + /* C7 */ {"MOV A,PSW",1,0}, + + /* C8 */ {"DEC R0",1,0}, + /* C9 */ {"DEC R1",1,0}, + /* CA */ {"DEC R2",1,0}, + /* CB */ {"DEC R3",1,0}, + + /* CC */ {"DEC R4",1,0}, + /* CD */ {"DEC R5",1,0}, + /* CE */ {"DEC R6",1,0}, + /* CF */ {"DEC R7",1,0}, + + /* D0 */ {"XRL A,@R0",1,0}, + /* D1 */ {"XRL A,@R1",1,0}, + /* D2 */ {"JB6",2,3}, + /* D3 */ {"XRL A,",2,1}, + + /* D4 */ {"CALL",2,2}, + /* D5 */ {"SEL RB1",1,0}, + /* D6 */ {"ILL",1,0}, + /* D7 */ {"MOV PSW,A",1,0}, + + /* D8 */ {"XRL A,R0",1,0}, + /* D9 */ {"XRL A,R1",1,0}, + /* DA */ {"XRL A,R2",1,0}, + /* DB */ {"XRL A,R3",1,0}, + /* DC */ {"XRL A,R4",1,0}, + /* DD */ {"XRL A,R5",1,0}, + /* DE */ {"XRL A,R6",1,0}, + /* DF */ {"XRL A,R7",1,0}, + + /* E0 */ {"ILL",1,0}, + /* E1 */ {"ILL",1,0}, + /* E2 */ {"ILL",1,0}, + /* E3 */ {"MOVP3 A,@A",1,0}, + + /* E4 */ {"JMP",2,2}, + /* E5 */ {"SEL MB0",1,0}, + /* E6 */ {"JNC",2,3}, + /* E7 */ {"RL A",1,0}, + + /* E8 */ {"DJNZ R0,",2,3}, + /* E9 */ {"DJNZ R1,",2,3}, + /* EA */ {"DJNZ R2,",2,3}, + /* EB */ {"DJNZ R3,",2,3}, + /* EC */ {"DJNZ R4,",2,3}, + /* ED */ {"DJNZ R5,",2,3}, + /* EE */ {"DJNZ R6,",2,3}, + /* EF */ {"DJNZ R7,",2,3}, + + /* F0 */ {"MOV A,@R0",1,0}, + /* F1 */ {"MOV A,@R1",1,0}, + /* F2 */ {"JB7",2,3}, + /* F3 */ {"ILL",1,0}, + + /* F4 */ {"CALL",2,2}, + /* F5 */ {"SEL MB1",1,0}, + /* F6 */ {"JC",2,3}, + /* F7 */ {"RLC A",1,0}, + + /* F8 */ {"MOV A,R0",1,0}, + /* F9 */ {"MOV A,R1",1,0}, + /* FA */ {"MOV A,R2",1,0}, + /* FB */ {"MOV A,R3",1,0}, + /* FC */ {"MOV A,R4",1,0}, + /* FD */ {"MOV A,R5",1,0}, + /* FE */ {"MOV A,R6",1,0}, + /* FF */ {"MOV A,R7",1,0} + +}; + diff --git a/src/table.h b/src/table.h new file mode 100755 index 0000000..7ab8a93 --- /dev/null +++ b/src/table.h @@ -0,0 +1,10 @@ +#ifndef __TABLE_H +#define __TABLE_H + +extern struct lookup_tag { + char *mnemonic; + unsigned char bytes; + unsigned char type; +} lookup[]; + +#endif diff --git a/src/timefunc.c b/src/timefunc.c new file mode 100755 index 0000000..0f0f651 --- /dev/null +++ b/src/timefunc.c @@ -0,0 +1,124 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Timing functions + */ + + +#include + +#ifndef __LIBRETRO__ +#include "allegro.h" +#endif + +#ifdef ALLEGRO_WINDOWS +#include "winalleg.h" +#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX) +#include +#include +#endif +#include "timefunc.h" + +#ifndef __LIBRETRO__ + +#ifdef ALLEGRO_WINDOWS + +/* Windows */ +long gettimeticks(void){ + LARGE_INTEGER counter, freq; + static LONG_LONG first=-1; + if (QueryPerformanceCounter(&counter)) + if (QueryPerformanceFrequency(&freq)) { + if (first<0) first = counter.QuadPart; + return (long)(((counter.QuadPart-first)*TICKSPERSEC)/freq.QuadPart); + } + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); +} + +#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX) + +#if defined(_BSD_SOURCE) || defined(FREEBSD) + +/* Unix with gettimeofday */ +long gettimeticks(void){ + struct timeval tv; + static LONG_LONG first=-1; + LONG_LONG ll; + if (first<0) { + if (gettimeofday(&tv, NULL) != 0) + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); + first = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + } + if (gettimeofday(&tv, NULL) == 0) { + ll = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + return (long) (((ll-first)*TICKSPERSEC)/1000000); + } + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); +} + +#else + +/* Unix without gettimeofday */ +long gettimeticks(void){ + struct tms t; + return (long)((((LONG_LONG)times(&t))*TICKSPERSEC)/sysconf(_SC_CLK_TCK)); +} + +#endif + +#else + +/* Default (use Allegro timers) */ + +volatile long ticks_counter = 0; +static int timer_init = 0; + +void inc_ticks_counter(void){ + ticks_counter++; +} + +END_OF_FUNCTION(inc_ticks_counter); + +long gettimeticks(void){ + if (timer_init==0) { + ticks_counter=0; + LOCK_VARIABLE(ticks_counter); + LOCK_FUNCTION(inc_ticks_counter); + install_int(inc_ticks_counter, 1); + timer_init=1; + } + return (long)(((LONG_LONG)ticks_counter*TICKSPERSEC)/1000); +} + +#endif + +#else +//RETRO +#include +#define LONG_LONG long long +long gettimeticks(void){ + struct timeval tv; + static LONG_LONG first=-1; + LONG_LONG ll; + if (first<0) { + if (gettimeofday(&tv, NULL) != 0) + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); + first = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + } + if (gettimeofday(&tv, NULL) == 0) { + ll = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec; + return (long) (((ll-first)*TICKSPERSEC)/1000000); + } + return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC); +} +#endif diff --git a/src/timefunc.h b/src/timefunc.h new file mode 100755 index 0000000..8d180e2 --- /dev/null +++ b/src/timefunc.h @@ -0,0 +1,8 @@ +#ifndef __TIMEFUNC_H +#define __TIMEFUNC_H + +#define TICKSPERSEC 10000 + +long gettimeticks(void); + +#endif diff --git a/src/types.h b/src/types.h new file mode 100755 index 0000000..e673494 --- /dev/null +++ b/src/types.h @@ -0,0 +1,8 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char Byte; +typedef unsigned short ADDRESS; +#define MAXC 1024 +#endif /* TYPES_H */ + diff --git a/src/vdc.c b/src/vdc.c new file mode 100755 index 0000000..63db617 --- /dev/null +++ b/src/vdc.c @@ -0,0 +1,882 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 Video Display Controller emulation + */ + + +#include +#include +#include +#include "types.h" +#include "vmachine.h" +#include "config.h" +#include "keyboard.h" +#include "cset.h" +#include "timefunc.h" +#include "cpu.h" +#include "vpp.h" +#include "vdc.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "libretro.h" +#include "wrapalleg.h" +#endif + +#include "audio.h" +#include "voice.h" + + +#define COL_SP0 0x01 +#define COL_SP1 0x02 +#define COL_SP2 0x04 +#define COL_SP3 0x08 +#define COL_VGRID 0x10 +#define COL_HGRID 0x20 +#define COL_VPP 0x40 +#define COL_CHAR 0x80 + +#define X_START 8 +#define Y_START 24 + +typedef APALETTE PALETTE[256]; + +static long colortable[2][16]={ + /* O2 palette */ + {0x000000, 0x0e3dd4, 0x00981b, 0x00bbd9, 0xc70008, 0xcc16b3, 0x9d8710, 0xe1dee1, + 0x5f6e6b, 0x6aa1ff, 0x3df07a, 0x31ffff, 0xff4255, 0xff98ff, 0xd9ad5d, 0xffffff}, + /* VP+ G7400 palette */ + {0x000000, 0x0000b6, 0x00b600, 0x00b6b6, 0xb60000, 0xb600b6, 0xb6b600, 0xb6b6b6, + 0x494949, 0x4949ff, 0x49ff49, 0x49ffff, 0xff4949, 0xff49ff, 0xffff49, 0xffffff} + +}; + + +/* Collision buffer */ +static Byte *col = NULL; + +static PALETTE colors,oldcol; + +/* The pointer to the graphics buffer */ +static Byte *vscreen = NULL; + +static BITMAP *bmp, *bmpcache; +static int cached_lines[MAXLINES]; + +Byte coltab[256]; + +long clip_low; +long clip_high; + +int show_fps=0; + +int wsize; + +static void create_cmap(void); +static void draw_char(Byte ypos,Byte xpos,Byte chr,Byte col); +static void draw_quad(Byte ypos, Byte xpos, Byte cp0l, Byte cp0h, Byte cp1l, Byte cp1h, Byte cp2l, Byte cp2h, Byte cp3l, Byte cp3h); +static void draw_grid(void); +INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c); + + +void draw_region(void){ + int i; + + if (regionoff == 0xffff) + i = (master_clk/(LINECNT-1)-5); + else + i = (master_clk/22+regionoff); + i = (snapline(i, VDCwrite[0xA0], 0)); + + + if (app_data.crc == 0xA7344D1F) + {i = (master_clk/22+regionoff)+6; + i = (snapline(i, VDCwrite[0xA0], 0)+6); + }/*Atlantis*/ + + if (app_data.crc == 0xD0BC4EE6) + {i = (master_clk/24+regionoff)-6; + i = (snapline(i, VDCwrite[0xA0], 0)+7); + }/*Frogger*/ + + if (app_data.crc == 0x26517E77) + {i = (master_clk/22+regionoff); + i = (snapline(i, VDCwrite[0xA0], 0)-5); + }/*Comando Noturno*/ + + if (app_data.crc == 0xA57E1724) + {i = (master_clk/(LINECNT-1)-5); + i = (snapline(i, VDCwrite[0xA0], 0)-3); + }/*Catch the ball*/ + + if (i<0) i=0; + clip_low = last_line * (long)BMPW; + clip_high = i * (long)BMPW; + if (clip_high > BMPW*BMPH) clip_high = BMPW*BMPH; + if (clip_low < 0) clip_low=0; + if (clip_low < clip_high) draw_display(); + last_line=i; + +} + +static void create_cmap(void){ + int i; + + /* Initialise parts of the colors array */ + for (i = 0; i < 16; i++) { + /* Use the color values from the color table */ + colors[i+32].r = colors[i].r = (colortable[app_data.vpp?1:0][i] & 0xff0000) >> 18; + colors[i+32].g = colors[i].g = (colortable[app_data.vpp?1:0][i] & 0x00ff00) >> 10; + colors[i+32].b = colors[i].b = (colortable[app_data.vpp?1:0][i] & 0x0000ff) >> 2; + } + + for (i = 16; i < 32; i++) { + /* Half-bright colors for the 50% scanlines */ + colors[i+32].r = colors[i].r = colors[i-16].r/2; + colors[i+32].g = colors[i].g = colors[i-16].g/2; + colors[i+32].b = colors[i].b = colors[i-16].b/2; + } + + for (i = 64; i < 256; i++) colors[i].r = colors[i].g = colors[i].b = 0; +} + +void grmode(void){ + +#ifndef __LIBRETRO__ + set_color_depth(8); + wsize = app_data.wsize; + + if (app_data.fullscreen){ + if (app_data.scanlines){ + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)){ + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) { + fprintf(stderr,"Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } + } else { + #ifdef ALLEGRO_DOS + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)){ + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)){ + fprintf(stderr,"Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } + #else + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)){ + wsize = 1; + if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)){ + fprintf(stderr,"Error: could not create screen.\n"); + exit(EXIT_FAILURE); + } + } + #endif + } + } else { + if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW*wsize, WNDH*wsize, 0, 0)){ + wsize = 2; + if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW*2, WNDH*2, 0, 0)){ + if (set_gfx_mode(GFX_AUTODETECT, WNDW*2, WNDH*2, 0, 0)){ + fprintf(stderr,"Error: could not create window.\n"); + exit(EXIT_FAILURE); + } + } + #ifndef ALLEGRO_DOS + printf("Could not set the requested window size\n"); + #endif + } + } + + if ((app_data.scanlines) && (wsize==1)) { + #ifndef ALLEGRO_DOS + printf("Could not set scanlines\n"); + #endif + } + + set_palette(colors); + set_window_title(app_data.window_title); + clearscr(); + set_display_switch_mode(SWITCH_PAUSE); +#else +wsize = 1; +clearscr(); +#endif + +} + + +void set_textmode(void){ +#ifndef __LIBRETRO__ + set_palette(oldcol); + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); +#endif + if (new_int) Set_Old_Int9(); +} + + +void clearscr(void){ +#ifndef __LIBRETRO__ + acquire_screen(); + clear(screen); + release_screen(); + clear(bmpcache); +#endif +} + + +INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c){ + if ((ad > (unsigned long)clip_low) && (ad < (unsigned long)clip_high)) { + unsigned int i; + if (((len & 3)==0) && (sizeof(unsigned long) == 4)) { + unsigned long dddd = (((unsigned long)d) & 0xff) | ((((unsigned long)d) & 0xff) << 8) | ((((unsigned long)d) & 0xff) << 16) | ((((unsigned long)d) & 0xff) << 24); + unsigned long cccc = (((unsigned long)c) & 0xff) | ((((unsigned long)c) & 0xff) << 8) | ((((unsigned long)c) & 0xff) << 16) | ((((unsigned long)c) & 0xff) << 24); + for (i=0; i>2; i++) { + *((unsigned long*)(vscreen+ad)) = dddd; + cccc |= *((unsigned long*)(col+ad)); + *((unsigned long*)(col+ad)) = cccc; + coltab[c] |= ((cccc | (cccc >> 8) | (cccc >> 16) | (cccc >> 24)) & 0xff); + ad += 4; + } + } else { + for (i=0; i> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j*24+25]; + mputvid(pn1+BMPW, 4, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j*24+26]; + mputvid(pn1+BMPW*2, 4, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + } + } + } + + mask=0x01; + for(j=0; j<9; j++) { + pnt = (((j*24)+24) * BMPW); + for (i=0; i<9; i++) { + pn1 = pnt + (i * 32) + 20; + if ((pn1+BMPW*3 >= (unsigned long)clip_low) && (pn1 <= (unsigned long)clip_high)) { + d=VDCwrite[0xC0 + i]; + if (j == 8) { + d=VDCwrite[0xD0+i]; + mask=1; + } + if (d & mask) { + color = ColorVector[j*24+24]; + mputvid(pn1, 36, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j*24+25]; + mputvid(pn1+BMPW, 36, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + color = ColorVector[j*24+26]; + mputvid(pn1+BMPW*2, 36, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID); + } + } + } + mask = mask << 1; + } + + mask=0x01; + w=4; + if (VDCwrite[0xA0] & 0x80) w=32; + for(j=0; j<10; j++) { + + pnt=(j*32); + mask=0x01; + d=VDCwrite[0xE0+j]; + for (x=0; x<8; x++) { + pn1 = pnt + (((x*24)+24) * BMPW) + 20; + if (d & mask) { + for(i=0; i<24; i++) { + if ((pn1 >= (unsigned long)clip_low) && (pn1 <= (unsigned long)clip_high)) { + color = ColorVector[x*24+24+i]; + mputvid(pn1, w, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_VGRID); + } + pn1+=BMPW; + + } + } + mask = mask << 1; + } + } + +} + +#ifdef __LIBRETRO__ + +//extern unsigned short int mbmp[TEX_WIDTH * TEX_HEIGHT]; +extern uint16_t mbmp[TEX_WIDTH * TEX_HEIGHT]; + +void retro_blit(){ + + int i,j; + unsigned char ind; + unsigned short *outp=&mbmp[0]; + unsigned char *inp=&bmp->line[0]; + for(i=0;i<250;i++){ + for(j=0;j<340;j++){ + ind=inp[i*340 + j]; + (*outp++)= RGB565( colors[ ind].r>>1 , colors[ind].g>>1 , colors[ind].b>>1 ); + } + outp+= (TEX_WIDTH-340); + } +} + +void retro_destroybmp(){ + + destroy_bitmap(bmp); + destroy_bitmap(bmpcache); +} + +#endif + +void finish_display(void){ + int x,y,sn; + static int cache_counter=0; + + vpp_finish_bmp(vscreen, 9, 5, BMPW-9, BMPH-5, bmp->w, bmp->h); + + if (show_fps) { + static long last=-1, index=0, curr=0, t=0; + if (last<0) last=gettimeticks(); + index = (index+1)%200; + if (!index) { + t=gettimeticks(); + curr=t-last; + last=t; + } + if (curr) { +#ifndef __LIBRETRO__ + text_mode(0); + textprintf(bmp, font, 20 , 4, 7, "FPS: %3d",(int)((200.0*TICKSPERSEC)/curr+0.5)); +#endif + } + + } + + for (y=0; yh; y++){ + cached_lines[y] = !memcmp(&bmpcache->line[y*bmpcache->w], &bmp->line[y*bmp->w], bmp->w); + + if (!cached_lines[y]) memcpy(&bmpcache->line[y*bmpcache->w], &bmp->line[y*bmp->w], bmp->w); + } + + for (y=0; y<10; y++) cached_lines[(y+cache_counter) % bmp->h] = 0; + cache_counter = (cache_counter+10) % bmp->h; + +#ifndef __LIBRETRO__ + acquire_screen(); +#endif + + sn = ((wsize>1) && (app_data.scanlines)) ? 1 : 0; + + for (y=0; yw; x++) bmp->line[(y+2)*bmp->w +x] += 16; +#ifndef __LIBRETRO__ + stretch_blit(bmp,screen,7,2+y,WNDW,1,0,(y+1)*wsize-1,WNDW*wsize,1); +#else +//TODO + +#endif + memcpy(&bmp->line[(y+2)*bmp->w], &bmpcache->line[(y+2)*bmpcache->w], bmp->w); + } + } + } + + +#ifndef __LIBRETRO__ + release_screen(); +#else + retro_blit(); +#endif +} + + +void clear_collision(void){ + load_colplus(col); + coltab[0x01]=coltab[0x02]=0; + coltab[0x04]=coltab[0x08]=0; + coltab[0x10]=coltab[0x20]=0; + coltab[0x40]=coltab[0x80]=0; +} + + +void draw_display(void){ + int i,j,x,sm,t; + Byte y,b,d1,cl,c; + + unsigned int pnt,pnt2; + + + for (i=clip_low/BMPW; i> 3) | (ColorVector[i] & 0x80 ? 0 : 8), BMPW); + + if (VDCwrite[0xA0] & 0x08) draw_grid(); + + if (useforen && (!(VDCwrite[0xA0] & 0x20))) return; + + for(i=0x10; i<0x40; i+=4) draw_char(VDCwrite[i],VDCwrite[i+1],VDCwrite[i+2],VDCwrite[i+3]); + + /* draw quads, position mapping happens in ext_write (vmachine.c)*/ + for(i = 0x40; i < 0x80; i+= 0x10) + draw_quad(VDCwrite[i], VDCwrite[i+1], VDCwrite[i+2], VDCwrite[i+3], + VDCwrite[i+6], VDCwrite[i+7], + VDCwrite[i+10], VDCwrite[i+11], + VDCwrite[i+14], VDCwrite[i+15]); + + c=8; + for (i=12; i>=0; i -=4) { + pnt2 = 0x80 + (i * 2); + y = VDCwrite[i]; + x = VDCwrite[i+1]-8; + t = VDCwrite[i+2]; + cl = ((t & 0x38) >> 3); + cl = ((cl&2) | ((cl&1)<<2) | ((cl&4)>>2)) + 8; + /*174*/ + if ((x<164) && (y>0) && (y<232)) { + pnt = y * BMPW + (x * 2) + 20 + sproff; + if (t & 4) { + if ((pnt+BMPW*32 >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) { + for (j=0; j<8; j++) { + sm = (((j%2==0) && (((t>>1) & 1) != (t & 1))) || ((j%2==1) && (t & 1))) ? 1 : 0; + d1 = VDCwrite[pnt2++]; + for (b=0; b<8; b++) { + if (d1 & 0x01) { + if ((x+b+sm < 159) && (y+j < 247)) { + mputvid(sm+pnt,4,cl,c); + mputvid(sm+pnt+BMPW,4,cl,c); + mputvid(sm+pnt+2*BMPW,4,cl,c); + mputvid(sm+pnt+3*BMPW,4,cl,c); + } + } + pnt += 4; + d1 = d1 >> 1; + } + pnt += BMPW*4-32; + } + } + } else { + if ((pnt+BMPW*16 >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) { + for (j=0; j<8; j++) { + sm = (((j%2==0) && (((t>>1) & 1) != (t & 1))) || ((j%2==1) && (t & 1))) ? 1 : 0; + d1 = VDCwrite[pnt2++]; + for (b=0; b<8; b++) { + if (d1 & 0x01) { + if ((x+b+sm<160) && (y+j<249)) { + mputvid(sm+pnt,2,cl,c); + mputvid(sm+pnt+BMPW,2,cl,c); + } + } + pnt += 2; + d1 = d1 >> 1; + } + pnt += BMPW*2-16; + } + } + } + } + c = c >> 1; + } +} + + +void draw_char(Byte ypos,Byte xpos,Byte chr,Byte col){ + + int j,c; + Byte cl,d1; + int y,b,n; + unsigned int pnt; + + y=(ypos & 0xFE); + pnt = y * BMPW + ((xpos-8) * 2)+20; + + ypos = ypos >> 1; + n = 8 - (ypos % 8) - (chr % 8); + if (n < 3) n = n + 7; + + if ((pnt+BMPW*2*n >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) { + + c=(int)chr + ypos; + if (col & 0x01) c+=256; + if (c > 511) c=c-512; + + cl = ((col & 0x0E) >> 1); + cl = ((cl&2) | ((cl&1)<<2) | ((cl&4)>>2)) + 8; + + if ((y>0) && (y<232) && (xpos<157)) { + for (j=0; j (unsigned long) clip_high) return; + /* extract and convert char-set offsets */ + chp[0] = cp0l | ((cp0h & 1) << 8); + chp[1] = cp1l | ((cp1h & 1) << 8); + chp[2] = cp2l | ((cp2h & 1) << 8); + chp[3] = cp3l | ((cp3h & 1) << 8); + for(i = 0; i < 4; i++) chp[i] = (chp[i] + (ypos >> 1)) & 0x1ff; + lines = 8 - (chp[3]+1) % 8; + /* abort drawing if completely over the top clip */ + if (pnt+BMPW*2*lines < (unsigned long) clip_low) return; + /* extract and convert color information */ + col[0] = (cp0h & 0xe) >> 1; + col[1] = (cp1h & 0xe) >> 1; + col[2] = (cp2h & 0xe) >> 1; + col[3] = (cp3h & 0xe) >> 1; + for(i = 0; i < 4; i++) col[i] = ((col[i] & 2) | ((col[i] & 1) << 2) | ((col[i] & 4) >> 2)) + 8; + /* now draw the quad line by line controlled by the last quad */ + while(lines-- > 0) { + off = 0; + /* draw all 4 sub-quads */ + for(i = 0; i < 4; i++) { + /* draw sub-quad pixel by pixel, but stay in same line */ + for(j = 0; j < 8; j++) { + if((cset[chp[i]] & (1 << (7-j))) && (off < BMPW)) { + mputvid(pnt+off, 2, col[i], COL_CHAR); + mputvid(pnt+off+BMPW, 2, col[i], COL_CHAR); + } + /* next pixel */ + off += 2; + } + /* space between sub-quads */ + off += 16; + } + /* advance char-set pointers */ + for(i = 0; i < 4; i++) chp[i] = (chp[i]+1) & 0x1ff; + /* advance screen bitmap pointer */ + pnt += BMPW*2; + } +} + +void close_display(void) { +#ifndef __LIBRETRO__ + free(vscreen); +#endif + free(col); +} + + +void window_close_hook(void){ + key_debug=0; + key_done=1; +} +static void txtmsg(int x, int y, int c, const char *s){ +#ifndef __LIBRETRO__ + text_mode(-1); + textout_centre(bmp, font, s, x+1 , y+1, 32); + textout_centre(bmp, font, s, x , y, c); +#else +//TODO +#endif +} +void display_bg(void){ + rectfill(bmp,20,72,311,172,9+32); + line(bmp,20,72,311,72,15+32); + line(bmp,20,72,20,172,15+32); + line(bmp,21,172,311,172,1+32); + line(bmp,311,172,311,72,1+32); +} + +void abaut(void) +{ + char *ver; + char exitstr[80]; + + int i = 0; + while (syskeys[1]!=keybtab[i].keybcode) i++; + + strcpy (exitstr,"Press "); + strcat (exitstr,keybtab[i].keybname); + strcat (exitstr," to continue"); + + + #if defined(ALLEGRO_WINDOWS) + ver = "Windows version"; + #elif defined(ALLEGRO_DOS) + ver = "DOS version"; + #elif defined(ALLEGRO_LINUX) + ver = "Linux version"; + #elif defined(ALLEGRO_BEOS) + ver = "BEOS version"; + #elif defined(ALLEGRO_QNX) + ver = "QNX version"; + #elif defined(ALLEGRO_UNIX) + ver = "UNIX version"; + #elif defined(ALLEGRO_MPW) + ver = "MacOS version"; + #else + ver = "Unknown platform"; + #endif + display_bg(); + txtmsg(166,76,15+32,"O2EM v" O2EM_VERSION " " RELEASE_DATE); + txtmsg(166,90,15+32,"Free Odyssey2 / VP+ Emulator"); + txtmsg(166,104,15+32,ver); + txtmsg(166,118,15+32,"Developed by Andre de la Rocha"); + txtmsg(168,132,15+32,"and Arlindo M. de Oliveira"); + txtmsg(166,148,15+32,"Copyright 1996/1998 by Daniel Boris"); + txtmsg(166,162,15+32,exitstr); + finish_display(); +} +void display_msg(char *msg, int waits) +{ + mute_audio(); + mute_voice(); + rectfill(bmp,60,72,271,90,9+32); + line(bmp,60,72,271,72,15+32); + line(bmp,60,72,60,90,15+32); + line(bmp,61,90,271,90,1+32); + line(bmp,271,90,271,72,1+32); + txtmsg(166,76,15+32,msg); + finish_display(); + rest(waits*100); + init_sound_stream(); +} +void init_display(void) { +#ifndef __LIBRETRO__ + get_palette(oldcol); +#endif + create_cmap(); + bmp = create_bitmap(BMPW,BMPH); + bmpcache = create_bitmap(BMPW,BMPH); + + if ((!bmp) || (!bmpcache)) { + fprintf(stderr,"Could not allocate memory for screen buffer.\n"); + exit(EXIT_FAILURE); + } +#ifndef __LIBRETRO__ + vscreen = (Byte *) bmp->dat; +#else + vscreen = (Byte *) &bmp->line[0]; +#endif + +#ifndef __LIBRETRO__ + clear(bmp); + clear(bmpcache); +#endif + col = (Byte *)malloc(BMPW*BMPH); + if (!col) { + fprintf(stderr,"Could not allocate memory for collision buffer.\n"); + free(vscreen); + exit(EXIT_FAILURE); + } + memset(col,0,BMPW*BMPH); + if (!app_data.debug) { + grmode(); + init_keyboard(); + } + +#ifndef __LIBRETRO__ + set_window_close_button(TRUE); + set_window_close_hook(window_close_hook); +#endif +} +/*************************** Help*/ +void help(void){ +int cnt, cntt, cnttt, way; +cnttt = 40; +cntt = 0; +cnt = 0; +way = 0; +static char hl[96][70]= + {"-wsize=n", + " Window size (1-4)","", + "-fullscreen", + " Full screen mode","", + "-Help", + " This instructions","", + "-scanlines", + " Enable scanlines","", + "-nosound", + " Turn off sound emulation","", + "-novoice", + " Turn off voice emulation","", + "-svolume=n", + " Set sound volume (0-100)","", + "-vvolume=n", + " Set voice volume (0-100)","", + "-filter", + " Enable low-pass audio filter","", + "-debug", + " Start the emulator in "," debug mode","", + "-speed=n", + " Relative speed"," (100 = original)","", + "-nolimit", + " Turn off speed limiter","", + "-bios=file", + " Set the O2 bios file name/dir","", + "-biosdir=path", + " Set the O2 bios path "," (default= bios/ )","", + "-romdir=path", + " Set the O2 roms Path "," (default= roms/ )","", + "-scshot=file", + " Set the screenshot file "," name/template","", + "-euro", + " Use European timing /"," 50Hz mode","", + "-exrom", + " Use special 3K program/"," 1K data ROM mode","", + "-3k", + " Use 3K rom mapping mode","", + "-s=mode/keys", + " Define stick n mode/keys (n=1-2)","", + "-c52", + " Start the emulator with "," french Odyssey 2 BIOS","", + "-g7400", + " Start the emulator "," with VP+ BIOS","", + "-jopac", + " Start the emulator with "," french VP+ bios","", + "-scoretype=m", + " Set Scoretype to m (see manual)","", + "-scoreadr=n", + " Set Scoreaddress to n "," (decimal value)","", + "-scorefile=file", + " Set Output-Scorefile to "," file (highscore.txt)","", + "-score=n", + " Set Highscore to n","", + "-savefile=file", + " Load/Save State "," from/to file" + }; +#ifndef __LIBRETRO__ +text_mode(-1); + +textout(bmp, font, "O2EM v" O2EM_VERSION " Help", 26 , 16, 2); +textout(bmp, font, "Use: o2em [options]", 26, 26, 2); +#endif +rect(bmp,20,12,315,228,6); +line(bmp,20,35,315,35,6); +for (cntt=0; cntt<16; cntt++) + { +#ifndef __LIBRETRO__ + textout(bmp, font, hl[cnt+cntt], 26, cnttt, 4); +#endif + cnttt += 12; + } + cnttt = 40; + finish_display(); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + if (key[RETROK_UP]) { + cnt ++; + if (cnt >= 80) cnt = 80; + rectfill(bmp,25,36,306,227,0); + for (cntt=0; cntt<16; cntt++) + { +#ifndef __LIBRETRO__ + textout(bmp, font, hl[cnt+cntt], 26, cnttt, 4); +#endif + + cnttt += 12; + } + cnttt = 40; + for (way=0;way<8;way++) + finish_display(); + } + if (key[RETROK_DOWN]) { + cnt --; + if (cnt <= 0) cnt = 0; + rectfill(bmp,25,36,306,227,0); + for (cntt=0; cntt<16; cntt++) + { +#ifndef __LIBRETRO__ + textout(bmp, font, hl[cnt+cntt], 26, cnttt, 4); +#endif + cnttt += 12; + } + cnttt = 40; + for (way=0;way<8;way++) + finish_display(); + } + + } + while (!key[RETROK_ESCAPE]); + do { + rest(5); + if (NeedsPoll) + poll_keyboard(); + + } while (key[RETROK_ESCAPE]); +return; +} + diff --git a/src/vdc.h b/src/vdc.h new file mode 100755 index 0000000..2c69fc6 --- /dev/null +++ b/src/vdc.h @@ -0,0 +1,40 @@ +#ifndef __VDC_H +#define __VDC_H + +#define BMPW 340 +#define BMPH 250 +#define WNDW 320 +#define WNDH 240 +/*********/ +#define BOX_W MIN(512, SCREEN_W-16) +#define BOX_H MIN(256, (SCREEN_H-64)&0xFFF0) + +#define BOX_L ((SCREEN_W - BOX_W) / 2) +#define BOX_R ((SCREEN_W + BOX_W) / 2) +#define BOX_T ((SCREEN_H - BOX_H) / 2) +#define BOX_B ((SCREEN_H + BOX_H) / 2) + +/*********/ +extern Byte coltab[]; +extern long clip_low; +extern long clip_high; +extern int show_fps; + +void init_display(void); +void draw_display(void); +void set_textmode(void); +void draw_region(void); +void finish_display(); +void close_display(void); +void grmode(void); +void display_bg(void); +void display_msg(char *msg, int waits); +void clear_collision(void); +void clearscr(void); +void abaut(void); +void help(void); + + +#endif + + diff --git a/src/vmachine.c b/src/vmachine.c new file mode 100755 index 0000000..935b5de --- /dev/null +++ b/src/vmachine.c @@ -0,0 +1,827 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Main O2 machine emulation + */ + + +#include +#include +#include +#include "audio.h" +#include "types.h" +#include "cpu.h" +#include "keyboard.h" +#include "config.h" +#include "debug.h" +#include "vdc.h" +#include "vpp.h" +#include "timefunc.h" +#include "voice.h" +#include "vmachine.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "wrapalleg.h" +#include "libretro.h" +extern unsigned char key[512]; +#endif + + +static Byte x_latch,y_latch; +static int romlatch=0; +static Byte line_count; +static int fps=FPS_NTSC; + +static Byte snapedlines[MAXLINES+2*MAXSNAP][256][2]; + +int evblclk=EVBLCLK_NTSC; + +struct resource app_data; +int frame=0; +Byte dbstick1,dbstick2; + +int int_clk; /* counter for length of /INT pulses */ +int master_clk; /* Master clock */ +int h_clk; /* horizontal clock */ +unsigned long clk_counter; +int last_line; +int key2vcnt=0; +int mstate; + +int pendirq=0; +int enahirq=1; +int useforen=0; +long regionoff=0xffff; +int mxsnap=2; +int sproff=0; +int tweakedaudio=0; + +Byte rom_table[8][4096]; + +Byte intRAM[64]; +Byte extRAM[256]; +Byte extROM[1024]; +Byte VDCwrite[256]; +Byte ColorVector[MAXLINES]; +Byte AudioVector[MAXLINES]; +Byte *rom; +Byte *megarom; + +int key2[128]; + + +static unsigned int key_map[6][8]= { + {RETROK_0,RETROK_1,RETROK_2,RETROK_3,RETROK_4,RETROK_5,RETROK_6,RETROK_7}, + {RETROK_8,RETROK_9,0,0,RETROK_SPACE,RETROK_QUESTION,RETROK_l,RETROK_p}, + {RETROK_PLUS,RETROK_w,RETROK_e,RETROK_r,RETROK_t,RETROK_u,RETROK_i,RETROK_o}, + {RETROK_q,RETROK_s,RETROK_d,RETROK_f,RETROK_g,RETROK_h,RETROK_j,RETROK_k}, + {RETROK_a,RETROK_z,RETROK_x,RETROK_c,RETROK_v,RETROK_b,RETROK_m,RETROK_PERIOD}, + {RETROK_MINUS,RETROK_ASTERISK,RETROK_SLASH,RETROK_EQUALS,RETROK_y,RETROK_n,RETROK_END,RETROK_RETURN} +}; + + +static void do_kluges(void); +static void setvideomode(int t); + +void run(void){ + while(!key_done) { + + if (key_debug) { + app_data.debug=1; + set_textmode(); + mute_audio(); + mute_voice(); + debug(); + grmode(); + app_data.debug=0; + init_keyboard(); + init_sound_stream(); + } + + cpu_exec(); + + } + close_audio(); + close_voice(); + close_display(); +} + + +void handle_vbl(void){ + + if (!app_data.debug) { + +#ifndef __LIBRETRO__ + handle_key(); +#else + update_joy(); +#endif + + update_audio(); + +#ifndef __LIBRETRO__ + update_voice(); +#else + //TODO +#endif + + } + draw_region(); + ext_IRQ(); + mstate = 1; +} + + +void handle_evbl(void){ + static long last=0; + static int rest_cnt=0; + int i; + + + #ifndef ALLEGRO_DOS + yield_timeslice(); + #endif + i = (15*app_data.speed/100); + rest_cnt = (rest_cnt+1)%(i<5?5:i); + #ifdef ALLEGRO_WINDOWS + if (rest_cnt==0) rest(1); + #endif + last_line=0; + master_clk -= evblclk; + frame++; + if (!app_data.debug) { + finish_display(); + } + + if (app_data.crc == 0xA7344D1F) + {for (i=0; i<140; i++) + { + ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80); + AudioVector[i] = VDCwrite[0xAA]; + } + }/*Atlantis*/ + else + for (i=0; i 10) { + key2vcnt=0; + for (i=0; i<128; i++) key2[i] = 0; + dbstick1 = dbstick2 = 0; + } + if (app_data.limit) { + long d,f; + d = (TICKSPERSEC*100)/(app_data.speed*fps); + f = ((d-gettimeticks()+last)*1000)/TICKSPERSEC; + if (f>0) { + #ifdef ALLEGRO_WINDOWS + f = f-(f%10); + if (f>5) rest(f-5); + #else + #ifndef ALLEGRO_DOS + yield_timeslice(); + + #endif + #endif + } + while (gettimeticks() - last < d); + last = gettimeticks(); + } + mstate=0; + +} + +void handle_evbll(void){ + static long last=0; + static int rest_cnt=0; + int i; + + #ifndef ALLEGRO_DOS + yield_timeslice(); + #endif + i = (15*app_data.speed/100); + rest_cnt = (rest_cnt+1)%(i<5?5:i); + #ifdef ALLEGRO_WINDOWS + if (rest_cnt==0) rest(1); + #endif + +/******************* 150 */ + + for (i=150; i 10) { + key2vcnt=0; + for (i=0; i<128; i++) key2[i] = 0; + dbstick1 = dbstick2 = 0; + } + if (app_data.limit) { + long d,f; + d = (TICKSPERSEC*100)/(app_data.speed*fps); + f = ((d-gettimeticks()+last)*1000)/TICKSPERSEC; + if (f>0) { + #ifdef ALLEGRO_WINDOWS + f = f-(f%10); + if (f>5) rest(f-5); + #else + #ifndef ALLEGRO_DOS + yield_timeslice(); + #endif + #endif + } + while (gettimeticks() - last < d); + last = gettimeticks(); + } + mstate=0; +} + +void init_system(void){ + int i,j,k; + + last_line=0; + dbstick1=0x00; + dbstick2=0x00; + mstate=0; + master_clk=0; + h_clk=0; + line_count=0; + itimer=0; + clk_counter=0; + init_roms(); + for(i=0; i<256; i++) { + VDCwrite[i]=0; + extRAM[i]=0; + } + for(i=0; i<64; i++) { + intRAM[i]=0; + } + for (i=0; i 16) || (master_clk > VBLCLK)) + return 1; + else + return 0; +} + + +void write_p1(Byte d){ + if ((d & 0x80) != (p1 & 0x80)) { + int i,l; + l = snapline((int)((float)master_clk/22.0+0.1), VDCwrite[0xA3], 1); + for (i=l; i VBLCLK) d = d | 0x08; + if (h_clk < (LINECNT-7)) d = d | 0x01; + if (sound_IRQ) d = d | 0x04; + sound_IRQ=0; + return d; + case 0xA2: + si = VDCwrite[0xA2]; + m=0x01; + d=0; + for(i=0; i<8; i++) { + if (si & m) { + if (coltab[1] & m) d = d | (coltab[1] & (m ^ 0xFF)); + if (coltab[2] & m) d = d | (coltab[2] & (m ^ 0xFF)); + if (coltab[4] & m) d = d | (coltab[4] & (m ^ 0xFF)); + if (coltab[8] & m) d = d | (coltab[8] & (m ^ 0xFF)); + if (coltab[0x10] & m) d = d | (coltab[0x10] & (m ^ 0xFF)); + if (coltab[0x20] & m) d = d | (coltab[0x20] & (m ^ 0xFF)); + if (coltab[0x80] & m) d = d | (coltab[0x80] & (m ^ 0xFF)); + } + m = m << 1; + } + clear_collision(); + return d; + case 0xA5: + if (!(VDCwrite[0xA0] & 0x02)) { + return x_latch; + } + else { + x_latch = h_clk * 12; + return x_latch; + } + case 0xA4: + if (!(VDCwrite[0xA0] & 0x02)) { + return y_latch; + } + else { + y_latch = master_clk/22; + if (y_latch > 241) y_latch=0xFF; + return y_latch; + } + default: + return VDCwrite[adr]; + } + } else if (!(p1 & 0x10)) { + /* Handle ext RAM Read */ + if (app_data.megaxrom && (adr >= 0x80)) { + /* MegaCART registers are mirrored every 4 bytes */ + if ((adr & 0x83) == 0x83) { + /* TODO: emulate EEPROM data in */ + return 0xff; + } else return extRAM[adr & 0x83]; + } else return extRAM[adr & 0xFF]; + } else if (!(p1 & 0x20)) { + /* Read a Videopac+ register */ + return vpp_read(adr); + } else if (app_data.exrom && (p1 & 0x02)) { + /* Handle read from exrom */ + return extROM[(p2 << 8) | (adr & 0xFF)]; + } else if (app_data.megaxrom && !(p1 & 0x02) && !(p1 & 0x40)) { + /* Handle data read from MegaCART */ + return megarom[(extRAM[0x81] << 12) | ((p2 & 0x0f) << 8) | (adr & 0xff)]; + } + + return 0; +} + + +Byte in_bus(void){ + Byte si=0,d=0,mode=0,jn=0,sticknum=0; + + if ((p1 & 0x08) && (p1 & 0x10)) { + /* Handle joystick read */ + if (!(p1 & 0x04)) { + si = (p2 & 7); + } + d=0xFF; + if (si == 1) { + mode = app_data.stick[0]; + jn = 0; + sticknum = app_data.sticknumber[0]-1; + } else { + mode = app_data.stick[1]; + jn = 1; + sticknum = app_data.sticknumber[1]-1; + } + switch(mode) { + case 1: + d = keyjoy(jn); + break; + case 2: + +#ifndef __LIBRETRO__ + poll_joystick(); + if (joy[sticknum].stick[0].axis[1].d1) d &= 0xFE; // joy_up + if (joy[sticknum].stick[0].axis[0].d2) d &= 0xFD; // joy_right + if (joy[sticknum].stick[0].axis[1].d2) d &= 0xFB; // joy_down + if (joy[sticknum].stick[0].axis[0].d1) d &= 0xF7; // joy_left + if (joy[sticknum].button[0].b || joy[jn].button[1].b) d &= 0xEF; // both main-buttons +#else +//FIXME + d = keyjoy(jn); +#endif + + break; + } + if (si == 1) { + if (dbstick1) d = dbstick1; + } else { + if (dbstick2) d = dbstick2; + } + } + return d; +} + + +void ext_write(Byte dat, ADDRESS adr){ + int i; + + if (!(p1 & 0x08)) { + /* Handle VDC Write */ + if (adr == 0xA0){ + if ((VDCwrite[0xA0] & 0x02) && !(dat & 0x02)) { + y_latch = master_clk/22; + x_latch = h_clk * 12; + if (y_latch > 241) y_latch=0xFF; + } + if ((master_clk <= VBLCLK) && (VDCwrite[0xA0] != dat)) { + draw_region(); + } + } else if (adr == 0xA3){ + int l; + l = snapline((int)((float)master_clk/22.0+0.5), dat, 1); + for (i=l; i= 0x40) && (adr <= 0x7f) && ((adr & 2) == 0)) { + /* simulate quad: all 4 sub quad position registers + * are mapped to the same internal register */ + adr = adr & 0x71; + /* Another minor thing: the y register always returns + * bit 0 as 0 */ + if ((adr & 1) == 0) dat = dat & 0xfe; + VDCwrite[adr] = VDCwrite[adr+4] = VDCwrite[adr+8] = VDCwrite[adr+12] = dat; + } + VDCwrite[adr]=dat; + } else if (!(p1 & 0x10) && !(p1 & 0x40)) { + adr = adr & 0xFF; + + if (adr < 0x80) { + /* Handle ext RAM Write */ + extRAM[adr] = dat; + + + } else { + if (app_data.bank == 4) { + romlatch = (~dat) & 7; + rom=rom_table[(p1 & 1)?0:romlatch]; + } + + /* Handle The Voice */ + if (!(dat & 0x20)) + reset_voice(); + else { + if (adr == 0xE4) + set_voice_bank(0); + else if ((adr >= 0xE8) && (adr <= 0xEF)) + set_voice_bank(adr-0xE7); + else if (((adr >= 0x80) && (adr <= 0xDF)) || ((adr >= 0xF0) && (adr <= 0xFF))) + trigger_voice(adr); + } + } + } else if (!(p1 & 0x20)) { + /* Write to a Videopac+ register */ + vpp_write(dat,adr); + } +} + + +static void do_kluges(void){ + if (app_data.crc == 0xA7344D1F) pendirq=1; /* Atlantis */ + if (app_data.crc == 0xFB83171E) pendirq=1; /* Blockout */ + if (app_data.crc == 0xD38153F6) pendirq=1; /* Blockout (french) */ + if (app_data.crc == 0x881CEAE4) pendirq=1; /* Wall Street */ + + if (app_data.crc == 0x9E42E766) useforen=1; /* Turtles */ + if (app_data.crc == 0x1C750349) useforen=1; /* Turtles (European version) */ + if (app_data.crc == 0x202F2749) useforen=1; /* Q*bert */ + if (app_data.crc == 0x06861A9C) useforen=1; /* Flashpoint 5 (Videopac adaption) */ + + if (app_data.crc == 0xFB83171E) enahirq=0; /* Blockout*/ + if (app_data.crc == 0xD38153F6) enahirq=0; /* Blockout (french) */ + + if (app_data.crc == 0xFB83171E) regionoff=1; /* Blockout*/ + if (app_data.crc == 0xD38153F6) regionoff=1; /* Blockout (french) */ + if (app_data.crc == 0x202F2749) regionoff=0; /* Q*bert */ + if (app_data.crc == 0x5216771A) regionoff=1; /* Popeye */ + if (app_data.crc == 0x0C2E4811) regionoff=11; /* Out of this World! / Helicopter Rescue! */ + if (app_data.crc == 0x67069924) regionoff=11; /* Smithereens! */ + if (app_data.crc == 0x44D1A8A5) regionoff=11; /* Smithereens! (European version) */ + if (app_data.crc == 0x2391C2FB) regionoff=11; /* Smithereens! + */ + if (app_data.crc == 0xBB4AD548) regionoff=11; /* Smithereens! modified 1 */ + if (app_data.crc == 0x25057C11) regionoff=11; /* Smithereens! modified 2 */ + if (app_data.crc == 0xB936BD78) regionoff=12; /* Type & Tell */ + if (app_data.crc == 0xAD8B9AE0) regionoff=2; /* Type & Tell modified 1 */ + if (app_data.crc == 0x5C02BEE6) regionoff=2; /* Type & Tell modified 2 */ + if (app_data.crc == 0xDC30AD3D) regionoff=10; /* Dynasty! */ + if (app_data.crc == 0x7810BAD5) regionoff=8; /* Dynasty! (European) */ + if (app_data.crc == 0xA7344D1F) regionoff=0; /* Atlantis */ + if (app_data.crc == 0xD0BC4EE6) regionoff=12; /* Frogger */ + if (app_data.crc == 0xA57D84F3) regionoff=8; /* Frogger BR */ + if (app_data.crc == 0x825976A9) regionoff=0; /* Mousing Cat 8kb */ + if (app_data.crc == 0xF390BFEC) regionoff=0; /* Mousing Cat 4kb */ + if (app_data.crc == 0x61A350E6) regionoff=0; /* Mousing Cat (french) */ + if (app_data.crc == 0x3BFEF56B) regionoff=1; /* Four in 1 Row! */ + if (app_data.crc == 0x7C747245) regionoff=1; /* Four in 1 Row! modified */ + if (app_data.crc == 0x9B5E9356) regionoff=1; /* Four in 1 Row! (french) */ + + if (app_data.crc == 0x6CEBAB74) regionoff=12; /* P.T. Barnum's Acrobats! (European version) */ + if (app_data.crc == 0xE7B26A56) regionoff=12; /* P.T. Barnum's Acrobats! (European version - Extra keys) */ + + if (app_data.crc == 0xFB83171E) mxsnap=3; /* Blockout*/ + if (app_data.crc == 0xD38153F6) mxsnap=3; /* Blockout (french) */ + if (app_data.crc == 0xA57E1724) mxsnap=12; /* Catch the Ball / Noughts and Crosses */ + if (app_data.crc == 0xBE4FF48E) mxsnap=12; /* Catch the Ball / Noughts and Crosses modified */ + if (app_data.crc == 0xFD179F6D) mxsnap=3; /* Clay Pigeon! */ + if (app_data.crc == 0x9C9DDDF9) mxsnap=3; /* Verkehr */ + if (app_data.crc == 0x95936B07) mxsnap=3; /* Super Cobra */ + if (app_data.crc == 0x881CEAE4) mxsnap=3; /* Wall Street */ + if (app_data.crc == 0x9E42E766) mxsnap=0; /* Turtles */ + if (app_data.crc == 0x1C750349) mxsnap=0; /* Turtles (European version) */ + if (app_data.crc == 0xD0BC4EE6) mxsnap=3; /* Frogger */ + if (app_data.crc == 0xA57D84F3) mxsnap=3; /* Frogger BR */ + if (app_data.crc == 0x3BFEF56B) mxsnap=6; /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) mxsnap=6; /* Four in 1 Row! (french) */ + if (app_data.crc == 0x7C747245) mxsnap=6; /* Four in 1 Row! modified */ + + if (app_data.crc == 0xA7344D1F) setvideomode(1); /* Atlantis */ + if (app_data.crc == 0x39E31BF0) setvideomode(1); /* Jake */ + if (app_data.crc == 0x92D0177B) setvideomode(1); /* Jake (hack) */ + if (app_data.crc == 0x3351FEDA) setvideomode(1); /* Power Lords */ + if (app_data.crc == 0x40AE062D) setvideomode(1); /* Power Lords (alternate) */ + if (app_data.crc == 0xD158EEBA) setvideomode(1); /* Labirinth */ + if (app_data.crc == 0x26B0FF5B) setvideomode(1); /* Nightmare */ + if (app_data.crc == 0xDF36683F) setvideomode(1); /* Shark Hunter */ + if (app_data.crc == 0xAF307559) setvideomode(1); /* Super Bee 8Kb */ + if (app_data.crc == 0x9585D511) setvideomode(1); /* Super Bee 4Kb */ + if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */ + if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */ + if (app_data.crc == 0x39989464) setvideomode(1); /* Hockey! / Soccer! */ + if (app_data.crc == 0x3BFEF56B) setvideomode(1); /* Four in 1 Row! */ + if (app_data.crc == 0x9B5E9356) setvideomode(1); /* Four in 1 Row! (french) */ + if (app_data.crc == 0x7C747245) setvideomode(1); /* Four in 1 Row! modified */ + if (app_data.crc == 0x68560DC7) setvideomode(1); /* Jopac Moto Crash */ + if (app_data.crc == 0x020FCA15) setvideomode(1); /* Jopac Moto Crash modified (non VP+) */ + if (app_data.crc == 0xC4134DF8) setvideomode(1); /* Helicopter Rescue + */ + if (app_data.crc == 0x0D2D721D) setvideomode(1); /* Trans American Rally + */ + if (app_data.crc == 0x9D72D4E9) setvideomode(1); /* Blobbers */ + if (app_data.crc == 0xB2F0F0B4) setvideomode(1); /* Le Tresor Englouti + */ + if (app_data.crc == 0x0B2DEB61) setvideomode(1); /* Tutankham */ + if (app_data.crc == 0x313547EB) setvideomode(1); /* VP53 */ + if (app_data.crc == 0x06861A9C) setvideomode(1); /* Flashpoint 5 (Videopac adaption) */ + if (app_data.crc == 0xA57E1724) setvideomode(0); /* Catch the Ball / Noughts and Crosses */ + if (app_data.crc == 0xBE4FF48E) setvideomode(0); /* Catch the Ball / Noughts and Crosses modified */ + if (app_data.crc == 0xFB83171E) setvideomode(0); /* Blockout*/ + if (app_data.crc == 0xD38153F6) setvideomode(0); /* Blockout (french) */ + if (app_data.crc == 0x9BFC3E01) setvideomode(0); /* Demon Attack */ + if (app_data.crc == 0x50AF9D45) setvideomode(0); /* Demon Attack + */ + if (app_data.crc == 0x9884EF36) setvideomode(0); /* Demon Attack + modified */ + if (app_data.crc == 0x4A578DFE) setvideomode(0); /* Restaurant ntsc */ + if (app_data.crc == 0x863D5E2D) setvideomode(0); /* Shark Hunter ntsc */ + + if (app_data.crc == 0xD62814A3) evblclk=12000; /* Pick Axe Pete */ + if (app_data.crc == 0xB2FFB353) evblclk=12000; /* Pick Axe Pete + */ + if (app_data.crc == 0x81C20196) evblclk=12000; /* Pick Axe Pete + (modified) */ + + if ((app_data.crc == 0xF390BFEC) || (app_data.crc == 0x825976A9) || (app_data.crc == 0x61A350E6)){ /* Mousing Cat */ + setvideomode(1); + evblclk=7642; + } + + if (app_data.crc == 0xD0BC4EE6) { /* Frogger */ + setvideomode(1); + evblclk=7642; + + } + if (app_data.crc == 0x26517E77) { /* Commando Noturno */ + setvideomode(1); + evblclk=6100; + regionoff=12; + } + if (app_data.crc == 0xA57E1724) { /* Catch the ball*/ + regionoff=5; + sproff=1; + + } + + if ((app_data.crc == 0x2DCB77F0) || (app_data.crc == 0xF6882734)) { /* Depth Charge / Marksman */ + setvideomode(1); + evblclk=8000; + } + if (app_data.crc == 0x881CEAE4) { /* Wall Street */ + setvideomode(1); + evblclk=6100; + } + if (app_data.crc == 0xD0BC4EE6) tweakedaudio=1; /* Frogger */ + if (app_data.crc == 0xA57D84F3) tweakedaudio=1; /* Frogger BR */ + if (app_data.crc == 0x5216771A) tweakedaudio=1; /* Popeye */ + if (app_data.crc == 0xAFB23F89) tweakedaudio=1; /* Musician */ + if (app_data.crc == 0xC4134DF8) tweakedaudio=1; /* Helicopter Rescue + */ + if (app_data.crc == 0x0D2D721D) tweakedaudio=1; /* Trans American Rally + */ + + if (app_data.crc == 0xD3B09FEC) sproff=1; /* Volleyball! */ + if (app_data.crc == 0x551E38A2) sproff=1; /* Volleyball! (french) */ + +} + + +int snapline(int pos, Byte reg, int t){ + int i; + if (pos (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * O2 Voice emulation + */ + + +#include +#include "vmachine.h" +#include "cpu.h" +#include "voice.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#define SAMPLE signed short +#endif + +static SAMPLE *voices[9][128]; +static int voice_bank=0; +static int voice_num=-1; +static int voice_addr=0; +static int voice_ok=0; +static int voice_st=0; +static unsigned long clk_voice_start=0; + + +void load_voice_samples(char *path){ +#ifndef __LIBRETRO__ + int bank, sam, i, ld=0; + char name[MAXC]; + SAMPLE *sp=NULL; + + printf("Loading voice samples... "); + fflush(stdout); + + for (i=0; i<9; i++) { + for (sam=0; sam<128; sam++) { + + if (i) + bank = 0xE8+i-1; + else + bank = 0xE4; + + sprintf(name,"%svoice/%02x%02x.wav",path,bank,sam+0x80); + + voices[i][sam] = load_sample(name); + + if (!voices[i][sam]) { + sprintf(name,"%svoice/%02X%02X.WAV",path,bank,sam+0x80); + voices[i][sam] = load_sample(name); + } + + if (voices[i][sam]) { + ld++; + if (!sp) sp = voices[i][sam]; + } + + } + } + + printf("%d samples loaded\n",ld); + + if (ld>0){ + voice_num = allocate_voice(sp); + if (voice_num != -1) + voice_ok=1; + else { + printf(" ERROR: could not allocate sound card voice\n"); + voice_ok=0; + } + } +#endif + +} + + +void update_voice(void){ +#ifndef __LIBRETRO__ + if (!voice_ok) return; + if (voice_st==2) { + if (voice_get_position(voice_num) < 0){ + if ((voice_bank>=0) && (voice_bank<9) && (voice_addr>=0x80) && (voice_addr<=0xff)) { + if (voices[voice_bank][voice_addr-0x80]) { + reallocate_voice(voice_num, voices[voice_bank][voice_addr-0x80]); + voice_set_volume(voice_num, (255*app_data.vvolume)/100); + voice_start(voice_num); + clk_voice_start = clk_counter; + voice_st=1; + } else { + voice_st=0; + } + } + } + } else if (voice_st==1) { + if ((voice_get_position(voice_num) < 0) || (clk_counter-clk_voice_start>20) ) { + voice_st=0; + } + } +#endif +} + + +void trigger_voice(int addr){ +#ifndef __LIBRETRO__ + if (voice_ok){ + if (voice_st) update_voice(); + if ((voice_st==0) && (voice_bank>=0) && (voice_bank<9) && (addr>=0x80) && (addr<=0xff)){ + voice_addr = addr; + voice_st = 2; + update_voice(); + } + } +#endif +} + + +void set_voice_bank(int bank){ +#ifndef __LIBRETRO__ + if (!voice_ok) return; + if ((bank>=0) && (bank<=8)) voice_bank = bank; +#endif +} + + +int get_voice_status(void){ +#ifndef __LIBRETRO__ + if (voice_ok){ + update_voice(); + if (voice_st) return 1; + } +#endif + return 0; +} + + +void reset_voice(void){ +#ifndef __LIBRETRO__ + if (voice_ok) { + voice_stop(voice_num); + voice_bank=0; + voice_addr=0; + voice_st=0; + } +#endif +} + + +void mute_voice(void){ +#ifndef __LIBRETRO__ + if (voice_ok) { + voice_stop(voice_num); + } +#endif +} + + +void close_voice(void){ +#ifndef __LIBRETRO__ + reset_voice(); +#endif + voice_ok=0; +} + + diff --git a/src/voice.h b/src/voice.h new file mode 100755 index 0000000..36b61ed --- /dev/null +++ b/src/voice.h @@ -0,0 +1,14 @@ +#ifndef __VOICE_H +#define __VOICE_H + +void load_voice_samples(char *path); +void update_voice(void); +void trigger_voice(int addr); +void reset_voice(void); +void set_voice_bank(int bank); +void close_voice(void); +void mute_voice(void); +int get_voice_status(void); + +#endif + diff --git a/src/vpp.c b/src/vpp.c new file mode 100755 index 0000000..052fc6f --- /dev/null +++ b/src/vpp.c @@ -0,0 +1,521 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Videopac+ G7400 emulation + */ + + +#include +#include +#include +#include "types.h" +#include "vmachine.h" +#include "vdc.h" +#include "vpp_cset.h" +#include "vpp.h" + +#ifndef __LIBRETRO__ +#include "allegro.h" +#else +#include "wrapalleg.h" +#endif + +static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext, Byte dw, Byte dh, Byte ul); +static void vpp_update_screen(void); + + +static Byte LumReg = 0xff, TraReg = 0xff; +static BITMAP *vppbmp = NULL; +static Byte *colplus = NULL; +static int vppon = 1; +static int vpp_cx = 0; +static int vpp_cy = 0; +static Byte vpp_data = 0; +static int inc_curs=1; +static int slice=0; +static int vpp_y0=0; +static Byte vpp_r=0; +Byte dchars[2][960]; +Byte vpp_mem[40][32][4]; +static int frame_cnt=0; +static int blink_st=0; +static int slicemode=0; +static int need_update=0; + + +Byte read_PB(Byte p){ + p &= 0x3; + switch (p) { + case 0: + return LumReg >> 4; + break; + case 1: + return LumReg & 0xf; + break; + case 2: + return TraReg >> 4; + break; + case 3: + return TraReg & 0xf; + break; + } + return 0; +} + + +void write_PB(Byte p, Byte val){ + p &= 0x3; + val &= 0xf; + + switch (p) { + case 0: + LumReg = (val<<4) | (LumReg & 0xf); + break; + case 1: + LumReg = (LumReg & 0xf0) | val; + break; + case 2: + TraReg = (val<<4) | (TraReg & 0xf); + break; + case 3: + TraReg = (TraReg & 0xf0) | val; + break; + } + need_update = 1; +} + + +Byte vpp_read(ADDRESS adr){ + Byte t; + static Byte ta=0; + static Byte tb=0; + + switch (adr){ + case 4: + return ta; + case 5: + /* get return value from last read */ + t = tb; + /* the real VPP starts a read cycle, + * the data gets returned at next read */ + if (slicemode) { + Byte ext, chr; + chr = vpp_mem[vpp_cx][vpp_cy][0]; + ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0; + if (chr < 0xA0) { + ta = 0; +fprintf(stderr, "unsupported: CHARROM read %d %d %d\n", chr, ext, slice); + } else { + ta = dchars[ext][(chr-0xA0)*10+slice]; + ta = ((ta&0x80)>>7) | ((ta&0x40)>>5) | ((ta&0x20)>>3) | ((ta&0x10)>>1) | ((ta&0x08)<<1) | ((ta&0x04)<<3) | ((ta&0x02)<<5) | ((ta&0x01)<<7); + } + tb = 0xff; /* real VPP seems to return junk */ + slice = (slice+1) % 10; + } else { + ta = vpp_mem[vpp_cx][vpp_cy][1]; + tb = vpp_mem[vpp_cx][vpp_cy][0]; + if (inc_curs) { + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) vpp_cy = 0; + } + } + } + return t; + case 6: + return 0; + default: + return 0; + } +} + + +void vpp_write(Byte dat, ADDRESS adr){ + static Byte ta; + + switch (adr) { + case 0: + if (!slicemode) vpp_mem[vpp_cx][vpp_cy][1] = dat; + else ta = dat; + break; + case 1: + if (slicemode) { + Byte ext, chr; + chr = vpp_mem[vpp_cx][vpp_cy][0]; + ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0; + if (chr >= 0xA0) dchars[ext][(chr-0xA0)*10+slice] = ((ta&0x80)>>7) | ((ta&0x40)>>5) | ((ta&0x20)>>3) | ((ta&0x10)>>1) | ((ta&0x08)<<1) | ((ta&0x04)<<3) | ((ta&0x02)<<5) | ((ta&0x01)<<7); + slice = (slice+1) % 10; + } else { + vpp_mem[vpp_cx][vpp_cy][0] = dat; + if ((dat>0x7f) && (dat<0xa0) && (!(vpp_mem[vpp_cx][vpp_cy][1] & 0x80))) { + vpp_mem[vpp_cx][vpp_cy][2] = dat; + vpp_mem[vpp_cx][vpp_cy][3] = vpp_mem[vpp_cx][vpp_cy][1]; + } else { + vpp_mem[vpp_cx][vpp_cy][2] = vpp_mem[vpp_cx][vpp_cy][3] = 0; + } + if (inc_curs) { + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) vpp_cy = 0; + } + } + } + break; + case 2: + vpp_data = dat; + break; + case 3: + switch (dat & 0xe0) { + case 0x00: /* plus_cmd_brow */ + vpp_cy = vpp_data & 0x1f; + vpp_cx = 0; + break; + case 0x20: /* plus_cmd_loady */ + vpp_cy = vpp_data & 0x1f; + break; + case 0x40: /* plus_cmd_loadx */ + vpp_cx = (vpp_data & 0x3f) % 40; + break; + case 0x60: /* plus_cmd_incc */ + vpp_cx++; + if (vpp_cx >= 40) { + vpp_cx = 0; + vpp_cy++; + if (vpp_cy >= 24) vpp_cy = 0; + } + break; + case 0x80: /* plus_cmd_loadm */ + slicemode = 0; + slice = (vpp_data & 0x1f) % 10; + switch (vpp_data & 0xe0) { + case 0x00: /* plus_loadm_wr */ + inc_curs = 1; + break; + case 0x20: /* plus_loadm_rd */ + inc_curs = 1; + break; + case 0x40: /* plus_loadm_wrni */ + inc_curs = 0; + break; + case 0x60: /* plus_loadm_rdni */ + inc_curs = 0; + break; + case 0x80: /* plus_loadm_wrsl */ + slicemode = 1; + break; + case 0xA0: /* plus_loadm_rdsl */ + slicemode = 1; + break; + default: + break; + } + break; + case 0xA0: /* plus_cmd_loadr */ + vpp_r = vpp_data; + break; + case 0xC0: /* plus_cmd_loady0 */ +if (vpp_data & 0x20) fprintf(stderr, "unsupported: global double height"); + vpp_y0 = (vpp_data & 0x1f) % 24; + break; + default: + break; + } + break; + default: + break; + } + + need_update = 1; +} + + +void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth){ + int i, x, y, t, c, nc, clrx, clry; + int tcol[16], m[8] = {0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80}; + Byte *pnt, *pnt2, *pnt3; + + if (vppon) { + memset(colplus,0,BMPW*BMPH); + vppon=0; + } + + if (TraReg == 0xff) return; + + vppon=1; + + frame_cnt--; + if (frame_cnt<=0) { + frame_cnt = 100; + blink_st = 1-blink_st; + need_update = 1; + } + + if (need_update) vpp_update_screen(); + + for (i=0; i<8; i++) tcol[i] = tcol[i+8] = !(TraReg & m[i]); + + if (w > totw-offx) w = totw-offx; + if (h > toth-offy) h = toth-offy; + + if (w > vppbmp->w) w = vppbmp->w; + if (h > vppbmp->h) h = vppbmp->h; + + clrx = clry = 0; + for (i=0; (!clrx) && (iline[y]; +#else + pnt2 = (Byte *)&vppbmp->line[y*vppbmp->w]; +#endif + + + x=0; + while (x < w) { + pnt3 = pnt; + c = *pnt++; + t = x++; + + if ((((x+offx) & 3) == 0) && (sizeof(unsigned long)==4)) { + unsigned long cccc, dddd, *p = (unsigned long*) pnt; + int t2=x, w2=w-4; + cccc = (((unsigned long)c) & 0xff) | ((((unsigned long)c) & 0xff) << 8) | ((((unsigned long)c) & 0xff) << 16) | ((((unsigned long)c) & 0xff) << 24); + dddd = *p++; + while ((x39) || (y>24) || (ext>1)) return; + + d = (dh==2) ? 5 : 0; + + for (yy=0; yy<10; yy++) { + if (ul && (d==9)) + k = 255; + else if (ch >= 0xA0) + k = dchars[ext][(ch-0xA0)*10 + d]; + else if (ch >= 0x80) + k = 255; + else + k = vpp_cset[ext][ch * 10 + d]; + + m = (dw==2) ? 0x08 : 0x80; + + for (xx=0; xx<8; xx++) { +#ifndef __LIBRETRO__ + vppbmp->line[y*10+yy][x*8+xx] = (k & m) ? c1 : c0; +#else + vppbmp->line[(y*10+yy)*vppbmp->w+(x*8+xx)] = (k & m) ? c1 : c0; +#endif + if ((xx%2) || (dw==0)) m >>= 1; + } + if ((yy%2) || (dh==0)) d++; + } + +} + + +static void vpp_update_screen(void){ + int i,x,y,l,chr,attr,ext,c0,c1,dw,dh,hpar,vpar,lvd,lhd,ser_chr,ser_atr,ul,conc,box,swapcol; + int tlum[8], m[8] = {0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80}; +#ifndef __LIBRETRO__ + clear(vppbmp); +#endif + for (i=0; i<8; i++) tlum[i] = (LumReg & m[i]) ? 0 : 8; + + vpar = lvd = 0; + for (y=0; y<25; y++) { + + vpar = (lvd==0) ? 0 : 1-vpar; + + l = (y==0) ? 31 : (y-1+vpp_y0)%24; + c0 = ul = conc = box = 0; + + hpar = lhd = 0; + for (x=0; x<40; x++) { + hpar = (lhd==0) ? 0 : 1-hpar; + + chr = vpp_mem[x][l][0]; + attr = vpp_mem[x][l][1]; + c1 = attr & 0x7; + c1 = ((c1&2) | ((c1&1)<<2) | ((c1&4)>>2)); + ext = (attr & 0x80) ? 1 : 0; + + ser_chr = vpp_mem[x][l][2]; + ser_atr = vpp_mem[x][l][3]; + if (ser_chr) { + c0 = (ser_atr>>4) & 0x7; + c0 = ((c0&2) | ((c0&1)<<2) | ((c0&4)>>2)); + ul = ser_chr & 4; + conc = ser_chr & 1; + box = ser_chr & 2; + } + + if (ext) { + c0 = (attr>>4) & 0x7; + c0 = ((c0&2) | ((c0&1)<<2) | ((c0&4)>>2)); + dw = dh = 0; + } else { + dw = (attr & 0x20) ? (hpar ? 2 : 1) : 0; + dh = (attr & 0x10) ? (vpar ? 2 : 1) : 0; + if (dw) lhd=1; + if (dh) lvd=1; + } + + swapcol = 0; + + /* cursor display */ + if ((x == vpp_cx) && (l == vpp_cy)) { + /* on cursor position */ + if (vpp_r & 0x10) { + /* cursor display active */ + swapcol = !swapcol; + if ((vpp_r & 0x80) && blink_st) { + /* blinking active */ + swapcol = !swapcol; + } + } + } + + /* invert attribute */ + if ((!ext) && (attr & 0x40)) swapcol = !swapcol; + + /* blinking chars */ + if ((vpp_r & 0x80) && !(attr & 8) && !blink_st) { + /* cursor handling is done already */ + if (!(vpp_r & 0x10) || (x != vpp_cx) || (l != vpp_cy)) { + c1=c0; + } + } + + if (((y == 0) && (vpp_r & 8)) || ((y != 0) && (vpp_r & 1))) { + if ((!conc) || (!(vpp_r & 4))) { + if (box || (!(vpp_r & 2))) { + if (swapcol) + vpp_draw_char(x, y, chr, c1|tlum[c1], c0|tlum[c0], ext, dw, dh, ul); + else + vpp_draw_char(x, y, chr, c0|tlum[c0], c1|tlum[c1], ext, dw, dh, ul); + } else { + vpp_draw_char(x, y, 255, (app_data.openb) ? 16 : 0, 0, 0, 0, 0, 0); + } + } + } + } + + } + + if (vpp_r & 0x20) { + for (y = vppbmp->h-1; y >= 10; y--) + for (x = 0; x < vppbmp->w; x++) +#ifndef __LIBRETRO__ + vppbmp->line[y][x] = vppbmp->line[(y-10)/2+10][x]; +#else + vppbmp->line[y*vppbmp->w +x] = vppbmp->line[((y-10)/2+10)*vppbmp->w +x]; ; +#endif + } + + need_update=0; +} + + +void load_colplus(Byte *col){ + if (vppon) + memcpy(col,colplus,BMPW*BMPH); + else + memset(col,0,BMPW*BMPH); +} + + +void init_vpp(void){ + int i,j,k; + + if (!vppbmp) vppbmp = create_bitmap(320,250); + if (!colplus) colplus = (Byte *)malloc(BMPW*BMPH); + + if ((!vppbmp) || (!colplus)) { + fprintf(stderr,"Could not allocate memory for Videopac+ screen buffer.\n"); + exit(EXIT_FAILURE); + } +#ifndef __LIBRETRO__ + clear(vppbmp); +#endif + memset(colplus,0,BMPW*BMPH); + + LumReg = TraReg = 0xff; + vpp_cx = 0; + vpp_cy = 0; + vpp_y0 = 0; + vpp_r = 0; + inc_curs = 1; + vpp_data = 0; + frame_cnt=0; + blink_st=0; + slice = 0; + slicemode=0; + need_update = 1; + vppon = 1; + + for (i=0; i<2; i++) + for (j=0; j<960; j++) dchars[i][j] = 0; + + for (i=0; i<40; i++) + for (j=0; j<32; j++) + for (k=0; k<4; k++) vpp_mem[i][j][k] = 0; +} + diff --git a/src/vpp.h b/src/vpp.h new file mode 100755 index 0000000..e3f8df6 --- /dev/null +++ b/src/vpp.h @@ -0,0 +1,12 @@ +#ifndef __VPP_H +#define __VPP_H + +Byte read_PB(Byte p); +void write_PB(Byte p, Byte val); +Byte vpp_read(ADDRESS adr); +void vpp_write(Byte dat, ADDRESS adr); +void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth); +void init_vpp(void); +void load_colplus(Byte *col); + +#endif diff --git a/src/vpp_cset.c b/src/vpp_cset.c new file mode 100755 index 0000000..531d881 --- /dev/null +++ b/src/vpp_cset.c @@ -0,0 +1,285 @@ + +/* + * O2EM Free Odyssey2 / Videopac+ Emulator + * + * Created by Daniel Boris (c) 1997,1998 + * + * Developed by Andre de la Rocha + * Arlindo M. de Oliveira + * + * http://o2em.sourceforge.net + * + * + * + * Videopac+ character table + */ + + +#include "types.h" +#include "vpp_cset.h" + + +Byte vpp_cset[2][1280] = { + { + /* Alphanumeric */ + 0x00,0x38,0x44,0x40,0x20,0x10,0x00,0x10,0x00,0x00, + 0x00,0x10,0x28,0x00,0x38,0x44,0x7c,0x44,0x00,0x00, + 0x00,0x08,0x10,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x08,0x14,0x10,0x38,0x10,0x24,0x3c,0x00,0x00, + 0x00,0x10,0x38,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10,0x20, + 0x00,0x28,0x28,0x7c,0x28,0x7c,0x28,0x28,0x00,0x00, + 0x00,0x20,0x18,0x00,0x38,0x44,0x7c,0x44,0x00,0x00, + 0x00,0x20,0x18,0x00,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x10,0x08,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x3c,0x50,0x50,0x58,0x50,0x50,0x3c,0x00,0x00, + 0x00,0x08,0x14,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x00,0x10,0x20,0x7f,0x20,0x10,0x00,0x00,0x00, + 0x00,0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10,0x10, + 0x00,0x00,0x08,0x04,0xfe,0x04,0x08,0x00,0x00,0x00, + 0x10,0x10,0x10,0x10,0x10,0x10,0x54,0x38,0x10,0x00, + 0x00,0x18,0x24,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x7c,0x00,0x00, + 0x00,0x08,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x28,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x10,0x20, + 0x00,0x10,0x28,0x00,0x44,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x20,0x10,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,0x00,0x00, + 0x00,0x20,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x52,0x5e,0x50,0x3e,0x00,0x00, + 0x00,0x10,0x28,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x40,0xc0,0x40,0x44,0x4c,0x14,0x3e,0x04,0x00, + 0x00,0x40,0xc0,0x40,0x4c,0x52,0x04,0x08,0x1e,0x00, + 0x00,0xe0,0x20,0x40,0x24,0xcc,0x14,0x3e,0x04,0x00, + 0x00,0x10,0x28,0x00,0x38,0x44,0x44,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + 0x00,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x28,0x00,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00, + 0x00,0x10,0x28,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x60,0x64,0x08,0x10,0x20,0x4c,0x0c,0x00,0x00, + 0x00,0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00,0x00, + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x00, + 0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00,0x00, + 0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10,0x00,0x00, + 0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, + 0x01,0x02,0x02,0x04,0x08,0x10,0x20,0x20,0x40,0x80, + 0x00,0x10,0x28,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7c,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x18,0x04,0x44,0x38,0x00,0x00, + 0x00,0x08,0x18,0x28,0x48,0x7c,0x08,0x08,0x00,0x00, + 0x00,0x7c,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00, + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + 0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x38,0x00,0x00, + 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40,0x00, + 0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00, + 0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,0x00,0x00, + 0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00, + 0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00,0x00, + 0x00,0x38,0x44,0x5c,0x54,0x5c,0x40,0x38,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x7c,0x44,0x44,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00, + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x7c,0x00,0x00, + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x00,0x00, + 0x00,0x38,0x44,0x40,0x40,0x4c,0x44,0x3c,0x00,0x00, + 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00, + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x1c,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00, + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00, + 0x00,0x44,0x6c,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + 0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + 0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + 0x00,0x44,0x44,0x44,0x54,0x54,0x54,0x28,0x00,0x00, + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + 0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x7c,0x00,0x00, + 0x00,0x1c,0x10,0x10,0x10,0x10,0x10,0x1c,0x00,0x00, + 0x80,0x40,0x40,0x20,0x10,0x08,0x04,0x04,0x02,0x01, + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + 0x00,0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00, + 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x3c,0x00,0x00, + 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00, + 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x44,0x44,0x3c,0x04,0x24,0x18, + 0x00,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30, + 0x00,0x20,0x20,0x24,0x28,0x30,0x28,0x24,0x00,0x00, + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00,0x00, + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40, + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x04, + 0x00,0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00,0x00, + 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00, + 0x00,0x20,0x20,0x38,0x20,0x20,0x20,0x18,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x44,0x4c,0x34,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00, + 0x00,0x00,0x00,0x44,0x44,0x4c,0x34,0x04,0x44,0x38, + 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x7c,0x00,0x00, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + { + /* Separated semi-graphic */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00, + 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00, + /* Mosaic semi-graphic */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff, + 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} +}; + diff --git a/src/vpp_cset.h b/src/vpp_cset.h new file mode 100755 index 0000000..973d3b2 --- /dev/null +++ b/src/vpp_cset.h @@ -0,0 +1,6 @@ +#ifndef __VPP_CSET_H +#define __VPP_CSET_H + +extern Byte vpp_cset[2][1280]; + +#endif