add sega genesis emu
This commit is contained in:
parent
6e99a22d1d
commit
53657f2aac
124 changed files with 1576 additions and 320704 deletions
BIN
MCUME_pico2/.DS_Store
vendored
BIN
MCUME_pico2/.DS_Store
vendored
Binary file not shown.
|
|
@ -19,10 +19,10 @@ include(pico_sdk_import.cmake)
|
|||
#set(TARGET picovcs)
|
||||
#set(TARGET picogb)
|
||||
#set(TARGET picopce)
|
||||
set(TARGET picosms)
|
||||
#set(TARGET picosms)
|
||||
set(TARGET picogen)
|
||||
|
||||
#set(TARGET pico5200)
|
||||
#set(TARGET picogen)
|
||||
|
||||
project(${TARGET} C CXX)
|
||||
|
||||
|
|
@ -262,21 +262,6 @@ set(PICO8086_SOURCES
|
|||
)
|
||||
endif()
|
||||
|
||||
if( ${TARGET} MATCHES "picopceold" )
|
||||
set(PICOPCE_SOURCES
|
||||
picopce/emu.cpp
|
||||
picopce/h6280.c
|
||||
picopce/memory.c
|
||||
picopce/pce.c
|
||||
picopce/psg.c
|
||||
picopce/render.c
|
||||
picopce/system.c
|
||||
picopce/vce.c
|
||||
picopce/vdc.c
|
||||
picopce/picopce.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if( ${TARGET} MATCHES "picopce" )
|
||||
set(PICOPCE_SOURCES
|
||||
picopce/emu.cpp
|
||||
|
|
@ -307,33 +292,6 @@ set(PICOMSX_SOURCES
|
|||
)
|
||||
endif()
|
||||
|
||||
if( ${TARGET} MATCHES "picogenold" )
|
||||
set(PICOGEN_SOURCES
|
||||
picogen/emu.cpp
|
||||
picogen/fm.c
|
||||
picogen/genesis.c
|
||||
picogen/io.c
|
||||
picogen/m68kcpu.c
|
||||
picogen/m68kopac.c
|
||||
picogen/m68kopdm.c
|
||||
picogen/m68kopnz.c
|
||||
picogen/m68kops_pre.c
|
||||
picogen/m68kops.c
|
||||
picogen/mem68k.c
|
||||
picogen/membnk.c
|
||||
picogen/memory.c
|
||||
picogen/memvdp.c
|
||||
picogen/memz80.c
|
||||
picogen/render.c
|
||||
picogen/sn76496.c
|
||||
picogen/sound.c
|
||||
picogen/system.c
|
||||
picogen/vdp.c
|
||||
picogen/z80.c
|
||||
picogen/picogen.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if( ${TARGET} MATCHES "picogen" )
|
||||
|
||||
set(PICOGEN_SOURCES
|
||||
|
|
|
|||
Binary file not shown.
BIN
MCUME_pico2/bin/usbhost/picogen.uf2
Normal file
BIN
MCUME_pico2/bin/usbhost/picogen.uf2
Normal file
Binary file not shown.
|
|
@ -8,7 +8,7 @@
|
|||
#define HAS_SND 1
|
||||
#define USE_VGA 1
|
||||
#define HAS_USBHOST 1
|
||||
#define HAS_USBPIO 1
|
||||
//#define HAS_USBPIO 1
|
||||
|
||||
//#define ILI9341 1
|
||||
//#define ST7789 1
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ extern int emu_oskbActive(void);
|
|||
|
||||
extern void emu_sndPlaySound(int chan, int volume, int freq);
|
||||
extern void emu_sndPlayBuzz(int size, int val);
|
||||
extern void * emu_sndGetBuffer(void);
|
||||
extern void emu_sndInit();
|
||||
extern void emu_resetus(void);
|
||||
extern int emu_us(void);
|
||||
|
|
|
|||
|
|
@ -1337,7 +1337,7 @@ static void pwm_audio_handle_buffer(void)
|
|||
}
|
||||
audio_sample *buf = audio_buffers[last_audio_buffer];
|
||||
last_audio_buffer = cur_audio_buffer;
|
||||
if (fillsamples != NULL) fillsamples(buf, snd_nb_samples);
|
||||
fillsamples(buf, snd_nb_samples);
|
||||
}
|
||||
|
||||
static void pwm_audio_reset(void)
|
||||
|
|
@ -1468,7 +1468,7 @@ static void pwm_audio_init(int buffersize, void (*callback)(audio_sample * strea
|
|||
|
||||
static void core1_func_tft() {
|
||||
while (true) {
|
||||
pwm_audio_handle_buffer();
|
||||
if (fillsamples != NULL) pwm_audio_handle_buffer();
|
||||
__dmb();
|
||||
}
|
||||
}
|
||||
|
|
@ -1482,6 +1482,13 @@ void PICO_DSP::begin_audio(int samplesize, void (*callback)(short * stream, int
|
|||
void PICO_DSP::end_audio()
|
||||
{
|
||||
}
|
||||
|
||||
void * PICO_DSP::get_buffer_audio(void)
|
||||
{
|
||||
void *buf = audio_buffers[cur_audio_buffer==0?1:0];
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ public:
|
|||
#ifdef HAS_SND
|
||||
void begin_audio(int samplesize, void (*callback)(short * stream, int len));
|
||||
void end_audio();
|
||||
void * get_buffer_audio();
|
||||
#endif
|
||||
|
||||
// framebuffer/screen operation
|
||||
|
|
|
|||
|
|
@ -45,6 +45,42 @@ int flash_load(const char * filename)
|
|||
return size;
|
||||
}
|
||||
|
||||
int flash_load_bswap(const char * filename)
|
||||
{
|
||||
uint32_t offset = HW_FLASH_STORAGE_BASE;
|
||||
int n;
|
||||
int size = 0;
|
||||
emu_printf("flash_load...");
|
||||
int f = emu_FileOpen(filename,"r+b");
|
||||
if (f) {
|
||||
while ( (offset < (HW_FLASH_STORAGE_TOP-FLASH_SECTOR_SIZE)) && (n = emu_FileRead(cache,FLASH_SECTOR_SIZE,f) ) ) {
|
||||
for (int i=0;i<n; i+=2) {
|
||||
uint8_t k = cache[i];
|
||||
cache[i]=cache[i+1];
|
||||
cache[i+1] = k;
|
||||
}
|
||||
//memcpy(cache, (unsigned char *)offset, n);
|
||||
uint32_t ints = save_and_disable_interrupts();
|
||||
flash_range_erase(offset, FLASH_SECTOR_SIZE);
|
||||
flash_range_program(offset, (const uint8_t *)&cache[0], FLASH_SECTOR_SIZE);
|
||||
restore_interrupts(ints);
|
||||
emu_printi(n);
|
||||
emu_printi(offset);
|
||||
//uint8_t * pt = (uint8_t*)(XIP_BASE + offset);
|
||||
//emu_printi(pt[0]);
|
||||
//emu_printi(pt[1]);
|
||||
//emu_printi(pt[2]);
|
||||
//emu_printi(pt[3]);
|
||||
offset += FLASH_SECTOR_SIZE;
|
||||
size += n;
|
||||
}
|
||||
emu_FileClose(f);
|
||||
emu_printf("flash_load OK.");
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int flash_verify(unsigned char * buf, int size)
|
||||
{
|
||||
unsigned char * datapt = (unsigned char *)(XIP_BASE + HW_FLASH_STORAGE_BASE);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ extern "C"
|
|||
extern unsigned char * flash_start;
|
||||
extern unsigned char * flash_end;
|
||||
extern int flash_load(const char * filename);
|
||||
extern int flash_load_bswap(const char * filename);
|
||||
extern int flash_verify(unsigned char * buf,int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ int main(void) {
|
|||
#ifdef HAS_USBPIO
|
||||
set_sys_clock_khz(140000, true);
|
||||
#else
|
||||
set_sys_clock_khz(250000, true);
|
||||
set_sys_clock_khz(280000, true);
|
||||
*((uint32_t *)(0x40010000+0x58)) = 2 << 16; //CLK_HSTX_DIV = 2 << 16; // HSTX clock/2
|
||||
#endif
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ int main(void) {
|
|||
emu_Init(filename);
|
||||
tft.startRefresh();
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_ms(25, repeating_timer_callback, NULL, &timer);
|
||||
add_repeating_timer_ms(20, repeating_timer_callback, NULL, &timer);
|
||||
while (true) {
|
||||
//uint16_t bClick = emu_DebounceLocalKeys();
|
||||
//emu_Input(bClick);
|
||||
|
|
@ -103,7 +103,9 @@ void emu_DrawVsync(void)
|
|||
#ifdef HAS_USBPIO
|
||||
#else
|
||||
#ifdef USE_VGA
|
||||
tft.waitSync();
|
||||
// tft.waitSync();
|
||||
volatile bool vb=vbl;
|
||||
while (vbl==vb) {};
|
||||
#else
|
||||
volatile bool vb=vbl;
|
||||
while (vbl==vb) {};
|
||||
|
|
|
|||
BIN
MCUME_pico2/picogen/.DS_Store
vendored
BIN
MCUME_pico2/picogen/.DS_Store
vendored
Binary file not shown.
|
|
@ -1,649 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../cpus/M68K/m68k.h"
|
||||
|
||||
#include "../sound/z80inst.h"
|
||||
#include "gwenesis_bus.h"
|
||||
|
||||
#include <gwenesis/sound/gwenesis_sn76489.h>
|
||||
#include <gwenesis/sound/ym2612.h>
|
||||
|
||||
#include "../io/gwenesis_io.h"
|
||||
#include "../vdp/gwenesis_vdp.h"
|
||||
#include "../savestate/gwenesis_savestate.h"
|
||||
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#define BUS_DISABLE_LOGGING 1
|
||||
|
||||
uint8_t GWENESIS_AUDIO_SAMPLING_DIVISOR = 6;
|
||||
|
||||
#if !BUS_DISABLE_LOGGING
|
||||
#include <stdarg.h>
|
||||
void bus_log(const char *subs, const char *fmt, ...) {
|
||||
extern int frame_counter;
|
||||
extern int scan_line;
|
||||
|
||||
va_list va;
|
||||
|
||||
printf("%06d:%03d :[%s] vc:%04x hc:%04x hv:%04x ", frame_counter, scan_line, subs,gwenesis_vdp_vcounter(),gwenesis_vdp_hcounter(),gwenesis_vdp_hvcounter());
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stdout, fmt, va);
|
||||
va_end(va);
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
#define bus_log(...)
|
||||
#endif
|
||||
|
||||
// Setup M68k memories ROM & RAM
|
||||
//#include "rom_manager.h"
|
||||
const unsigned char* ROM_DATA; // 68K Main Program (uncompressed)
|
||||
// const unsigned char* ROM_METADATA; // 68K Main Program (uncompressed)
|
||||
//unsigned char* M68K_RAM=(void *)(uint32_t)(0); // 68K RAM
|
||||
//unsigned char* M68K_RAM = NULL; // 68K RAM
|
||||
unsigned char M68K_RAM[MAX_RAM_SIZE]; // 68K RAM
|
||||
|
||||
// Setup Z80 Memory
|
||||
//unsigned char* ZRAM = NULL; // Z80 RAM
|
||||
unsigned char ZRAM[MAX_Z80_RAM_SIZE]; // Z80 RAM
|
||||
unsigned char TMSS[0x4];
|
||||
extern unsigned short gwenesis_vdp_status;
|
||||
|
||||
extern int audio_enabled;
|
||||
|
||||
// TMSS
|
||||
int tmss_state = 0;
|
||||
int tmss_count = 0;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Load a Sega Genesis Cartridge into CPU Memory
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void load_cartridge(uintptr_t rom) {
|
||||
ROM_DATA = (const unsigned char *)rom;
|
||||
// Clear all volatile memory
|
||||
memset(M68K_RAM, 0, MAX_RAM_SIZE);
|
||||
memset(ZRAM, 0, MAX_Z80_RAM_SIZE);
|
||||
|
||||
// Set Z80 Memory as Z80_RAM
|
||||
z80_set_memory(ZRAM);
|
||||
|
||||
z80_pulse_reset();
|
||||
|
||||
|
||||
set_region();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Power ON the CPU
|
||||
* Initialize 68K, Z80 and YM2612 Cores
|
||||
*
|
||||
******************************************************************************/
|
||||
void power_on() {
|
||||
// Set M68K CPU as original MOTOROLA 68000
|
||||
//m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
// Initialize M68K CPU
|
||||
m68k_init();
|
||||
// Initialize Z80 CPU
|
||||
z80_start();
|
||||
|
||||
// Initialize YM2612 chip
|
||||
YM2612Init();
|
||||
YM2612Config(9);
|
||||
// Initialize PSG SN76489 chip
|
||||
//CLOCK_NTSC = 3579545,
|
||||
//CLOCK_PAL = 3546895,
|
||||
// CLOCK_NTSC_SMS1 = 3579527
|
||||
|
||||
// if (mode_pal) {
|
||||
// gwenesis_SN76489_Init(3546895, GWENESIS_AUDIO_BUFFER_LENGTH_PAL*50,AUDIO_FREQ_DIVISOR);
|
||||
// } else{
|
||||
// gwenesis_SN76489_Init(3579545, GWENESIS_AUDIO_BUFFER_LENGTH_NTSC*60,AUDIO_FREQ_DIVISOR);
|
||||
// }
|
||||
|
||||
gwenesis_SN76489_Init(3579545, GWENESIS_AUDIO_BUFFER_LENGTH_NTSC * 60,AUDIO_FREQ_DIVISOR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Reset the CPU Emulation
|
||||
* Send a pulse reset to 68K, Z80 and YM2612 Cores
|
||||
*
|
||||
******************************************************************************/
|
||||
void reset_emulation() {
|
||||
// Send a reset pulse to Z80 CPU
|
||||
z80_pulse_reset();
|
||||
// Send a reset pulse to Z80 M68K
|
||||
m68k_pulse_reset();
|
||||
// Send a reset pulse to YM2612 chip
|
||||
YM2612ResetChip();
|
||||
|
||||
// Send a reset pulse to SEGA 315-5313 chip
|
||||
gwenesis_vdp_reset();
|
||||
gwenesis_SN76489_Reset();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Set Region
|
||||
* Look at ROM to set console compatible region
|
||||
*
|
||||
******************************************************************************/
|
||||
void set_region() {
|
||||
/*
|
||||
old style : JUE characters
|
||||
J : Domestic 60Hz (Asia)
|
||||
U : Oversea 60Hz (USA)
|
||||
E : Oversea 50Hz (Europe)
|
||||
|
||||
new style : 1st character
|
||||
bit 0 : +1 Domestic 60Hz (Asia)
|
||||
bit 1 : +2 Domestc 50Hz (Asia)
|
||||
bit 2: +4 Oversea 60Hz (USA)
|
||||
bit 3: +4 Oversea 50Hz (Europe)
|
||||
*/
|
||||
|
||||
// extern int mode_pal;
|
||||
|
||||
int country = 0;
|
||||
|
||||
char rom_str[3];
|
||||
|
||||
printf("ROM game : ");
|
||||
for (int j = 0; j < 48; j++) printf("%c", (char)FETCH8ROM(0x150+j));
|
||||
printf("\n");
|
||||
|
||||
rom_str[0] = FETCH8ROM(0x1F0);
|
||||
rom_str[1] = FETCH8ROM(0x1F1);
|
||||
rom_str[2] = FETCH8ROM(0x1F2);
|
||||
|
||||
printf("ROM region:%c%c%c (0x%02x 0x%02x 0x%02x)\n", rom_str[0], rom_str[1], rom_str[2], rom_str[0], rom_str[1],
|
||||
rom_str[2]);
|
||||
|
||||
/* from Gens */
|
||||
if (!memcmp(rom_str, "eur", 3)) country |= 8;
|
||||
else if (!memcmp(rom_str, "EUR", 3)) country |= 8;
|
||||
else if (!memcmp(rom_str, "Europe", 3)) country |= 8;
|
||||
else if (!memcmp(rom_str, "jap", 3)) country |= 1;
|
||||
else if (!memcmp(rom_str, "JAP", 3)) country |= 1;
|
||||
else if (!memcmp(rom_str, "usa", 3)) country |= 4;
|
||||
else if (!memcmp(rom_str, "USA", 3)) country |= 4;
|
||||
else {
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
/* look for each characters */
|
||||
for (i = 0; i < 3; i++) {
|
||||
c = rom_str[i];
|
||||
|
||||
if (c == 'E' || c == 'e') country |= 8;
|
||||
else if (c == 'U') country |= 4;
|
||||
else if (c == 'J' || c == 'j') country |= 1;
|
||||
else if (c == 'K' || c == 'k') country |= 1;
|
||||
else if (c < 16) country |= c;
|
||||
else if ((c >= '0') && (c <= '9')) country |= c - '0';
|
||||
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
|
||||
}
|
||||
}
|
||||
printf("country code=%01x : ", country);
|
||||
/* set default console region (USA > EUROPE > JAPAN) */
|
||||
/*
|
||||
IO REG0 : MODE VMOD DISK RSV VER3 VER2 VER1 VER0
|
||||
MODE (R) 0: Domestic Model
|
||||
1: Overseas Model
|
||||
VMOD (R) 0: NTSC CPU clock 7.67 MHz
|
||||
1: PAL CPU clock 7.60 MHz
|
||||
*/
|
||||
|
||||
/* EUROPE 50Hz */
|
||||
if (country & 8) {
|
||||
printf("Oversea-PAL Europe 50Hz\n");
|
||||
gwenesis_io_set_reg(0, 0xC1);
|
||||
// gwenesis_vdp_status |= 0x1;
|
||||
//mode_pal = 1;
|
||||
return;
|
||||
}
|
||||
/* USA 60Hz*/
|
||||
if (country & 4) {
|
||||
printf("Oversea-NTSC USA 60Hz\n");
|
||||
gwenesis_io_set_reg(0, 0x81);
|
||||
// gwenesis_vdp_status &= 0xFFFE;
|
||||
// mode_pal = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* set Asia 60HZ */
|
||||
if (country & 1) {
|
||||
printf("Domestic-NTSC Asia 60Hz\n");
|
||||
gwenesis_io_set_reg(0, 0x1);
|
||||
// gwenesis_vdp_status &= 0xFFFE;
|
||||
//mode_pal = 0;
|
||||
return;
|
||||
}
|
||||
printf("Oversea-NTSC USA 60Hz no detection>> default mode\n");
|
||||
gwenesis_io_set_reg(0, 0x81);
|
||||
// gwenesis_vdp_status &= 0xFFFE;
|
||||
// mode_pal = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Main memory address mapper
|
||||
* Map all main memory region address for CPU program
|
||||
* 68K Access to Z80 Memory
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline unsigned int gwenesis_bus_map_z80_address(unsigned int address) {
|
||||
unsigned int range = (address & 0xF000);
|
||||
switch (range) {
|
||||
case 0:
|
||||
case 0x1000:
|
||||
return Z80_RAM_ADDR;
|
||||
case 0x2000:
|
||||
case 0x3000:
|
||||
return Z80_RAM_ADDR1K;
|
||||
case 0x4000:
|
||||
return Z80_YM2612_ADDR;
|
||||
case 0x6000:
|
||||
return Z80_BANK_ADDR;
|
||||
case 0x7000:
|
||||
return Z80_SN76489_ADDR;
|
||||
default:
|
||||
bus_log(__FUNCTION__, "no map Z80 %x", address);
|
||||
assert(0);
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* IO memory address mapper
|
||||
* Map all input/output region address for CPU program
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline unsigned int gwenesis_bus_map_io_address(unsigned int address) {
|
||||
unsigned int range = (address & 0x1000);
|
||||
switch (range) {
|
||||
case 0: return IO_CTRL;
|
||||
case 0x1000: return Z80_CTRL;
|
||||
default:
|
||||
// if (address >= 0xa14000 && address < 0xa11404)
|
||||
// return (tmss_state == 0) ? TMSS_CTRL : NONE;
|
||||
bus_log(__FUNCTION__, "no map io %x", address);
|
||||
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Main memory address mapper
|
||||
* Map all main memory region address for CPU program
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static inline
|
||||
unsigned int gwenesis_bus_map_address(unsigned int address) {
|
||||
// Mask address page
|
||||
unsigned int range = (address & 0xFF0000) >> 16;
|
||||
|
||||
// Check mask and select memory type
|
||||
if (range < 0x80) // ROM ADDRESS 0x000000 - 0x3FFFFF
|
||||
return ROM_ADDR;
|
||||
if (range == 0xA0) // Z80 ADDRESS 0xA00000 - 0xA0FFFF
|
||||
return gwenesis_bus_map_z80_address(address);
|
||||
if (range == 0xA1) // IO ADDRESS 0xA10000 - 0xA1FFFF
|
||||
return gwenesis_bus_map_io_address(address);
|
||||
if (range == 0xC0) // VDP ADDRESS 0xC00000 - 0xDFFFFFF
|
||||
return VDP_ADDR;
|
||||
if (range == 0xFF) // RAM ADDRESS 0xE00000 - 0xFFFFFFF
|
||||
return RAM_ADDR;
|
||||
|
||||
|
||||
// If not a valid address return 0
|
||||
bus_log(__FUNCTION__, "M68K > ?? unnmap address %x", address);
|
||||
//assert(0);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Main read address routine
|
||||
* Write an value to memory mapped on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline unsigned int gwenesis_bus_read_memory_8(unsigned int address) {
|
||||
bus_log(__FUNCTION__, "read8 %x", address);
|
||||
|
||||
switch (gwenesis_bus_map_address(address)) {
|
||||
case VDP_ADDR:
|
||||
return gwenesis_vdp_read_memory_8(address);
|
||||
|
||||
case ROM_ADDR:
|
||||
return FETCH8ROM(address);
|
||||
|
||||
case RAM_ADDR:
|
||||
return FETCH8RAM(address);
|
||||
|
||||
case IO_CTRL:
|
||||
return gwenesis_io_read_ctrl(address & 0x1F);
|
||||
|
||||
case Z80_CTRL:
|
||||
return z80_read_ctrl(address & 0xFFFF);
|
||||
|
||||
case Z80_RAM_ADDR:
|
||||
case Z80_RAM_ADDR1K:
|
||||
return ZRAM[address & 0x1FFF];
|
||||
|
||||
case Z80_YM2612_ADDR:
|
||||
return audio_enabled ? YM2612Read(m68k_cycles_master()) : 0x00;
|
||||
|
||||
case Z80_SN76489_ADDR:
|
||||
return 0xff;
|
||||
|
||||
case Z80_BANK_ADDR:
|
||||
return 0xff;
|
||||
|
||||
case TMSS_CTRL:
|
||||
bus_log(__FUNCTION__, "TMS");
|
||||
if (tmss_state == 0)
|
||||
return TMSS[address & 0x4];
|
||||
return 0xFF;
|
||||
|
||||
default:
|
||||
bus_log(__FUNCTION__, " default read 8 %x", address);
|
||||
return 0x00;
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static inline unsigned int gwenesis_bus_read_memory_16(unsigned int address) {
|
||||
bus_log(__FUNCTION__, "read16 %x", address);
|
||||
|
||||
switch (gwenesis_bus_map_address(address)) {
|
||||
case VDP_ADDR:
|
||||
return gwenesis_vdp_read_memory_16(address);
|
||||
|
||||
case RAM_ADDR:
|
||||
return FETCH16RAM(address);
|
||||
|
||||
case ROM_ADDR:
|
||||
return FETCH16ROM(address);
|
||||
|
||||
case IO_CTRL:
|
||||
return gwenesis_io_read_ctrl(address & 0x1F);
|
||||
|
||||
case Z80_CTRL:
|
||||
// ret_value = z80_read_ctrl(address & 0xFFFF);
|
||||
// return ret_value | ret_value << 8;
|
||||
address &= 0xFFFF;
|
||||
return (z80_read_ctrl(address) << 8) | z80_read_ctrl(address | 1);
|
||||
|
||||
|
||||
case Z80_RAM_ADDR:
|
||||
case Z80_RAM_ADDR1K:
|
||||
return ZRAM[address & 0X1FFF] | (ZRAM[address & 0X1FFF] << 8);
|
||||
|
||||
case Z80_YM2612_ADDR: {
|
||||
if (audio_enabled) {
|
||||
unsigned int ret_value = YM2612Read(m68k_cycles_master());
|
||||
return ret_value | ret_value << 8;
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
case Z80_SN76489_ADDR:
|
||||
return 0xff;
|
||||
|
||||
case Z80_BANK_ADDR:
|
||||
return 0xff;
|
||||
|
||||
default:
|
||||
bus_log(__FUNCTION__, "read mem 16 default %x", address);
|
||||
return (gwenesis_bus_read_memory_8(address) << 8) |
|
||||
gwenesis_bus_read_memory_8(address + 1);
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Main write address routine
|
||||
* Write an value to memory mapped on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline void gwenesis_bus_write_memory_8(unsigned int address,
|
||||
unsigned int value) {
|
||||
bus_log(__FUNCTION__, "write8 @%x:%x", address, value);
|
||||
|
||||
switch (gwenesis_bus_map_address(address)) {
|
||||
case VDP_ADDR:
|
||||
gwenesis_vdp_write_memory_16(address & ~1, (value << 8) | value);
|
||||
return;
|
||||
|
||||
case RAM_ADDR:
|
||||
WRITE8RAM(address, value);
|
||||
return;
|
||||
|
||||
case IO_CTRL:
|
||||
gwenesis_io_write_ctrl(address & 0x1F, value);
|
||||
return;
|
||||
|
||||
case Z80_CTRL:
|
||||
z80_write_ctrl(address & 0x1FFF, value);
|
||||
return;
|
||||
|
||||
case Z80_RAM_ADDR:
|
||||
case Z80_RAM_ADDR1K:
|
||||
ZRAM[address & 0x1FFF] = value;
|
||||
return;
|
||||
|
||||
case Z80_YM2612_ADDR:
|
||||
bus_log(__FUNCTION__, "CPUZ80PSG8 ,m68kclk= %d", m68k_cycles_master());
|
||||
if (audio_enabled)
|
||||
YM2612Write(address & 0x3, value & 0Xff, m68k_cycles_master());
|
||||
|
||||
return;
|
||||
|
||||
case Z80_SN76489_ADDR:
|
||||
bus_log(__FUNCTION__, "CPUZ80FM8 ,m68kclk= %d", m68k_cycles_master());
|
||||
if (audio_enabled)
|
||||
gwenesis_SN76489_Write(value & 0Xff, m68k_cycles_master());
|
||||
return;
|
||||
|
||||
case Z80_BANK_ADDR:
|
||||
//TODO
|
||||
return;
|
||||
|
||||
case TMSS_CTRL:
|
||||
|
||||
if (tmss_state == 0) {
|
||||
TMSS[address & 0x4] = value;
|
||||
tmss_count++;
|
||||
if (tmss_count == 4)
|
||||
tmss_state = 1;
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
default:
|
||||
//printf("write(%x, %x)\n", address, value);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
extern bool sn76489_enabled;
|
||||
|
||||
static inline void gwenesis_bus_write_memory_16(unsigned int address,
|
||||
unsigned int value) {
|
||||
bus_log(__FUNCTION__, "write16 @%x:%x", address, value);
|
||||
|
||||
switch (gwenesis_bus_map_address(address)) {
|
||||
case VDP_ADDR:
|
||||
gwenesis_vdp_write_memory_16(address, value);
|
||||
return;
|
||||
|
||||
case RAM_ADDR:
|
||||
WRITE16RAM(address, value);
|
||||
return;
|
||||
|
||||
case Z80_RAM_ADDR:
|
||||
case Z80_RAM_ADDR1K:
|
||||
ZRAM[address & 0X1FFF] = value >> 8;
|
||||
return;
|
||||
|
||||
case IO_CTRL:
|
||||
gwenesis_io_write_ctrl(address & 0x1F, value);
|
||||
return;
|
||||
|
||||
case Z80_CTRL:
|
||||
z80_write_ctrl(address & 0xFFFF, value >> 8);
|
||||
return;
|
||||
|
||||
case Z80_YM2612_ADDR:
|
||||
bus_log(__FUNCTION__, "CZYM16 ,mclk=%d", m68k_cycles_master());
|
||||
if (audio_enabled)
|
||||
YM2612Write(address & 0x3, value >> 8, m68k_cycles_master());
|
||||
|
||||
return;
|
||||
|
||||
case Z80_SN76489_ADDR:
|
||||
bus_log(__FUNCTION__, "CZSN16 ,mclk=%d", m68k_cycles_master());
|
||||
if (audio_enabled && sn76489_enabled)
|
||||
gwenesis_SN76489_Write(value >> 8, m68k_cycles_master());
|
||||
return;
|
||||
|
||||
default:
|
||||
bus_log(__FUNCTION__, "write mem 16 default %x ", address);
|
||||
gwenesis_bus_write_memory_8(address, (value >> 8) & 0xff);
|
||||
gwenesis_bus_write_memory_8(address + 1, (value) & 0xff);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU read address R8
|
||||
* Read an address from memory mapped and return value as byte
|
||||
*
|
||||
******************************************************************************/
|
||||
unsigned int m68k_read_memory_8(unsigned int address) {
|
||||
// if ((address & 0xFF0000 ) == 0xFF0000) return FETCH8RAM(address);
|
||||
return gwenesis_bus_read_memory_8(address);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU read address R16
|
||||
* Read an address from memory mapped and return value as word
|
||||
*
|
||||
******************************************************************************/
|
||||
unsigned int m68k_read_memory_16(unsigned int address) {
|
||||
// if ((address & 0xFF0000 ) == 0xFF0000) return FETCH16RAM(address);
|
||||
return gwenesis_bus_read_memory_16(address);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU read address R32
|
||||
* Read an address from memory mapped and return value as long
|
||||
*
|
||||
******************************************************************************/
|
||||
unsigned int m68k_read_memory_32(unsigned int address) {
|
||||
// if ((address & 0xFF0000 ) == 0xFF0000) return FETCH32RAM(address);
|
||||
return (gwenesis_bus_read_memory_16(address) << 16) | gwenesis_bus_read_memory_16(address + 2);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU write address W8
|
||||
* Write an value as byte to memory mapped on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value) {
|
||||
// if ((address & 0xFF0000) == 0xFF0000) {
|
||||
// WRITE8RAM(address, value);
|
||||
// return;
|
||||
// }
|
||||
gwenesis_bus_write_memory_8(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU write address W16
|
||||
* Write an value as word to memory mapped on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value) {
|
||||
// if ((address & 0xFF0000) == 0xFF0000) {
|
||||
// WRITE16RAM(address, value);
|
||||
// return;
|
||||
// }
|
||||
gwenesis_bus_write_memory_16(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 68K CPU write address W32
|
||||
* Write an value as word to memory mapped on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value) {
|
||||
// if ((address & 0xFF0000) == 0xFF0000) {
|
||||
// WRITE32RAM(address, value);
|
||||
// return;
|
||||
// }
|
||||
gwenesis_bus_write_memory_16(address, (value >> 16) & 0xffff);
|
||||
gwenesis_bus_write_memory_16(address + 2, (value) & 0xffff);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int m68k_read_disassembler_16(unsigned int address) {
|
||||
return m68k_read_memory_16(address);
|
||||
}
|
||||
|
||||
unsigned int m68k_read_disassembler_32(unsigned int address) {
|
||||
return m68k_read_memory_32(address);
|
||||
}
|
||||
|
||||
void gwenesis_bus_save_state() {
|
||||
|
||||
}
|
||||
|
||||
void gwenesis_bus_load_state() {
|
||||
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#ifndef _gwenesis_bus_H_
|
||||
#define _gwenesis_bus_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_ROM_SIZE 0x800000
|
||||
#define MAX_RAM_SIZE 0x10000
|
||||
#define MAX_Z80_RAM_SIZE 8192
|
||||
|
||||
// NTSC PAL timings
|
||||
#define MCLOCK_PAL 53203424
|
||||
#define MCLOCK_NTSC 53693175
|
||||
|
||||
#define MCYCLES_PER_FRAME_NTSC 896040
|
||||
#define MCYCLES_PER_FRAME_PAL 1067040
|
||||
#define LINES_PER_FRAME_NTSC 262
|
||||
#define LINES_PER_FRAME_PAL 313
|
||||
|
||||
#define GWENESIS_REFRESH_RATE_NTSC 60
|
||||
#define GWENESIS_AUDIO_FREQ_NTSC 53267
|
||||
|
||||
#define GWENESIS_REFRESH_RATE_PAL 50
|
||||
#define GWENESIS_AUDIO_FREQ_PAL 52781
|
||||
|
||||
#define Z80_FREQ_DIVISOR 14 // Frequency divisor to Z80 clock
|
||||
#define VDP_CYCLES_PER_LINE 3420// VDP Cycles per Line
|
||||
#define GWENESIS_SCREEN_WIDTH 320
|
||||
#define GWENESIS_SCREEN_HEIGHT 240
|
||||
|
||||
extern uint8_t GWENESIS_AUDIO_SAMPLING_DIVISOR; // Audio quality (i.e. sampling rate) 1: best ... 10: poor
|
||||
|
||||
#define AUDIO_FREQ_DIVISOR 1009 //1009
|
||||
#define GWENESIS_AUDIO_BUFFER_LENGTH_NTSC 888
|
||||
#define GWENESIS_AUDIO_BUFFER_LENGTH_PAL 1056
|
||||
|
||||
/* Audio buffer length */
|
||||
|
||||
enum mapped_address
|
||||
{
|
||||
NONE = 0,
|
||||
ROM_ADDR,
|
||||
ROM_ADDR_MIRROR,
|
||||
Z80_RAM_ADDR,
|
||||
Z80_RAM_ADDR1K,
|
||||
Z80_YM2612_ADDR,
|
||||
Z80_BANK_ADDR,
|
||||
Z80_VDP_ADDR,
|
||||
Z80_SN76489_ADDR,
|
||||
IO_CTRL,
|
||||
Z80_CTRL,
|
||||
TMSS_CTRL,
|
||||
VDP_ADDR,
|
||||
RAM_ADDR
|
||||
};
|
||||
|
||||
enum gwenesis_bus_pad_button
|
||||
{
|
||||
PAD_UP,
|
||||
PAD_DOWN,
|
||||
PAD_LEFT,
|
||||
PAD_RIGHT,
|
||||
PAD_B,
|
||||
PAD_C,
|
||||
PAD_A,
|
||||
PAD_S,
|
||||
};
|
||||
|
||||
void load_cartridge(uintptr_t rom);
|
||||
|
||||
void power_on();
|
||||
void reset_emulation();
|
||||
void set_region();
|
||||
|
||||
void gwenesis_bus_save_state();
|
||||
void gwenesis_bus_load_state();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,462 +0,0 @@
|
|||
#ifndef M68K__HEADER
|
||||
#define M68K__HEADER
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.32
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other licensing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
* http://kstenerud.cjb.net
|
||||
*/
|
||||
|
||||
/* Modified by Eke-Eke for Genesis Plus GX:
|
||||
|
||||
- removed unused stuff to reduce memory usage / optimize execution (multiple CPU types support, NMI support, ...)
|
||||
- moved stuff to compile statically in a single object file
|
||||
- implemented support for global cycle count (shared by 68k & Z80 CPU)
|
||||
- added support for interrupt latency (Sesame's Street Counting Cafe, Fatal Rewind)
|
||||
- added proper cycle use on reset
|
||||
- added cycle accurate timings for MUL/DIV instructions (thanks to Jorge Cwik !)
|
||||
- fixed undocumented flags for DIV instructions (Blood Shot)
|
||||
- fixed undocumented behaviors for ABCD/SBCD/NBCD instructions (thanks to flamewing for his test ROM)
|
||||
- improved auto-vectored interrupts acknowledge cycle timing accuracy
|
||||
- added MAIN-CPU & SUB-CPU support for Mega CD emulation
|
||||
|
||||
*/
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "macros.h"
|
||||
#ifdef HOOK_CPU
|
||||
#include "cpuhook.h"
|
||||
#endif
|
||||
//#include <avr/pgmspace.h>
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Check for > 32bit sizes */
|
||||
#if UINT_MAX > 0xffffffff
|
||||
#define M68K_INT_GT_32_BIT 1
|
||||
#else
|
||||
#define M68K_INT_GT_32_BIT 0
|
||||
#endif
|
||||
|
||||
/* Data types used in this emulation core */
|
||||
#undef sint8
|
||||
#undef sint16
|
||||
#undef sint32
|
||||
#undef sint64
|
||||
#undef uint8
|
||||
#undef uint16
|
||||
#undef uint32
|
||||
#undef uint64
|
||||
#undef sint
|
||||
#undef uint
|
||||
|
||||
#define sint8 signed char /* ASG: changed from char to signed char */
|
||||
#define sint16 signed short
|
||||
#define sint32 signed int /* AWJ: changed from long to int */
|
||||
#define uint8 unsigned char
|
||||
#define uint16 unsigned short
|
||||
#define uint32 unsigned int /* AWJ: changed from long to int */
|
||||
|
||||
/* signed and unsigned int must be at least 32 bits wide */
|
||||
#define sint signed int
|
||||
//#define uint unsigned int
|
||||
|
||||
|
||||
#if M68K_USE_64_BIT
|
||||
#define sint64 signed long long
|
||||
#define uint64 unsigned long long
|
||||
#else
|
||||
#define sint64 sint32
|
||||
#define uint64 uint32
|
||||
#endif /* M68K_USE_64_BIT */
|
||||
|
||||
|
||||
|
||||
/* Allow for architectures that don't have 8-bit sizes */
|
||||
/*#if UCHAR_MAX == 0xff*/
|
||||
#define MAKE_INT_8(A) (sint8)(A)
|
||||
/*#else
|
||||
#undef sint8
|
||||
#define sint8 signed int
|
||||
#undef uint8
|
||||
#define uint8 unsigned int
|
||||
INLINE sint MAKE_INT_8(uint value)
|
||||
{
|
||||
return (value & 0x80) ? value | ~0xff : value & 0xff;
|
||||
}*/
|
||||
/*#endif *//* UCHAR_MAX == 0xff */
|
||||
|
||||
|
||||
/* Allow for architectures that don't have 16-bit sizes */
|
||||
/*#if USHRT_MAX == 0xffff*/
|
||||
#define MAKE_INT_16(A) (sint16)(A)
|
||||
/*#else
|
||||
#undef sint16
|
||||
#define sint16 signed int
|
||||
#undef uint16
|
||||
#define uint16 unsigned int
|
||||
INLINE sint MAKE_INT_16(uint value)
|
||||
{
|
||||
return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
|
||||
}*/
|
||||
/*#endif *//* USHRT_MAX == 0xffff */
|
||||
|
||||
|
||||
/* Allow for architectures that don't have 32-bit sizes */
|
||||
/*#if UINT_MAX == 0xffffffff*/
|
||||
#define MAKE_INT_32(A) (sint32)(A)
|
||||
/*#else
|
||||
#undef sint32
|
||||
#define sint32 signed int
|
||||
#undef uint32
|
||||
#define uint32 unsigned int
|
||||
INLINE sint MAKE_INT_32(uint value)
|
||||
{
|
||||
return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
|
||||
}*/
|
||||
/*#endif *//* UINT_MAX == 0xffffffff */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ GENERAL DEFINES =========================== */
|
||||
/*** BZHXX ***/
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#define ROM_SWAP
|
||||
#define RAM_SWAP
|
||||
|
||||
// 8/16/32 bits access to RAM/ROM
|
||||
|
||||
extern const unsigned char *ROM_DATA;
|
||||
extern const unsigned char *ROM_METADATA;
|
||||
//extern unsigned char* M68K_RAM;
|
||||
extern unsigned char M68K_RAM[];
|
||||
|
||||
// ROM needs to be converted for this to work!
|
||||
#define FETCH8ROM(A) (unsigned char) ROM_DATA[ A^1 ]
|
||||
#define FETCH16ROM(A) ( (unsigned short) (*((unsigned short *) &ROM_DATA[A])) )
|
||||
#define FETCH32ROM(A) ( (*(unsigned short *)(&ROM_DATA[(A+2)])) | ((*(unsigned short *)(&ROM_DATA[A])) << 16))
|
||||
|
||||
#define FETCH8RAM(A) (unsigned char) M68K_RAM[ (A ^ 1) & 0xFFFF]
|
||||
#define FETCH16RAM(A) ( (unsigned short) (*((unsigned short *) &M68K_RAM[A&0XFFFF])) )
|
||||
#define FETCH32RAM(A) ( (*(unsigned short *)(&M68K_RAM[(A+2)&0XFFFF])) | ((*(unsigned short *)(&M68K_RAM[A&0XFFFF])) << 16))
|
||||
|
||||
#define WRITE8RAM(A, V) M68K_RAM[ (A ^ 1) & 0xFFFF ] = V
|
||||
#define WRITE16RAM(A, V) ( *((unsigned short *) &M68K_RAM[ A & 0XFFFF ]) = V )
|
||||
// RAM needs to be cyclically accessible (i.e. addresses wrap around)
|
||||
#define WRITE32RAM(A, V) ( *((unsigned short *) &M68K_RAM[ A & 0XFFFF ]) = V >> 16); \
|
||||
( *((unsigned short *) &M68K_RAM[ (A + 2) & 0XFFFF ]) = V & 0xffff); \
|
||||
|
||||
#define m68k_read_immediate_16(A) ( ( (A) & 0x800000) ? FETCH16RAM((A)) : FETCH16ROM((A)) )
|
||||
#define m68k_read_immediate_32(A) ( ( (A) & 0x800000) ? FETCH32RAM((A)) : FETCH32ROM((A)) )
|
||||
|
||||
#define m68k_read_pcrelative_8(A) ( FETCH8ROM((A)) )
|
||||
#define m68k_read_pcrelative_16(A) ( FETCH16ROM((A)) )
|
||||
#define m68k_read_pcrelative_32(A) ( FETCH32ROM((A)) )
|
||||
|
||||
/* Read from anywhere */
|
||||
unsigned int m68k_read_memory_8(unsigned int address);
|
||||
unsigned int m68k_read_memory_16(unsigned int address);
|
||||
unsigned int m68k_read_memory_32(unsigned int address);
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
// unsigned int m68k_read_immediate_16(unsigned int address);
|
||||
// unsigned int m68k_read_immediate_32(unsigned int address);
|
||||
|
||||
/* Read data relative to the PC */
|
||||
//unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||
//unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||
//unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||
|
||||
/* Memory access for the disassembler */
|
||||
unsigned int m68k_read_disassembler_8 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_16 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_32 (unsigned int address);
|
||||
|
||||
/* Write to anywhere */
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
/*** BZHXX ***/
|
||||
/* ======================================================================== */
|
||||
|
||||
/* There are 7 levels of interrupt to the 68K.
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
*/
|
||||
#define M68K_IRQ_NONE 0
|
||||
#define M68K_IRQ_1 1
|
||||
#define M68K_IRQ_2 2
|
||||
#define M68K_IRQ_3 3
|
||||
#define M68K_IRQ_4 4
|
||||
#define M68K_IRQ_5 5
|
||||
#define M68K_IRQ_6 6
|
||||
#define M68K_IRQ_7 7
|
||||
|
||||
|
||||
/* Special interrupt acknowledge values.
|
||||
* Use these as special returns from the interrupt acknowledge callback
|
||||
* (specified later in this header).
|
||||
*/
|
||||
|
||||
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
|
||||
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
|
||||
* acknowledge cycle instead of DTACK.
|
||||
*/
|
||||
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
|
||||
|
||||
/* Causes the spurious interrupt vector (0x18) to be taken
|
||||
* This happens in a real 68K if BERR is asserted during the interrupt
|
||||
* acknowledge cycle (i.e. no devices responded to the acknowledge).
|
||||
*/
|
||||
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
|
||||
|
||||
|
||||
/* Registers used by m68k_get_reg() and m68k_set_reg() */
|
||||
typedef enum
|
||||
{
|
||||
/* Real registers */
|
||||
M68K_REG_D0, /* Data registers */
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0, /* Address registers */
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC, /* Program Counter */
|
||||
M68K_REG_SR, /* Status Register */
|
||||
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||
M68K_REG_USP, /* User Stack Pointer */
|
||||
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
/* Assumed registers */
|
||||
/* These are cheat registers which emulate the 1-longword prefetch
|
||||
* present in the 68000 and 68010.
|
||||
*/
|
||||
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||
#endif
|
||||
|
||||
/* Convenience registers */
|
||||
M68K_REG_IR /* Instruction register */
|
||||
} m68k_register_t;
|
||||
|
||||
|
||||
/* 68k memory map structure */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *base; /* memory-based access (ROM, RAM) */
|
||||
unsigned int (*read8)(unsigned int address); /* I/O byte read access */
|
||||
unsigned int (*read16)(unsigned int address); /* I/O word read access */
|
||||
void (*write8)(unsigned int address, unsigned int data); /* I/O byte write access */
|
||||
void (*write16)(unsigned int address, unsigned int data); /* I/O word write access */
|
||||
} cpu_memory_map;
|
||||
|
||||
/* 68k idle loop detection */
|
||||
typedef struct
|
||||
{
|
||||
uint pc;
|
||||
uint cycle;
|
||||
uint detected;
|
||||
} cpu_idle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cpu_memory_map memory_map[256]; /* memory mapping */
|
||||
|
||||
cpu_idle_t poll; /* polling detection */
|
||||
|
||||
uint cycles; /* current master cycle count */
|
||||
uint cycle_end; /* aimed master cycle count for current execution frame */
|
||||
|
||||
uint dar[16]; /* Data and Address Registers */
|
||||
uint pc; /* Program Counter */
|
||||
uint sp[5]; /* User and Interrupt Stack Pointers */
|
||||
uint ir; /* Instruction Register */
|
||||
uint t1_flag; /* Trace 1 */
|
||||
uint s_flag; /* Supervisor */
|
||||
uint x_flag; /* Extend */
|
||||
uint n_flag; /* Negative */
|
||||
uint not_z_flag; /* Zero, inverted for speedups */
|
||||
uint v_flag; /* Overflow */
|
||||
uint c_flag; /* Carry */
|
||||
uint int_mask; /* I0-I2 */
|
||||
uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
|
||||
uint stopped; /* Stopped state */
|
||||
|
||||
uint pref_addr; /* Last prefetch address */
|
||||
uint pref_data; /* Data in the prefetch queue */
|
||||
|
||||
uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
||||
uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
||||
uint aerr_enabled; /* Enables/deisables address error checks at runtime */
|
||||
jmp_buf aerr_trap; /* Address error jump */
|
||||
uint aerr_address; /* Address error location */
|
||||
uint aerr_write_mode; /* Address error write mode */
|
||||
uint aerr_fc; /* Address error FC code */
|
||||
|
||||
uint tracing; /* Tracing enable flag */
|
||||
|
||||
uint address_space; /* Current FC code */
|
||||
|
||||
#ifdef M68K_OVERCLOCK_SHIFT
|
||||
int cycle_ratio;
|
||||
#endif
|
||||
|
||||
/* Callbacks to host */
|
||||
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
|
||||
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
|
||||
int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */
|
||||
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
|
||||
} m68ki_cpu_core;
|
||||
|
||||
/* CPU cores */
|
||||
extern m68ki_cpu_core m68k;
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== CALLBACKS =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* These functions allow you to set callbacks to the host when specific events
|
||||
* occur. Note that you must enable the corresponding value in m68kconf.h
|
||||
* in order for these to do anything useful.
|
||||
* Note: I have defined default callbacks which are used if you have enabled
|
||||
* the corresponding #define in m68kconf.h but either haven't assigned a
|
||||
* callback or have assigned a callback of NULL.
|
||||
*/
|
||||
|
||||
#if M68K_EMULATE_INT_ACK == OPT_ON
|
||||
/* Set the callback for an interrupt acknowledge.
|
||||
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
|
||||
* The CPU will call the callback with the interrupt level being acknowledged.
|
||||
* The host program must return either a vector from 0x02-0xff, or one of the
|
||||
* special interrupt acknowledge values specified earlier in this header.
|
||||
* If this is not implemented, the CPU will always assume an autovectored
|
||||
* interrupt, and will automatically clear the interrupt request when it
|
||||
* services the interrupt.
|
||||
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
|
||||
*/
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level));
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_RESET == OPT_ON
|
||||
/* Set the callback for the RESET instruction.
|
||||
* You must enable M68K_EMULATE_RESET in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a RESET instruction.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void));
|
||||
#endif
|
||||
|
||||
#if M68K_TAS_HAS_CALLBACK == OPT_ON
|
||||
/* Set the callback for the TAS instruction.
|
||||
* You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a TAS instruction.
|
||||
* Default behavior: return 1, allow writeback.
|
||||
*/
|
||||
void m68k_set_tas_instr_callback(int (*callback)(void));
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_FC == OPT_ON
|
||||
/* Set the callback for CPU function code changes.
|
||||
* You must enable M68K_EMULATE_FC in m68kconf.h.
|
||||
* The CPU calls this callback with the function code before every memory
|
||||
* access to set the CPU's function code according to what kind of memory
|
||||
* access it is (supervisor/user, program/data and such).
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Do whatever initialisations the core requires. Should be called
|
||||
* at least once at init time.
|
||||
*/
|
||||
extern void m68k_init(void);
|
||||
|
||||
/* Pulse the RESET pin on the CPU.
|
||||
* You *MUST* reset the CPU at least once to initialize the emulation
|
||||
*/
|
||||
extern void m68k_pulse_reset(void);
|
||||
|
||||
/* Run until given cycle count is reached */
|
||||
extern void m68k_run(unsigned int cycles);
|
||||
|
||||
/* Get current instruction execution time */
|
||||
extern int m68k_cycles(void);
|
||||
|
||||
/* Number of cycles run so far from start of frame */
|
||||
extern int m68k_cycles_master(void);
|
||||
|
||||
/* Number of cycles run so far from run call */
|
||||
extern int m68k_cycles_run(void);
|
||||
|
||||
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
* Setting IRQ to 0 will clear an interrupt request.
|
||||
*/
|
||||
extern void m68k_set_irq(unsigned int int_level);
|
||||
extern void m68k_set_irq_delay(unsigned int int_level);
|
||||
extern void m68k_update_irq(unsigned int mask);
|
||||
|
||||
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||
extern void m68k_pulse_halt(void);
|
||||
extern void m68k_clear_halt(void);
|
||||
|
||||
/* Peek at the internals of a CPU context. This can either be a context
|
||||
* retrieved using m68k_get_context() or the currently running context.
|
||||
* If context is NULL, the currently running CPU context will be used.
|
||||
*/
|
||||
extern unsigned int m68k_get_reg(m68k_register_t reg);
|
||||
|
||||
/* Poke values into the internals of the currently running CPU context */
|
||||
extern void m68k_set_reg(m68k_register_t reg, unsigned int value);
|
||||
|
||||
/* Load/Save state of CPU */
|
||||
extern void gwenesis_m68k_save_state();
|
||||
extern void gwenesis_m68k_load_state();
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68K__HEADER */
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
#ifndef M68KCONF__HEADER
|
||||
#define M68KCONF__HEADER
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ======================== MAIN 68K CONFIGURATION ======================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Configuration switches.
|
||||
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
|
||||
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
|
||||
* or macro you specify, rather than using callback functions whose pointer
|
||||
* must be passed in using m68k_set_xxx_callback().
|
||||
*/
|
||||
#define OPT_OFF 0
|
||||
#define OPT_ON 1
|
||||
#define OPT_SPECIFY_HANDLER 2
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
|
||||
* word to [address+2], and then write the low word to [address].
|
||||
*/
|
||||
#define M68K_SIMULATE_PD_WRITES OPT_OFF
|
||||
|
||||
/* If ON, CPU will call the interrupt acknowledge callback when it services an
|
||||
* interrupt.
|
||||
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||
* auto-clear when the interrupt is serviced.
|
||||
*/
|
||||
#define M68K_EMULATE_INT_ACK OPT_ON //OPT_SPECIFY_HANDLER
|
||||
#define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A)
|
||||
|
||||
/* If ON, CPU will call the output reset callback when it encounters a reset
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_EMULATE_RESET OPT_OFF
|
||||
#define M68K_RESET_CALLBACK() your_reset_handler_function()
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a tas
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_TAS_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_TAS_CALLBACK() your_tas_handler_function()
|
||||
|
||||
/* If ON, CPU will call the set fc callback on every memory access to
|
||||
* differentiate between user/supervisor, program/data access like a real
|
||||
* 68000 would. This should be enabled and the callback should be set if you
|
||||
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||
* to read/write data from different address spaces)
|
||||
*/
|
||||
#define M68K_EMULATE_FC OPT_OFF
|
||||
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
|
||||
|
||||
/* If ON, the CPU will monitor the trace flags and take trace exceptions
|
||||
*/
|
||||
#define M68K_EMULATE_TRACE OPT_OFF
|
||||
|
||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||
|
||||
/* If ON, the CPU will generate address error exceptions if it tries to
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
|
||||
|
||||
/* If ON and previous option is also ON, address error exceptions will
|
||||
also be checked when fetching instructions. Disabling this can help
|
||||
speeding up emulation while still emulating address error exceptions
|
||||
on other memory access if needed.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_CHECK_PC_ADDRESS_ERROR OPT_OFF
|
||||
|
||||
|
||||
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||
|
||||
/* The following options set optimizations that violate the current ANSI
|
||||
* standard, but will be compliant under the forthcoming C9X standard.
|
||||
*/
|
||||
|
||||
|
||||
/* If ON, the enulation core will use 64-bit integers to speed up some
|
||||
* operations.
|
||||
*/
|
||||
#define M68K_USE_64_BIT OPT_OFF
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68KCONF__HEADER */
|
||||
|
|
@ -1,455 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* MAIN 68K CORE */
|
||||
/* ======================================================================== */
|
||||
#pragma GCC optimize("Ofast")
|
||||
#include "pico.h"
|
||||
extern int vdp_68k_irq_ack(int int_level);
|
||||
|
||||
#define m68ki_cpu m68k
|
||||
#define MUL (7)
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#ifndef BUILD_TABLES
|
||||
#ifndef TABLES_FULL
|
||||
#include "m68ki_cycles.h"
|
||||
#else
|
||||
#include "m68ki_cycles_full.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "m68kconf.h"
|
||||
#include "m68kcpu.h"
|
||||
#include "m68kops.h"
|
||||
#include "../../savestate/gwenesis_savestate.h"
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= DATA ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#ifdef BUILD_TABLES
|
||||
static unsigned char m68ki_cycles[0x10000];
|
||||
#endif
|
||||
|
||||
static int irq_latency;
|
||||
|
||||
m68ki_cpu_core m68k;
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== CALLBACKS ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Default callbacks used if the callback hasn't been set yet, or if the
|
||||
* callback is set to NULL
|
||||
*/
|
||||
|
||||
#if M68K_EMULATE_INT_ACK == OPT_ON
|
||||
/* Interrupt acknowledge */
|
||||
static int default_int_ack_callback(int int_level)
|
||||
{
|
||||
CPU_INT_LEVEL = 0;
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_RESET == OPT_ON
|
||||
/* Called when a reset instruction is executed */
|
||||
static void default_reset_instr_callback(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_TAS_HAS_CALLBACK == OPT_ON
|
||||
/* Called when a tas instruction is executed */
|
||||
static int default_tas_instr_callback(void)
|
||||
{
|
||||
return 1; // allow writeback
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_FC == OPT_ON
|
||||
/* Called every time there's bus activity (read/write to/from memory */
|
||||
static void default_set_fc_callback(unsigned int new_fc)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Access the internals of the CPU */
|
||||
unsigned int m68k_get_reg(m68k_register_t regnum)
|
||||
{
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: return m68ki_cpu.dar[0];
|
||||
case M68K_REG_D1: return m68ki_cpu.dar[1];
|
||||
case M68K_REG_D2: return m68ki_cpu.dar[2];
|
||||
case M68K_REG_D3: return m68ki_cpu.dar[3];
|
||||
case M68K_REG_D4: return m68ki_cpu.dar[4];
|
||||
case M68K_REG_D5: return m68ki_cpu.dar[5];
|
||||
case M68K_REG_D6: return m68ki_cpu.dar[6];
|
||||
case M68K_REG_D7: return m68ki_cpu.dar[7];
|
||||
case M68K_REG_A0: return m68ki_cpu.dar[8];
|
||||
case M68K_REG_A1: return m68ki_cpu.dar[9];
|
||||
case M68K_REG_A2: return m68ki_cpu.dar[10];
|
||||
case M68K_REG_A3: return m68ki_cpu.dar[11];
|
||||
case M68K_REG_A4: return m68ki_cpu.dar[12];
|
||||
case M68K_REG_A5: return m68ki_cpu.dar[13];
|
||||
case M68K_REG_A6: return m68ki_cpu.dar[14];
|
||||
case M68K_REG_A7: return m68ki_cpu.dar[15];
|
||||
case M68K_REG_PC: return MASK_OUT_ABOVE_32(m68ki_cpu.pc);
|
||||
case M68K_REG_SR: return m68ki_cpu.t1_flag |
|
||||
(m68ki_cpu.s_flag << 11) |
|
||||
m68ki_cpu.int_mask |
|
||||
((m68ki_cpu.x_flag & XFLAG_SET) >> 4) |
|
||||
((m68ki_cpu.n_flag & NFLAG_SET) >> 4) |
|
||||
((!m68ki_cpu.not_z_flag) << 2) |
|
||||
((m68ki_cpu.v_flag & VFLAG_SET) >> 6) |
|
||||
((m68ki_cpu.c_flag & CFLAG_SET) >> 8);
|
||||
case M68K_REG_SP: return m68ki_cpu.dar[15];
|
||||
case M68K_REG_USP: return m68ki_cpu.s_flag ? m68ki_cpu.sp[0] : m68ki_cpu.dar[15];
|
||||
case M68K_REG_ISP: return m68ki_cpu.s_flag ? m68ki_cpu.dar[15] : m68ki_cpu.sp[4];
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
case M68K_REG_PREF_ADDR: return m68ki_cpu.pref_addr;
|
||||
case M68K_REG_PREF_DATA: return m68ki_cpu.pref_data;
|
||||
#endif
|
||||
case M68K_REG_IR: return m68ki_cpu.ir;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
|
||||
{
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
|
||||
case M68K_REG_SR: m68ki_set_sr(value); return;
|
||||
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_USP: if(FLAG_S)
|
||||
REG_USP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_ISP: if(FLAG_S)
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_ISP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return;
|
||||
#endif
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the callbacks */
|
||||
#if M68K_EMULATE_INT_ACK == OPT_ON
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level))
|
||||
{
|
||||
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_RESET == OPT_ON
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_TAS_HAS_CALLBACK == OPT_ON
|
||||
void m68k_set_tas_instr_callback(int (*callback)(void))
|
||||
{
|
||||
CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_FC == OPT_ON
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
|
||||
{
|
||||
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOGERROR
|
||||
|
||||
extern void error(char *format, ...);
|
||||
extern uint16 v_counter;
|
||||
#endif
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
void m68k_update_irq(unsigned int mask)
|
||||
{
|
||||
/* Update IRQ level */
|
||||
CPU_INT_LEVEL |= (mask << 8);
|
||||
|
||||
#ifdef LOGERROR
|
||||
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
|
||||
#endif
|
||||
}
|
||||
|
||||
void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
/* Set IRQ level */
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
|
||||
#ifdef LOGERROR
|
||||
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* IRQ latency (Fatal Rewind, Sesame's Street Counting Cafe)*/
|
||||
void m68k_set_irq_delay(unsigned int int_level)
|
||||
{
|
||||
/* Prevent reentrance */
|
||||
if (!irq_latency)
|
||||
{
|
||||
/* This is always triggered from MOVE instructions (VDP CTRL port write) */
|
||||
/* We just make sure this is not a MOVE.L instruction as we could be in */
|
||||
/* the middle of its execution (first memory write). */
|
||||
if ((REG_IR & 0xF000) != 0x2000)
|
||||
{
|
||||
/* Finish executing current instruction */
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
|
||||
/* One instruction delay before interrupt */
|
||||
irq_latency = 1;
|
||||
m68ki_trace_t1() /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_use_data_space() /* auto-disable (see m68kcpu.h) */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
m68ki_exception_if_trace() /* auto-disable (see m68kcpu.h) */
|
||||
irq_latency = 0;
|
||||
}
|
||||
|
||||
/* Set IRQ level */
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
}
|
||||
|
||||
#ifdef LOGERROR
|
||||
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* Check interrupt mask to process IRQ */
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
void __time_critical_func(m68k_run)(unsigned int cycles)
|
||||
{
|
||||
// printf("m68K_run current_cycles=%d add=%d STOP=%x\n",m68k.cycles,cycles,CPU_STOPPED);
|
||||
/* Make sure CPU is not already ahead */
|
||||
if (m68k.cycles >= cycles)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check interrupt mask to process IRQ if needed */
|
||||
m68ki_check_interrupts();
|
||||
|
||||
/* Make sure we're not stopped */
|
||||
if (CPU_STOPPED)
|
||||
{
|
||||
m68k.cycles = cycles;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save end cycles count for when CPU is stopped */
|
||||
m68k.cycle_end = cycles;
|
||||
|
||||
/* Return point for when we have an address error (TODO: use goto) */
|
||||
m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
#ifdef LOGERROR
|
||||
error("[%d][%d] m68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, m68k.cycles, cycles, m68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL);
|
||||
#endif
|
||||
#pragma GCC unroll(4)
|
||||
while (m68k.cycles < cycles)
|
||||
{
|
||||
/* Set tracing accodring to T1. */
|
||||
m68ki_trace_t1() /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Set the address space for reads */
|
||||
m68ki_use_data_space() /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
/* Trigger execution hook */
|
||||
if (cpu_hook)
|
||||
cpu_hook(HOOK_M68K_E, 0, REG_PC, 0);
|
||||
#endif
|
||||
|
||||
/* Decode next instruction */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
|
||||
// printf("PC=%x IR=%x CYCLES=%d \n",m68k.pc,REG_IR,CYC_INSTRUCTION[REG_IR]);
|
||||
/* Execute instruction */
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
/* Trace m68k_exception, if necessary */
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
}
|
||||
}
|
||||
|
||||
int m68k_cycles(void)
|
||||
{
|
||||
return CYC_INSTRUCTION[REG_IR];
|
||||
}
|
||||
|
||||
int __always_inline m68k_cycles_run(void)
|
||||
{
|
||||
return m68k.cycle_end - m68k.cycles;
|
||||
}
|
||||
|
||||
int __always_inline m68k_cycles_master(void)
|
||||
{
|
||||
return m68k.cycles;
|
||||
}
|
||||
|
||||
void m68k_init(void)
|
||||
{
|
||||
#ifdef BUILD_TABLES
|
||||
static uint emulation_initialized = 0;
|
||||
|
||||
/* The first call to this function initializes the opcode handler jump table */
|
||||
if(!emulation_initialized)
|
||||
{
|
||||
m68ki_build_opcode_table();
|
||||
emulation_initialized = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef M68K_OVERCLOCK_SHIFT
|
||||
m68k.cycle_ratio = 1 << M68K_OVERCLOCK_SHIFT;
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_INT_ACK == OPT_ON
|
||||
m68k_set_int_ack_callback(NULL);
|
||||
#endif
|
||||
#if M68K_EMULATE_RESET == OPT_ON
|
||||
m68k_set_reset_instr_callback(NULL);
|
||||
#endif
|
||||
#if M68K_TAS_HAS_CALLBACK == OPT_ON
|
||||
m68k_set_tas_instr_callback(NULL);
|
||||
#endif
|
||||
#if M68K_EMULATE_FC == OPT_ON
|
||||
m68k_set_fc_callback(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
{
|
||||
/* Clear all stop levels */
|
||||
CPU_STOPPED = 0;
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||
#endif
|
||||
|
||||
/* Turn off tracing */
|
||||
FLAG_T1 = 0;
|
||||
m68ki_clear_trace()
|
||||
|
||||
/* Interrupt mask to level 7 */
|
||||
FLAG_INT_MASK = 0x0700;
|
||||
CPU_INT_LEVEL = 0;
|
||||
irq_latency = 0;
|
||||
|
||||
/* Go to supervisor mode */
|
||||
m68ki_set_s_flag(SFLAG_SET);
|
||||
|
||||
/* Invalidate the prefetch queue */
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
/* Set to arbitrary number since our first fetch is from 0 */
|
||||
CPU_PREF_ADDR = 0x1000;
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
|
||||
/* Read the initial stack pointer and program counter */
|
||||
m68ki_jump(0);
|
||||
REG_SP = m68ki_read_imm_32();
|
||||
REG_PC = m68ki_read_imm_32();
|
||||
m68ki_jump(REG_PC);
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||
#endif
|
||||
|
||||
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]);
|
||||
}
|
||||
|
||||
void m68k_pulse_halt(void)
|
||||
{
|
||||
/* Pulse the HALT line on the CPU */
|
||||
CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
}
|
||||
|
||||
void m68k_clear_halt(void)
|
||||
{
|
||||
/* Clear the HALT line on the CPU */
|
||||
CPU_STOPPED &= ~STOP_LEVEL_HALT;
|
||||
}
|
||||
|
||||
void gwenesis_m68k_save_state() {
|
||||
SaveState *state;
|
||||
state = saveGwenesisStateOpenForWrite("m68k");
|
||||
|
||||
saveGwenesisStateSetBuffer(state, "REG_D", REG_D, sizeof(REG_D));
|
||||
saveGwenesisStateSet(state, "SR", m68ki_get_sr());
|
||||
saveGwenesisStateSet(state, "REG_PC", REG_PC);
|
||||
saveGwenesisStateSet(state, "REG_SP", REG_SP);
|
||||
saveGwenesisStateSet(state, "REG_USP", REG_USP);
|
||||
saveGwenesisStateSet(state, "REG_ISP", REG_ISP);
|
||||
saveGwenesisStateSet(state, "REG_IR", REG_IR);
|
||||
|
||||
saveGwenesisStateSet(state, "m68k_cycle_end", m68k.cycle_end);
|
||||
saveGwenesisStateSet(state, "m68k_cycles", m68k.cycles);
|
||||
saveGwenesisStateSet(state, "m68k_int_level", m68k.int_level);
|
||||
saveGwenesisStateSet(state, "m68k_stopped", m68k.stopped);
|
||||
}
|
||||
|
||||
void gwenesis_m68k_load_state() {
|
||||
SaveState *state = saveGwenesisStateOpenForRead("m68k");
|
||||
saveGwenesisStateGetBuffer(state, "REG_D", REG_D, sizeof(REG_D));
|
||||
|
||||
m68ki_set_sr(saveGwenesisStateGet(state, "SR"));
|
||||
REG_PC = saveGwenesisStateGet(state, "REG_PC");
|
||||
REG_SP = saveGwenesisStateGet(state, "REG_SP");
|
||||
REG_USP = saveGwenesisStateGet(state, "REG_USP");
|
||||
REG_ISP = saveGwenesisStateGet(state, "REG_ISP");
|
||||
REG_IR = saveGwenesisStateGet(state, "REG_IR");
|
||||
|
||||
m68k.cycle_end = saveGwenesisStateGet(state, "m68k_cycle_end");
|
||||
m68k.cycles = saveGwenesisStateGet(state, "m68k_cycles");
|
||||
m68k.int_level = saveGwenesisStateGet(state, "m68k_int_level");
|
||||
m68k.stopped = saveGwenesisStateGet(state, "m68k_stopped");
|
||||
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,70 +0,0 @@
|
|||
#ifndef _MACROS_H_
|
||||
#define _MACROS_H_
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
|
||||
#define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1]
|
||||
|
||||
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | (BASE)[(ADDR)+1])
|
||||
|
||||
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[(ADDR)+1]<<24) | \
|
||||
((BASE)[(ADDR)]<<16) | \
|
||||
((BASE)[(ADDR)+3]<<8) | \
|
||||
(BASE)[(ADDR)+2])
|
||||
|
||||
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL)&0xff
|
||||
|
||||
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff; \
|
||||
(BASE)[(ADDR)+1] = (VAL)&0xff
|
||||
|
||||
#define WRITE_WORD_LONG(BASE, ADDR, VAL) (BASE)[(ADDR+1)] = ((VAL)>>24) & 0xff; \
|
||||
(BASE)[(ADDR)] = ((VAL)>>16)&0xff; \
|
||||
(BASE)[(ADDR+3)] = ((VAL)>>8)&0xff; \
|
||||
(BASE)[(ADDR+2)] = (VAL)&0xff
|
||||
|
||||
#else
|
||||
|
||||
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
|
||||
#define READ_WORD(BASE, ADDR) *(uint16 *)((BASE) + (ADDR))
|
||||
#define READ_WORD_LONG(BASE, ADDR) *(uint32 *)((BASE) + (ADDR))
|
||||
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = VAL & 0xff
|
||||
#define WRITE_WORD(BASE, ADDR, VAL) *(uint16 *)((BASE) + (ADDR)) = VAL & 0xffff
|
||||
#define WRITE_WORD_LONG(BASE, ADDR, VAL) *(uint32 *)((BASE) + (ADDR)) = VAL & 0xffffffff
|
||||
#endif
|
||||
|
||||
/* C89 compatibility */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327f
|
||||
#endif /* M_PI */
|
||||
|
||||
/* Set to your compiler's static inline keyword to enable it, or
|
||||
* set it to blank to disable it.
|
||||
* If you define INLINE in makefile or osd.h, it will override this value.
|
||||
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
|
||||
*/
|
||||
#ifndef INLINE
|
||||
#define INLINE static __inline__
|
||||
#endif /* INLINE */
|
||||
|
||||
/* Alignment macros for cross compiler compatibility */
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
#elif defined(__GNUC__)
|
||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||
#endif
|
||||
|
||||
/* Default CD image file access (read-only) functions */
|
||||
/* If you need to override default stdio.h functions with custom filesystem API,
|
||||
redefine following macros in platform specific include file (osd.h) or Makefile
|
||||
*/
|
||||
#ifndef cdStream
|
||||
#define cdStream FILE
|
||||
#define cdStreamOpen(fname) fopen(fname, "rb")
|
||||
#define cdStreamClose fclose
|
||||
#define cdStreamRead fread
|
||||
#define cdStreamSeek fseek
|
||||
#define cdStreamTell ftell
|
||||
#define cdStreamGets fgets
|
||||
#endif
|
||||
|
||||
#endif /* _MACROS_H_ */
|
||||
|
|
@ -1,315 +0,0 @@
|
|||
MUSASHI
|
||||
=======
|
||||
|
||||
Version 3.3
|
||||
|
||||
A portable Motorola M680x0 processor emulation engine.
|
||||
Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
|
||||
|
||||
|
||||
INTRODUCTION:
|
||||
------------
|
||||
|
||||
Musashi is a Motorola 68000, 68010, 68EC020, and 68020 emulator written in C.
|
||||
This emulator was written with two goals in mind: portability and speed.
|
||||
|
||||
The emulator is written to ANSI C specifications with the exception that I use
|
||||
inline functions. This is not compliant to the ANSI spec, but will be
|
||||
compliant to the ANSI C9X spec.
|
||||
|
||||
It has been successfully running in the MAME project (www.mame.net) for over 2
|
||||
years and so has had time to mature.
|
||||
|
||||
|
||||
|
||||
LICENSE AND COPYRIGHT:
|
||||
---------------------
|
||||
|
||||
The Musashi M680x0 emulator is copyright 1998-2001 Karl Stenerud.
|
||||
|
||||
The source code included in this archive is provided AS-IS, free for any
|
||||
non-commercial purpose.
|
||||
|
||||
If you build a program using this core, please give credit to the author.
|
||||
|
||||
If you wish to use this core in a commercial environment, please contact
|
||||
the author to discuss commercial licensing.
|
||||
|
||||
|
||||
|
||||
AVAILABILITY:
|
||||
------------
|
||||
The latest version of this code can be obtained at:
|
||||
http://kstenerud.cjb.net
|
||||
|
||||
|
||||
|
||||
CONTACTING THE AUTHOR:
|
||||
---------------------
|
||||
I can be reached at kstenerud@mame.net
|
||||
|
||||
|
||||
|
||||
BASIC CONFIGURATION:
|
||||
-------------------
|
||||
The basic configuration will give you a standard 68000 that has sufficient
|
||||
functionality to work in a primitive environment.
|
||||
|
||||
This setup assumes that you only have 1 device interrupting it, that the
|
||||
device will always request an autovectored interrupt, and it will always clear
|
||||
the interrupt before the interrupt service routine finishes (but could
|
||||
possibly re-assert the interrupt).
|
||||
You will have only one address space, no tracing, and no instruction prefetch.
|
||||
|
||||
To implement the basic configuration:
|
||||
|
||||
- Open m68kconf.h and verify that the settings for INLINE and DECL_SPEC will
|
||||
work with your compiler. (They are set for gcc)
|
||||
|
||||
- In your host program, implement the following functions:
|
||||
unsigned int m68k_read_memory_8(unsigned int address);
|
||||
unsigned int m68k_read_memory_16(unsigned int address);
|
||||
unsigned int m68k_read_memory_32(unsigned int address);
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
- In your host program, be sure to call m68k_pulse_reset() once before calling
|
||||
any of the other functions as this initializes the core.
|
||||
|
||||
- Use m68k_execute() to execute instructions and m68k_set_irq() to cause an
|
||||
interrupt.
|
||||
|
||||
|
||||
|
||||
ADDING PROPER INTERRUPT HANDLING:
|
||||
--------------------------------
|
||||
The interrupt handling in the basic configuration doesn't emulate the
|
||||
interrupt acknowledge phase of the CPU and automatically clears an interrupt
|
||||
request during interrupt processing.
|
||||
While this works for most systems, you may need more accurate interrupt
|
||||
handling.
|
||||
|
||||
To add proper interrupt handling:
|
||||
|
||||
- In m68kconf.h, set M68K_EMULATE_INT_ACK to OPT_SPECIFY_HANDLER
|
||||
|
||||
- In m68kconf.h, set M68K_INT_ACK_CALLBACK(A) to your interrupt acknowledge
|
||||
routine
|
||||
|
||||
- Your interrupt acknowledge routine must return an interrupt vector,
|
||||
M68K_INT_ACK_AUTOVECTOR, or M68K_INT_ACK_SPURIOUS. most m68k
|
||||
implementations just use autovectored interrupts.
|
||||
|
||||
- When the interrupting device is satisfied, you must call m68k_set_irq(0) to
|
||||
remove the interrupt request.
|
||||
|
||||
|
||||
|
||||
MULTIPLE INTERRUPTS:
|
||||
-------------------
|
||||
The above system will work if you have only one device interrupting the CPU,
|
||||
but if you have more than one device, you must do a bit more.
|
||||
|
||||
To add multiple interrupts:
|
||||
|
||||
- You must make an interrupt arbitration device that will take the highest
|
||||
priority interrupt and encode it onto the IRQ pins on the CPU.
|
||||
|
||||
- The interrupt arbitration device should use m68k_set_irq() to set the
|
||||
highest pending interrupt, or 0 for no interrupts pending.
|
||||
|
||||
|
||||
|
||||
SEPARATE IMMEDIATE AND PC-RELATIVE READS:
|
||||
----------------------------------------
|
||||
You can write faster memory access functions if you know whether you are
|
||||
fetching from ROM or RAM. Immediate reads are always from the program space
|
||||
(Always in ROM unless it is running self-modifying code).
|
||||
This will also separate the pc-relative reads, since some systems treat
|
||||
PROGRAM mode reads and DATA mode reads differently (for program encryption,
|
||||
for instance). See the section below (ADDRESS SPACE) for an explanation of
|
||||
PROGRAM and DATA mode.
|
||||
|
||||
To enable separate reads:
|
||||
|
||||
- In m68kconf.h, turn on M68K_SEPARATE_READS.
|
||||
|
||||
- In your host program, implement the following functions:
|
||||
unsigned int m68k_read_immediate_16(unsigned int address);
|
||||
unsigned int m68k_read_immediate_32(unsigned int address);
|
||||
|
||||
unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||
|
||||
- If you need to know the current PC (for banking and such), set
|
||||
M68K_MONITOR_PC to OPT_SPECIFY_HANDLER, and set M68K_SET_PC_CALLBACK(A) to
|
||||
your routine.
|
||||
|
||||
|
||||
|
||||
ADDRESS SPACES:
|
||||
--------------
|
||||
Most systems will only implement one address space, placing ROM at the lower
|
||||
addresses and RAM at the higher. However, there is the possibility that a
|
||||
system will implement ROM and RAM in the same address range, but in different
|
||||
address spaces, or will have different mamory types that require different
|
||||
handling for the program and the data.
|
||||
|
||||
The 68k accomodates this by allowing different program spaces, the most
|
||||
important to us being PROGRAM and DATA space. Here is a breakdown of
|
||||
how information is fetched:
|
||||
|
||||
- All immediate reads are fetched from PROGRAM space.
|
||||
|
||||
- All PC-relative reads are fetched from PROGRAM space.
|
||||
|
||||
- The initial stack pointer and program counter are fetched from PROGRAM space.
|
||||
|
||||
- All other reads (except for those from the moves instruction for 68020)
|
||||
are fetched from DATA space.
|
||||
|
||||
The m68k deals with this by encoding the requested address space on the
|
||||
function code pins:
|
||||
|
||||
FC
|
||||
Address Space 210
|
||||
------------------ ---
|
||||
USER DATA 001
|
||||
USER PROGRAM 010
|
||||
SUPERVISOR DATA 101
|
||||
SUPERVISOR PROGRAM 110
|
||||
CPU SPACE 111 <-- not emulated in this core since we emulate
|
||||
interrupt acknowledge in another way.
|
||||
|
||||
Problems arise here if you need to emulate this distinction (if, for example,
|
||||
your ROM and RAM are at the same address range, with RAM and ROM enable
|
||||
wired to the function code pins).
|
||||
|
||||
There are 2 ways to deal with this situation using Musashi:
|
||||
|
||||
1. If you only need the distinction between PROGRAM and DATA (the most common),
|
||||
you can just separate the reads (see the preceeding section). This is the
|
||||
faster solution.
|
||||
|
||||
2. You can emulate the function code pins entirely.
|
||||
|
||||
To emulate the function code pins:
|
||||
|
||||
- In m68kconf.h, set M68K_EMULATE_FC to OPT_SPECIFY_HANDLER and set
|
||||
M68K_SET_FC_CALLBACK(A) to your function code handler function.
|
||||
|
||||
- Your function code handler should select the proper address space for
|
||||
subsequent calls to m68k_read_xx (and m68k_write_xx for 68010+).
|
||||
|
||||
Note: immediate reads are always done from program space, so technically you
|
||||
don't need to implement the separate immediate reads, although you could
|
||||
gain more speed improvements leaving them in and doing some clever
|
||||
programming.
|
||||
|
||||
|
||||
|
||||
USING DIFFERENT CPU TYPES:
|
||||
-------------------------
|
||||
The default is to enable only the 68000 cpu type. To change this, change the
|
||||
settings for M68K_EMULATE_010 etc in m68kconf.h.
|
||||
|
||||
To set the CPU type you want to use:
|
||||
|
||||
- Make sure it is enabled in m68kconf.h. Current switches are:
|
||||
M68K_EMULATE_010
|
||||
M68K_EMULATE_EC020
|
||||
M68K_EMULATE_020
|
||||
|
||||
- In your host program, call m68k_set_cpu_type() and then call
|
||||
m68k_pulse_reset(). Valid CPU types are:
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020
|
||||
|
||||
|
||||
|
||||
CLOCK FREQUENCY:
|
||||
---------------
|
||||
In order to emulate the correct clock frequency, you will have to calculate
|
||||
how long it takes the emulation to execute a certain number of "cycles" and
|
||||
vary your calls to m68k_execute() accordingly.
|
||||
As well, it is a good idea to take away the CPU's timeslice when it writes to
|
||||
a memory-mapped port in order to give the device it wrote to a chance to
|
||||
react.
|
||||
|
||||
You can use the functions m68k_cycles_run(), m68k_cycles_remaining(),
|
||||
m68k_modify_timeslice(), and m68k_end_timeslice() to do this.
|
||||
Try to use large cycle values in your calls to m68k_execute() since it will
|
||||
increase throughput. You can always take away the timeslice later.
|
||||
|
||||
|
||||
|
||||
MORE CORRECT EMULATION:
|
||||
----------------------
|
||||
You may need to enable these in order to properly emulate some of the more
|
||||
obscure functions of the m68k:
|
||||
|
||||
- M68K_EMULATE_BKPT_ACK causes the CPU to call a breakpoint handler on a BKPT
|
||||
instruction
|
||||
|
||||
- M68K_EMULATE_TRACE causes the CPU to generate trace exceptions when the
|
||||
trace bits are set
|
||||
|
||||
- M68K_EMULATE_RESET causes the CPU to call a reset handler on a RESET
|
||||
instruction.
|
||||
|
||||
- M68K_EMULATE_PREFETCH emulates the 4-word instruction prefetch that is part
|
||||
of the 68000/68010 (needed for Amiga emulation).
|
||||
|
||||
- call m68k_pulse_halt() to emulate the HALT pin.
|
||||
|
||||
|
||||
|
||||
CONVENIENCE FUNCTIONS:
|
||||
---------------------
|
||||
These are in here for programmer convenience:
|
||||
|
||||
- M68K_INSTRUCTION_HOOK lets you call a handler before each instruction.
|
||||
|
||||
- M68K_LOG_ENABLE and M68K_LOG_1010_1111 lets you log illegal and A/F-line
|
||||
instructions.
|
||||
|
||||
|
||||
|
||||
MULTIPLE CPU EMULATION:
|
||||
----------------------
|
||||
The default is to use only one CPU. To use more than one CPU in this core,
|
||||
there are some things to keep in mind:
|
||||
|
||||
- To have different cpus call different functions, use OPT_ON instead of
|
||||
OPT_SPECIFY_HANDLER, and use the m68k_set_xxx_callback() functions to set
|
||||
your callback handlers on a per-cpu basis.
|
||||
|
||||
- Be sure to call set_cpu_type() for each CPU you use.
|
||||
|
||||
- Use m68k_set_context() and m68k_get_context() to switch to another CPU.
|
||||
|
||||
|
||||
|
||||
LOAD AND SAVE CPU CONTEXTS FROM DISK:
|
||||
------------------------------------
|
||||
You can use them68k_load_context() and m68k_save_context() functions to load
|
||||
and save the CPU state to disk.
|
||||
|
||||
|
||||
|
||||
GET/SET INFORMATION FROM THE CPU:
|
||||
--------------------------------
|
||||
You can use m68k_get_reg() and m68k_set_reg() to gain access to the internals
|
||||
of the CPU.
|
||||
|
||||
|
||||
|
||||
EXAMPLE:
|
||||
-------
|
||||
|
||||
I have included a file example.zip that contains a full example.
|
||||
|
|
@ -1,385 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Codes.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the main table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->HL.B.h);break;
|
||||
case ADD_L: M_ADD(R->HL.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->HL.W);M_ADD(I);break;
|
||||
case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->HL.B.h);break;
|
||||
case SUB_L: M_SUB(R->HL.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->HL.W);M_SUB(I);break;
|
||||
case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->HL.B.h);break;
|
||||
case AND_L: M_AND(R->HL.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->HL.W);M_AND(I);break;
|
||||
case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->HL.B.h);break;
|
||||
case OR_L: M_OR(R->HL.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->HL.W);M_OR(I);break;
|
||||
case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->HL.B.h);break;
|
||||
case ADC_L: M_ADC(R->HL.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->HL.W);M_ADC(I);break;
|
||||
case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->HL.B.h);break;
|
||||
case SBC_L: M_SBC(R->HL.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->HL.W);M_SBC(I);break;
|
||||
case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->HL.B.h);break;
|
||||
case XOR_L: M_XOR(R->HL.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->HL.W);M_XOR(I);break;
|
||||
case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->HL.B.h);break;
|
||||
case CP_L: M_CP(R->HL.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->HL.W);M_CP(I);break;
|
||||
case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(HL);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->HL.W;JumpZ80(R->PC.W);break;
|
||||
case LD_SP_HL: R->SP.W=R->HL.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(HL,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(HL,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(HL,HL);break;
|
||||
case ADD_HL_SP: M_ADDW(HL,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->HL.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->HL.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->HL.B.h);break;
|
||||
case DEC_L: M_DEC(R->HL.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->HL.W);M_DEC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->HL.B.h);break;
|
||||
case INC_L: M_INC(R->HL.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->HL.W);M_INC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case RLCA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(HL);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(HL);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break;
|
||||
case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break;
|
||||
|
||||
case HALT:
|
||||
R->PC.W--;
|
||||
R->IFF|=IFF_HALT;
|
||||
R->IBackup=0;
|
||||
R->ICount=0;
|
||||
break;
|
||||
|
||||
case DI:
|
||||
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
break;
|
||||
|
||||
case EI:
|
||||
if(!(R->IFF&(IFF_1|IFF_EI)))
|
||||
{
|
||||
R->IFF|=IFF_2|IFF_EI;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->HL.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->HL.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->HL.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->HL.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->HL.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->HL.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->HL.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->HL.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->HL.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->HL.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->HL.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->HL.B.h;break;
|
||||
case LD_H_H: R->HL.B.h=R->HL.B.h;break;
|
||||
case LD_L_H: R->HL.B.l=R->HL.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->HL.B.h;break;
|
||||
case LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->HL.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->HL.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->HL.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->HL.B.l;break;
|
||||
case LD_H_L: R->HL.B.h=R->HL.B.l;break;
|
||||
case LD_L_L: R->HL.B.l=R->HL.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->HL.B.l;break;
|
||||
case LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->HL.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->HL.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->HL.W);break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->HL.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->HL.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: WrZ80(R->HL.W,OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->HL.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->HL.B.h);
|
||||
R->HL.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
||||
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-1
|
||||
);
|
||||
break;
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the CB table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_B: M_RLC(R->BC.B.h);break; case RLC_C: M_RLC(R->BC.B.l);break;
|
||||
case RLC_D: M_RLC(R->DE.B.h);break; case RLC_E: M_RLC(R->DE.B.l);break;
|
||||
case RLC_H: M_RLC(R->HL.B.h);break; case RLC_L: M_RLC(R->HL.B.l);break;
|
||||
case RLC_xHL: I=RdZ80(R->HL.W);M_RLC(I);WrZ80(R->HL.W,I);break;
|
||||
case RLC_A: M_RLC(R->AF.B.h);break;
|
||||
|
||||
case RRC_B: M_RRC(R->BC.B.h);break; case RRC_C: M_RRC(R->BC.B.l);break;
|
||||
case RRC_D: M_RRC(R->DE.B.h);break; case RRC_E: M_RRC(R->DE.B.l);break;
|
||||
case RRC_H: M_RRC(R->HL.B.h);break; case RRC_L: M_RRC(R->HL.B.l);break;
|
||||
case RRC_xHL: I=RdZ80(R->HL.W);M_RRC(I);WrZ80(R->HL.W,I);break;
|
||||
case RRC_A: M_RRC(R->AF.B.h);break;
|
||||
|
||||
case RL_B: M_RL(R->BC.B.h);break; case RL_C: M_RL(R->BC.B.l);break;
|
||||
case RL_D: M_RL(R->DE.B.h);break; case RL_E: M_RL(R->DE.B.l);break;
|
||||
case RL_H: M_RL(R->HL.B.h);break; case RL_L: M_RL(R->HL.B.l);break;
|
||||
case RL_xHL: I=RdZ80(R->HL.W);M_RL(I);WrZ80(R->HL.W,I);break;
|
||||
case RL_A: M_RL(R->AF.B.h);break;
|
||||
|
||||
case RR_B: M_RR(R->BC.B.h);break; case RR_C: M_RR(R->BC.B.l);break;
|
||||
case RR_D: M_RR(R->DE.B.h);break; case RR_E: M_RR(R->DE.B.l);break;
|
||||
case RR_H: M_RR(R->HL.B.h);break; case RR_L: M_RR(R->HL.B.l);break;
|
||||
case RR_xHL: I=RdZ80(R->HL.W);M_RR(I);WrZ80(R->HL.W,I);break;
|
||||
case RR_A: M_RR(R->AF.B.h);break;
|
||||
|
||||
case SLA_B: M_SLA(R->BC.B.h);break; case SLA_C: M_SLA(R->BC.B.l);break;
|
||||
case SLA_D: M_SLA(R->DE.B.h);break; case SLA_E: M_SLA(R->DE.B.l);break;
|
||||
case SLA_H: M_SLA(R->HL.B.h);break; case SLA_L: M_SLA(R->HL.B.l);break;
|
||||
case SLA_xHL: I=RdZ80(R->HL.W);M_SLA(I);WrZ80(R->HL.W,I);break;
|
||||
case SLA_A: M_SLA(R->AF.B.h);break;
|
||||
|
||||
case SRA_B: M_SRA(R->BC.B.h);break; case SRA_C: M_SRA(R->BC.B.l);break;
|
||||
case SRA_D: M_SRA(R->DE.B.h);break; case SRA_E: M_SRA(R->DE.B.l);break;
|
||||
case SRA_H: M_SRA(R->HL.B.h);break; case SRA_L: M_SRA(R->HL.B.l);break;
|
||||
case SRA_xHL: I=RdZ80(R->HL.W);M_SRA(I);WrZ80(R->HL.W,I);break;
|
||||
case SRA_A: M_SRA(R->AF.B.h);break;
|
||||
|
||||
case SLL_B: M_SLL(R->BC.B.h);break; case SLL_C: M_SLL(R->BC.B.l);break;
|
||||
case SLL_D: M_SLL(R->DE.B.h);break; case SLL_E: M_SLL(R->DE.B.l);break;
|
||||
case SLL_H: M_SLL(R->HL.B.h);break; case SLL_L: M_SLL(R->HL.B.l);break;
|
||||
case SLL_xHL: I=RdZ80(R->HL.W);M_SLL(I);WrZ80(R->HL.W,I);break;
|
||||
case SLL_A: M_SLL(R->AF.B.h);break;
|
||||
|
||||
case SRL_B: M_SRL(R->BC.B.h);break; case SRL_C: M_SRL(R->BC.B.l);break;
|
||||
case SRL_D: M_SRL(R->DE.B.h);break; case SRL_E: M_SRL(R->DE.B.l);break;
|
||||
case SRL_H: M_SRL(R->HL.B.h);break; case SRL_L: M_SRL(R->HL.B.l);break;
|
||||
case SRL_xHL: I=RdZ80(R->HL.W);M_SRL(I);WrZ80(R->HL.W,I);break;
|
||||
case SRL_A: M_SRL(R->AF.B.h);break;
|
||||
|
||||
case BIT0_B: M_BIT(0,R->BC.B.h);break; case BIT0_C: M_BIT(0,R->BC.B.l);break;
|
||||
case BIT0_D: M_BIT(0,R->DE.B.h);break; case BIT0_E: M_BIT(0,R->DE.B.l);break;
|
||||
case BIT0_H: M_BIT(0,R->HL.B.h);break; case BIT0_L: M_BIT(0,R->HL.B.l);break;
|
||||
case BIT0_xHL: I=RdZ80(R->HL.W);M_BIT(0,I);break;
|
||||
case BIT0_A: M_BIT(0,R->AF.B.h);break;
|
||||
|
||||
case BIT1_B: M_BIT(1,R->BC.B.h);break; case BIT1_C: M_BIT(1,R->BC.B.l);break;
|
||||
case BIT1_D: M_BIT(1,R->DE.B.h);break; case BIT1_E: M_BIT(1,R->DE.B.l);break;
|
||||
case BIT1_H: M_BIT(1,R->HL.B.h);break; case BIT1_L: M_BIT(1,R->HL.B.l);break;
|
||||
case BIT1_xHL: I=RdZ80(R->HL.W);M_BIT(1,I);break;
|
||||
case BIT1_A: M_BIT(1,R->AF.B.h);break;
|
||||
|
||||
case BIT2_B: M_BIT(2,R->BC.B.h);break; case BIT2_C: M_BIT(2,R->BC.B.l);break;
|
||||
case BIT2_D: M_BIT(2,R->DE.B.h);break; case BIT2_E: M_BIT(2,R->DE.B.l);break;
|
||||
case BIT2_H: M_BIT(2,R->HL.B.h);break; case BIT2_L: M_BIT(2,R->HL.B.l);break;
|
||||
case BIT2_xHL: I=RdZ80(R->HL.W);M_BIT(2,I);break;
|
||||
case BIT2_A: M_BIT(2,R->AF.B.h);break;
|
||||
|
||||
case BIT3_B: M_BIT(3,R->BC.B.h);break; case BIT3_C: M_BIT(3,R->BC.B.l);break;
|
||||
case BIT3_D: M_BIT(3,R->DE.B.h);break; case BIT3_E: M_BIT(3,R->DE.B.l);break;
|
||||
case BIT3_H: M_BIT(3,R->HL.B.h);break; case BIT3_L: M_BIT(3,R->HL.B.l);break;
|
||||
case BIT3_xHL: I=RdZ80(R->HL.W);M_BIT(3,I);break;
|
||||
case BIT3_A: M_BIT(3,R->AF.B.h);break;
|
||||
|
||||
case BIT4_B: M_BIT(4,R->BC.B.h);break; case BIT4_C: M_BIT(4,R->BC.B.l);break;
|
||||
case BIT4_D: M_BIT(4,R->DE.B.h);break; case BIT4_E: M_BIT(4,R->DE.B.l);break;
|
||||
case BIT4_H: M_BIT(4,R->HL.B.h);break; case BIT4_L: M_BIT(4,R->HL.B.l);break;
|
||||
case BIT4_xHL: I=RdZ80(R->HL.W);M_BIT(4,I);break;
|
||||
case BIT4_A: M_BIT(4,R->AF.B.h);break;
|
||||
|
||||
case BIT5_B: M_BIT(5,R->BC.B.h);break; case BIT5_C: M_BIT(5,R->BC.B.l);break;
|
||||
case BIT5_D: M_BIT(5,R->DE.B.h);break; case BIT5_E: M_BIT(5,R->DE.B.l);break;
|
||||
case BIT5_H: M_BIT(5,R->HL.B.h);break; case BIT5_L: M_BIT(5,R->HL.B.l);break;
|
||||
case BIT5_xHL: I=RdZ80(R->HL.W);M_BIT(5,I);break;
|
||||
case BIT5_A: M_BIT(5,R->AF.B.h);break;
|
||||
|
||||
case BIT6_B: M_BIT(6,R->BC.B.h);break; case BIT6_C: M_BIT(6,R->BC.B.l);break;
|
||||
case BIT6_D: M_BIT(6,R->DE.B.h);break; case BIT6_E: M_BIT(6,R->DE.B.l);break;
|
||||
case BIT6_H: M_BIT(6,R->HL.B.h);break; case BIT6_L: M_BIT(6,R->HL.B.l);break;
|
||||
case BIT6_xHL: I=RdZ80(R->HL.W);M_BIT(6,I);break;
|
||||
case BIT6_A: M_BIT(6,R->AF.B.h);break;
|
||||
|
||||
case BIT7_B: M_BIT(7,R->BC.B.h);break; case BIT7_C: M_BIT(7,R->BC.B.l);break;
|
||||
case BIT7_D: M_BIT(7,R->DE.B.h);break; case BIT7_E: M_BIT(7,R->DE.B.l);break;
|
||||
case BIT7_H: M_BIT(7,R->HL.B.h);break; case BIT7_L: M_BIT(7,R->HL.B.l);break;
|
||||
case BIT7_xHL: I=RdZ80(R->HL.W);M_BIT(7,I);break;
|
||||
case BIT7_A: M_BIT(7,R->AF.B.h);break;
|
||||
|
||||
case RES0_B: M_RES(0,R->BC.B.h);break; case RES0_C: M_RES(0,R->BC.B.l);break;
|
||||
case RES0_D: M_RES(0,R->DE.B.h);break; case RES0_E: M_RES(0,R->DE.B.l);break;
|
||||
case RES0_H: M_RES(0,R->HL.B.h);break; case RES0_L: M_RES(0,R->HL.B.l);break;
|
||||
case RES0_xHL: I=RdZ80(R->HL.W);M_RES(0,I);WrZ80(R->HL.W,I);break;
|
||||
case RES0_A: M_RES(0,R->AF.B.h);break;
|
||||
|
||||
case RES1_B: M_RES(1,R->BC.B.h);break; case RES1_C: M_RES(1,R->BC.B.l);break;
|
||||
case RES1_D: M_RES(1,R->DE.B.h);break; case RES1_E: M_RES(1,R->DE.B.l);break;
|
||||
case RES1_H: M_RES(1,R->HL.B.h);break; case RES1_L: M_RES(1,R->HL.B.l);break;
|
||||
case RES1_xHL: I=RdZ80(R->HL.W);M_RES(1,I);WrZ80(R->HL.W,I);break;
|
||||
case RES1_A: M_RES(1,R->AF.B.h);break;
|
||||
|
||||
case RES2_B: M_RES(2,R->BC.B.h);break; case RES2_C: M_RES(2,R->BC.B.l);break;
|
||||
case RES2_D: M_RES(2,R->DE.B.h);break; case RES2_E: M_RES(2,R->DE.B.l);break;
|
||||
case RES2_H: M_RES(2,R->HL.B.h);break; case RES2_L: M_RES(2,R->HL.B.l);break;
|
||||
case RES2_xHL: I=RdZ80(R->HL.W);M_RES(2,I);WrZ80(R->HL.W,I);break;
|
||||
case RES2_A: M_RES(2,R->AF.B.h);break;
|
||||
|
||||
case RES3_B: M_RES(3,R->BC.B.h);break; case RES3_C: M_RES(3,R->BC.B.l);break;
|
||||
case RES3_D: M_RES(3,R->DE.B.h);break; case RES3_E: M_RES(3,R->DE.B.l);break;
|
||||
case RES3_H: M_RES(3,R->HL.B.h);break; case RES3_L: M_RES(3,R->HL.B.l);break;
|
||||
case RES3_xHL: I=RdZ80(R->HL.W);M_RES(3,I);WrZ80(R->HL.W,I);break;
|
||||
case RES3_A: M_RES(3,R->AF.B.h);break;
|
||||
|
||||
case RES4_B: M_RES(4,R->BC.B.h);break; case RES4_C: M_RES(4,R->BC.B.l);break;
|
||||
case RES4_D: M_RES(4,R->DE.B.h);break; case RES4_E: M_RES(4,R->DE.B.l);break;
|
||||
case RES4_H: M_RES(4,R->HL.B.h);break; case RES4_L: M_RES(4,R->HL.B.l);break;
|
||||
case RES4_xHL: I=RdZ80(R->HL.W);M_RES(4,I);WrZ80(R->HL.W,I);break;
|
||||
case RES4_A: M_RES(4,R->AF.B.h);break;
|
||||
|
||||
case RES5_B: M_RES(5,R->BC.B.h);break; case RES5_C: M_RES(5,R->BC.B.l);break;
|
||||
case RES5_D: M_RES(5,R->DE.B.h);break; case RES5_E: M_RES(5,R->DE.B.l);break;
|
||||
case RES5_H: M_RES(5,R->HL.B.h);break; case RES5_L: M_RES(5,R->HL.B.l);break;
|
||||
case RES5_xHL: I=RdZ80(R->HL.W);M_RES(5,I);WrZ80(R->HL.W,I);break;
|
||||
case RES5_A: M_RES(5,R->AF.B.h);break;
|
||||
|
||||
case RES6_B: M_RES(6,R->BC.B.h);break; case RES6_C: M_RES(6,R->BC.B.l);break;
|
||||
case RES6_D: M_RES(6,R->DE.B.h);break; case RES6_E: M_RES(6,R->DE.B.l);break;
|
||||
case RES6_H: M_RES(6,R->HL.B.h);break; case RES6_L: M_RES(6,R->HL.B.l);break;
|
||||
case RES6_xHL: I=RdZ80(R->HL.W);M_RES(6,I);WrZ80(R->HL.W,I);break;
|
||||
case RES6_A: M_RES(6,R->AF.B.h);break;
|
||||
|
||||
case RES7_B: M_RES(7,R->BC.B.h);break; case RES7_C: M_RES(7,R->BC.B.l);break;
|
||||
case RES7_D: M_RES(7,R->DE.B.h);break; case RES7_E: M_RES(7,R->DE.B.l);break;
|
||||
case RES7_H: M_RES(7,R->HL.B.h);break; case RES7_L: M_RES(7,R->HL.B.l);break;
|
||||
case RES7_xHL: I=RdZ80(R->HL.W);M_RES(7,I);WrZ80(R->HL.W,I);break;
|
||||
case RES7_A: M_RES(7,R->AF.B.h);break;
|
||||
|
||||
case SET0_B: M_SET(0,R->BC.B.h);break; case SET0_C: M_SET(0,R->BC.B.l);break;
|
||||
case SET0_D: M_SET(0,R->DE.B.h);break; case SET0_E: M_SET(0,R->DE.B.l);break;
|
||||
case SET0_H: M_SET(0,R->HL.B.h);break; case SET0_L: M_SET(0,R->HL.B.l);break;
|
||||
case SET0_xHL: I=RdZ80(R->HL.W);M_SET(0,I);WrZ80(R->HL.W,I);break;
|
||||
case SET0_A: M_SET(0,R->AF.B.h);break;
|
||||
|
||||
case SET1_B: M_SET(1,R->BC.B.h);break; case SET1_C: M_SET(1,R->BC.B.l);break;
|
||||
case SET1_D: M_SET(1,R->DE.B.h);break; case SET1_E: M_SET(1,R->DE.B.l);break;
|
||||
case SET1_H: M_SET(1,R->HL.B.h);break; case SET1_L: M_SET(1,R->HL.B.l);break;
|
||||
case SET1_xHL: I=RdZ80(R->HL.W);M_SET(1,I);WrZ80(R->HL.W,I);break;
|
||||
case SET1_A: M_SET(1,R->AF.B.h);break;
|
||||
|
||||
case SET2_B: M_SET(2,R->BC.B.h);break; case SET2_C: M_SET(2,R->BC.B.l);break;
|
||||
case SET2_D: M_SET(2,R->DE.B.h);break; case SET2_E: M_SET(2,R->DE.B.l);break;
|
||||
case SET2_H: M_SET(2,R->HL.B.h);break; case SET2_L: M_SET(2,R->HL.B.l);break;
|
||||
case SET2_xHL: I=RdZ80(R->HL.W);M_SET(2,I);WrZ80(R->HL.W,I);break;
|
||||
case SET2_A: M_SET(2,R->AF.B.h);break;
|
||||
|
||||
case SET3_B: M_SET(3,R->BC.B.h);break; case SET3_C: M_SET(3,R->BC.B.l);break;
|
||||
case SET3_D: M_SET(3,R->DE.B.h);break; case SET3_E: M_SET(3,R->DE.B.l);break;
|
||||
case SET3_H: M_SET(3,R->HL.B.h);break; case SET3_L: M_SET(3,R->HL.B.l);break;
|
||||
case SET3_xHL: I=RdZ80(R->HL.W);M_SET(3,I);WrZ80(R->HL.W,I);break;
|
||||
case SET3_A: M_SET(3,R->AF.B.h);break;
|
||||
|
||||
case SET4_B: M_SET(4,R->BC.B.h);break; case SET4_C: M_SET(4,R->BC.B.l);break;
|
||||
case SET4_D: M_SET(4,R->DE.B.h);break; case SET4_E: M_SET(4,R->DE.B.l);break;
|
||||
case SET4_H: M_SET(4,R->HL.B.h);break; case SET4_L: M_SET(4,R->HL.B.l);break;
|
||||
case SET4_xHL: I=RdZ80(R->HL.W);M_SET(4,I);WrZ80(R->HL.W,I);break;
|
||||
case SET4_A: M_SET(4,R->AF.B.h);break;
|
||||
|
||||
case SET5_B: M_SET(5,R->BC.B.h);break; case SET5_C: M_SET(5,R->BC.B.l);break;
|
||||
case SET5_D: M_SET(5,R->DE.B.h);break; case SET5_E: M_SET(5,R->DE.B.l);break;
|
||||
case SET5_H: M_SET(5,R->HL.B.h);break; case SET5_L: M_SET(5,R->HL.B.l);break;
|
||||
case SET5_xHL: I=RdZ80(R->HL.W);M_SET(5,I);WrZ80(R->HL.W,I);break;
|
||||
case SET5_A: M_SET(5,R->AF.B.h);break;
|
||||
|
||||
case SET6_B: M_SET(6,R->BC.B.h);break; case SET6_C: M_SET(6,R->BC.B.l);break;
|
||||
case SET6_D: M_SET(6,R->DE.B.h);break; case SET6_E: M_SET(6,R->DE.B.l);break;
|
||||
case SET6_H: M_SET(6,R->HL.B.h);break; case SET6_L: M_SET(6,R->HL.B.l);break;
|
||||
case SET6_xHL: I=RdZ80(R->HL.W);M_SET(6,I);WrZ80(R->HL.W,I);break;
|
||||
case SET6_A: M_SET(6,R->AF.B.h);break;
|
||||
|
||||
case SET7_B: M_SET(7,R->BC.B.h);break; case SET7_C: M_SET(7,R->BC.B.l);break;
|
||||
case SET7_D: M_SET(7,R->DE.B.h);break; case SET7_E: M_SET(7,R->DE.B.l);break;
|
||||
case SET7_H: M_SET(7,R->HL.B.h);break; case SET7_L: M_SET(7,R->HL.B.l);break;
|
||||
case SET7_xHL: I=RdZ80(R->HL.W);M_SET(7,I);WrZ80(R->HL.W,I);break;
|
||||
case SET7_A: M_SET(7,R->AF.B.h);break;
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesED.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the ED table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
/** This is a special patch for emulating BIOS calls: ********/
|
||||
case DB_FE: PatchZ80(R);break;
|
||||
/*************************************************************/
|
||||
|
||||
case ADC_HL_BC: M_ADCW(BC);break;
|
||||
case ADC_HL_DE: M_ADCW(DE);break;
|
||||
case ADC_HL_HL: M_ADCW(HL);break;
|
||||
case ADC_HL_SP: M_ADCW(SP);break;
|
||||
|
||||
case SBC_HL_BC: M_SBCW(BC);break;
|
||||
case SBC_HL_DE: M_SBCW(DE);break;
|
||||
case SBC_HL_HL: M_SBCW(HL);break;
|
||||
case SBC_HL_SP: M_SBCW(SP);break;
|
||||
|
||||
case LD_xWORDe_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
case LD_xWORDe_DE:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->DE.B.l);
|
||||
WrZ80(J.W,R->DE.B.h);
|
||||
break;
|
||||
case LD_xWORDe_BC:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->BC.B.l);
|
||||
WrZ80(J.W,R->BC.B.h);
|
||||
break;
|
||||
case LD_xWORDe_SP:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->SP.B.l);
|
||||
WrZ80(J.W,R->SP.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_DE_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->DE.B.l=RdZ80(J.W++);
|
||||
R->DE.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_BC_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->BC.B.l=RdZ80(J.W++);
|
||||
R->BC.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_SP_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->SP.B.l=RdZ80(J.W++);
|
||||
R->SP.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case RRD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I>>4)|(R->AF.B.h<<4);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
case RLD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I<<4)|(R->AF.B.h&0x0F);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
|
||||
case LD_A_I:
|
||||
R->AF.B.h=R->I;
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_A_R:
|
||||
R->R++;
|
||||
R->AF.B.h=(byte)(R->R-R->ICount);
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_I_A: R->I=R->AF.B.h;break;
|
||||
case LD_R_A: break;
|
||||
|
||||
case IM_0: R->IFF&=~(IFF_IM1|IFF_IM2);break;
|
||||
case IM_1: R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break;
|
||||
case IM_2: R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break;
|
||||
|
||||
case RETI:
|
||||
case RETN: if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1;
|
||||
M_RET;break;
|
||||
|
||||
case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break;
|
||||
|
||||
case IN_B_xC: M_IN(R->BC.B.h);break;
|
||||
case IN_C_xC: M_IN(R->BC.B.l);break;
|
||||
case IN_D_xC: M_IN(R->DE.B.h);break;
|
||||
case IN_E_xC: M_IN(R->DE.B.l);break;
|
||||
case IN_H_xC: M_IN(R->HL.B.h);break;
|
||||
case IN_L_xC: M_IN(R->HL.B.l);break;
|
||||
case IN_A_xC: M_IN(R->AF.B.h);break;
|
||||
case IN_F_xC: M_IN(J.B.l);break;
|
||||
|
||||
case OUT_xC_B: OutZ80(R->BC.W,R->BC.B.h);break;
|
||||
case OUT_xC_C: OutZ80(R->BC.W,R->BC.B.l);break;
|
||||
case OUT_xC_D: OutZ80(R->BC.W,R->DE.B.h);break;
|
||||
case OUT_xC_E: OutZ80(R->BC.W,R->DE.B.l);break;
|
||||
case OUT_xC_H: OutZ80(R->BC.W,R->HL.B.h);break;
|
||||
case OUT_xC_L: OutZ80(R->BC.W,R->HL.B.l);break;
|
||||
case OUT_xC_A: OutZ80(R->BC.W,R->AF.B.h);break;
|
||||
|
||||
case INI:
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.W));
|
||||
--R->BC.B.h;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.W));
|
||||
--R->BC.B.h;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case IND:
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.W));
|
||||
--R->BC.B.h;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.W));
|
||||
--R->BC.B.h;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case OUTI:
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W++);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
break;
|
||||
|
||||
case OTIR:
|
||||
do
|
||||
{
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W++);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h)
|
||||
{
|
||||
R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->PC.W-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->ICount+=5;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUTD:
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W--);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
break;
|
||||
|
||||
case OTDR:
|
||||
do
|
||||
{
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W--);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h)
|
||||
{
|
||||
R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->PC.W-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->ICount+=5;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDI:
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
--R->BC.W;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case LDD:
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
--R->BC.W;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPI:
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPIR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l&&(R->ICount>0));
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPD:
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPDR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l);
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD-CB tables **/
|
||||
/** of Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break;
|
||||
case RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break;
|
||||
case RL_xHL: I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break;
|
||||
case RR_xHL: I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break;
|
||||
case SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break;
|
||||
case SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break;
|
||||
case SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break;
|
||||
case SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break;
|
||||
|
||||
case BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E:
|
||||
case BIT0_H: case BIT0_L: case BIT0_A:
|
||||
case BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break;
|
||||
case BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E:
|
||||
case BIT1_H: case BIT1_L: case BIT1_A:
|
||||
case BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break;
|
||||
case BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E:
|
||||
case BIT2_H: case BIT2_L: case BIT2_A:
|
||||
case BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break;
|
||||
case BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E:
|
||||
case BIT3_H: case BIT3_L: case BIT3_A:
|
||||
case BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break;
|
||||
case BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E:
|
||||
case BIT4_H: case BIT4_L: case BIT4_A:
|
||||
case BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break;
|
||||
case BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E:
|
||||
case BIT5_H: case BIT5_L: case BIT5_A:
|
||||
case BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break;
|
||||
case BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E:
|
||||
case BIT6_H: case BIT6_L: case BIT6_A:
|
||||
case BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break;
|
||||
case BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E:
|
||||
case BIT7_H: case BIT7_L: case BIT7_A:
|
||||
case BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break;
|
||||
|
||||
case RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break;
|
||||
case RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break;
|
||||
case RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break;
|
||||
case RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break;
|
||||
case RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break;
|
||||
case RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break;
|
||||
case RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break;
|
||||
case RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break;
|
||||
|
||||
case SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break;
|
||||
case SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break;
|
||||
case SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break;
|
||||
case SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break;
|
||||
case SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break;
|
||||
case SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break;
|
||||
case SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break;
|
||||
case SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break;
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXX.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD tables of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->XX.B.h);break;
|
||||
case ADD_L: M_ADD(R->XX.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_ADD(I);break;
|
||||
case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->XX.B.h);break;
|
||||
case SUB_L: M_SUB(R->XX.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_SUB(I);break;
|
||||
case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->XX.B.h);break;
|
||||
case AND_L: M_AND(R->XX.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_AND(I);break;
|
||||
case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->XX.B.h);break;
|
||||
case OR_L: M_OR(R->XX.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_OR(I);break;
|
||||
case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->XX.B.h);break;
|
||||
case ADC_L: M_ADC(R->XX.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_ADC(I);break;
|
||||
case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->XX.B.h);break;
|
||||
case SBC_L: M_SBC(R->XX.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_SBC(I);break;
|
||||
case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->XX.B.h);break;
|
||||
case XOR_L: M_XOR(R->XX.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_XOR(I);break;
|
||||
case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->XX.B.h);break;
|
||||
case CP_L: M_CP(R->XX.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_CP(I);break;
|
||||
case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(XX);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->XX.W;JumpZ80(R->PC.W);break;
|
||||
case LD_SP_HL: R->SP.W=R->XX.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(XX,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(XX,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(XX,XX);break;
|
||||
case ADD_HL_SP: M_ADDW(XX,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->XX.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->XX.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->XX.B.h);break;
|
||||
case DEC_L: M_DEC(R->XX.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_DEC(I);
|
||||
WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->XX.B.h);break;
|
||||
case INC_L: M_INC(R->XX.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_INC(I);
|
||||
WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case RLCA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(XX);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(XX);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break;
|
||||
case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break;
|
||||
|
||||
case HALT:
|
||||
R->PC.W--;
|
||||
R->IFF|=IFF_HALT;
|
||||
R->IBackup=0;
|
||||
R->ICount=0;
|
||||
break;
|
||||
|
||||
case DI:
|
||||
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
break;
|
||||
|
||||
case EI:
|
||||
if(!(R->IFF&(IFF_1|IFF_EI)))
|
||||
{
|
||||
R->IFF|=IFF_2|IFF_EI;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->XX.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->XX.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->XX.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->XX.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->XX.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->XX.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->XX.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->XX.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->XX.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->XX.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->XX.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->XX.B.h;break;
|
||||
case LD_H_H: R->XX.B.h=R->XX.B.h;break;
|
||||
case LD_L_H: R->XX.B.l=R->XX.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->XX.B.h;break;
|
||||
case LD_xHL_H: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->XX.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->XX.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->XX.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->XX.B.l;break;
|
||||
case LD_H_L: R->XX.B.h=R->XX.B.l;break;
|
||||
case LD_L_L: R->XX.B.l=R->XX.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->XX.B.l;break;
|
||||
case LD_xHL_L: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->XX.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->XX.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->XX.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->XX.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->XX.B.l);
|
||||
WrZ80(J.W,R->XX.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->XX.B.l=RdZ80(J.W++);
|
||||
R->XX.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->XX.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->XX.B.h);
|
||||
R->XX.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** ConDebug.c **/
|
||||
/** **/
|
||||
/** This file contains a console version of the built-in **/
|
||||
/** debugger, using EMULib's Console.c. When -DCONDEBUG is **/
|
||||
/** ommitted, ConDebug.c just includes the default command **/
|
||||
/** line based debugger (Debug.c). **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 2005-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifndef CONDEBUG
|
||||
/** Normal DebugZ80() ****************************************/
|
||||
/** When CONDEBUG #undefined, we use plain command line. **/
|
||||
/*************************************************************/
|
||||
#include "Debug.c"
|
||||
|
||||
#else
|
||||
/** Console DebugZ80() ***************************************/
|
||||
/** When CONDEBUG #defined, we use EMULib console. **/
|
||||
/*************************************************************/
|
||||
|
||||
#include "Z80.h"
|
||||
#include "Console.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DebugZ80 OriginalDebugZ80
|
||||
#include "Debug.c"
|
||||
#undef DebugZ80
|
||||
|
||||
#define CLR_BACK PIXEL(255,255,255)
|
||||
#define CLR_TEXT PIXEL(0,0,0)
|
||||
#define CLR_DIALOG PIXEL(0,100,0)
|
||||
#define CLR_PC PIXEL(255,0,0)
|
||||
#define CLR_SP PIXEL(0,0,100)
|
||||
|
||||
static byte ChrDump(byte C)
|
||||
{
|
||||
return((C>=32)&&(C<128)? C:'.');
|
||||
}
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. **/
|
||||
/*************************************************************/
|
||||
byte DebugZ80(Z80 *R)
|
||||
{
|
||||
char S[1024];
|
||||
word A,Addr,ABuf[20];
|
||||
int J,I,K,X,Y,MemoryDump,DrawWindow,ExitNow;
|
||||
|
||||
/* If we don't have enough screen estate... */
|
||||
if((VideoW<32*8)||(VideoH<23*8))
|
||||
{
|
||||
/* Show warning message */
|
||||
CONMsg(
|
||||
-1,-1,-1,-1,PIXEL(255,255,255),PIXEL(255,0,0),
|
||||
"Error","Screen is\0too small!\0\0"
|
||||
);
|
||||
/* Continue emulation */
|
||||
R->Trace=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
X = ((VideoW>>3)-32)>>1;
|
||||
Y = ((VideoH>>3)-23)>>1;
|
||||
Addr = R->PC.W;
|
||||
A = ~Addr;
|
||||
K = 0;
|
||||
|
||||
for(DrawWindow=1,MemoryDump=ExitNow=0;!ExitNow&&VideoImg;)
|
||||
{
|
||||
if(DrawWindow)
|
||||
{
|
||||
CONWindow(X,Y,32,23,CLR_TEXT,CLR_BACK,"Z80 Debugger");
|
||||
|
||||
sprintf(S,"PC %04X",R->PC.W);
|
||||
CONSetColor(CLR_BACK,CLR_PC);
|
||||
CONPrint(X+24,Y+18,S);
|
||||
sprintf(S,"SP %04X",R->SP.W);
|
||||
CONSetColor(CLR_BACK,CLR_SP);
|
||||
CONPrint(X+24,Y+19,S);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,
|
||||
" %c%c%c%c%c%c\n\n"
|
||||
"AF %04X\nBC %04X\nDE %04X\nHL %04X\nIX %04X\nIY %04X\n\n"
|
||||
"AF'%04X\nBC'%04X\nDE'%04X\nHL'%04X\n\n"
|
||||
"IR %02X%02X",
|
||||
R->AF.B.l&0x80? 'S':'.',R->AF.B.l&0x40? 'Z':'.',R->AF.B.l&0x10? 'H':'.',
|
||||
R->AF.B.l&0x04? 'P':'.',R->AF.B.l&0x02? 'N':'.',R->AF.B.l&0x01? 'C':'.',
|
||||
R->AF.W,R->BC.W,R->DE.W,R->HL.W,
|
||||
R->IX.W,R->IY.W,
|
||||
R->AF1.W,R->BC1.W,R->DE1.W,R->HL1.W,
|
||||
R->I,R->R
|
||||
);
|
||||
CONPrint(X+24,Y+2,S);
|
||||
sprintf(S,
|
||||
"%s %s",
|
||||
R->IFF&0x04? "IM2":R->IFF&0x02? "IM1":"IM0",
|
||||
R->IFF&0x01? "EI":"DI"
|
||||
);
|
||||
CONPrint(X+25,Y+21,S);
|
||||
DrawWindow=0;
|
||||
A=~Addr;
|
||||
}
|
||||
|
||||
/* If top address has changed... */
|
||||
if(A!=Addr)
|
||||
{
|
||||
/* Clear display */
|
||||
CONBox((X+1)<<3,(Y+2)<<3,23*8,20*8,CLR_BACK);
|
||||
|
||||
if(MemoryDump)
|
||||
{
|
||||
/* Draw memory dump */
|
||||
for(J=0,A=Addr;J<20;J++,A+=4)
|
||||
{
|
||||
if(A==R->PC.W) CONSetColor(CLR_BACK,CLR_PC);
|
||||
else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
|
||||
else CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
|
||||
CONPrint(X+1,Y+J+2,S);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,
|
||||
"%02X %02X %02X %02X %c%c%c%c",
|
||||
RdZ80(A),RdZ80(A+1),RdZ80(A+2),RdZ80(A+3),
|
||||
ChrDump(RdZ80(A)),ChrDump(RdZ80(A+1)),
|
||||
ChrDump(RdZ80(A+2)),ChrDump(RdZ80(A+3))
|
||||
);
|
||||
CONPrint(X+7,Y+J+2,S);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw listing */
|
||||
for(J=0,A=Addr;J<20;J++)
|
||||
{
|
||||
if(A==R->PC.W) CONSetColor(CLR_BACK,CLR_PC);
|
||||
else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
|
||||
else CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
|
||||
CONPrint(X+1,Y+J+2,S);
|
||||
|
||||
ABuf[J]=A;
|
||||
A+=DAsm(S,A);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
CONPrintN(X+7,Y+J+2,S,23);
|
||||
}
|
||||
}
|
||||
|
||||
/* Display redrawn */
|
||||
A=Addr;
|
||||
}
|
||||
|
||||
/* Draw pointer */
|
||||
CONChar(X+6,Y+K+2,CON_ARROW);
|
||||
|
||||
/* Show screen buffer */
|
||||
ShowVideo();
|
||||
|
||||
/* Get key code */
|
||||
I=WaitKey();
|
||||
|
||||
/* Clear pointer */
|
||||
CONChar(X+6,Y+K+2,' ');
|
||||
|
||||
/* Get and process key code */
|
||||
switch(I)
|
||||
{
|
||||
case 'H':
|
||||
CONMsg(
|
||||
-1,-1,-1,-1,
|
||||
CLR_BACK,CLR_DIALOG,
|
||||
"Debugger Help",
|
||||
"ENTER - Execute next opcode\0"
|
||||
" UP - Previous opcode\0"
|
||||
" DOWN - Next opcode\0"
|
||||
" LEFT - Page up\0"
|
||||
"RIGHT - Page down\0"
|
||||
" H - This help page\0"
|
||||
" G - Go to address\0"
|
||||
" D - Disassembler view\0"
|
||||
" M - Memory dump view\0"
|
||||
" S - Show stack\0"
|
||||
" J - Jump to cursor\0"
|
||||
" R - Run to cursor\0"
|
||||
" C - Continue execution\0"
|
||||
" Q - Quit emulator\0"
|
||||
);
|
||||
DrawWindow=1;
|
||||
break;
|
||||
case CON_UP:
|
||||
if(K) --K;
|
||||
else
|
||||
if(MemoryDump) Addr-=4;
|
||||
else for(--Addr;Addr+DAsm(S,Addr)>A;--Addr);
|
||||
break;
|
||||
case CON_DOWN:
|
||||
if(K<19) ++K;
|
||||
else
|
||||
if(MemoryDump) Addr+=4;
|
||||
else Addr+=DAsm(S,Addr);
|
||||
break;
|
||||
case CON_LEFT:
|
||||
if(MemoryDump)
|
||||
Addr-=4*20;
|
||||
else
|
||||
{
|
||||
for(I=20,Addr=~A;(Addr>A)||((A^Addr)&~Addr&0x8000);++I)
|
||||
for(J=0,Addr=A-I;J<20;++J) Addr+=DAsm(S,Addr);
|
||||
Addr=A-I+1;
|
||||
}
|
||||
break;
|
||||
case CON_RIGHT:
|
||||
if(MemoryDump)
|
||||
Addr+=4*20;
|
||||
else
|
||||
for(J=0;J<20;++J) Addr+=DAsm(S,Addr);
|
||||
break;
|
||||
case CON_OK:
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'Q':
|
||||
return(0);
|
||||
case CON_EXIT:
|
||||
case 'C':
|
||||
R->Trap=0xFFFF;
|
||||
R->Trace=0;
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'R':
|
||||
R->Trap=ABuf[K];
|
||||
R->Trace=0;
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'M':
|
||||
MemoryDump=1;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'S':
|
||||
MemoryDump=1;
|
||||
Addr=R->SP.W;
|
||||
K=0;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'D':
|
||||
MemoryDump=0;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'G':
|
||||
if(CONInput(-1,-1,CLR_BACK,CLR_DIALOG,"Go to Address:",S,5|CON_HEX))
|
||||
{ Addr=strtol(S,0,16);K=0; }
|
||||
DrawWindow=1;
|
||||
break;
|
||||
case 'J':
|
||||
R->PC.W=ABuf[K];
|
||||
A=~Addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue emulation */
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* CONDEBUG */
|
||||
#endif /* DEBUG */
|
||||
|
|
@ -1,436 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Debug.c **/
|
||||
/** **/
|
||||
/** This file contains the built-in debugging routine for **/
|
||||
/** the Z80 emulator which is called on each Z80 step when **/
|
||||
/** Trap!=0. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1995-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include "Z80.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FMSX
|
||||
#include "AY8910.h"
|
||||
extern AY8910 PSG;
|
||||
#endif
|
||||
|
||||
static const char *Mnemonics[256] =
|
||||
{
|
||||
"NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA",
|
||||
"EX AF,AF'","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA",
|
||||
"DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA",
|
||||
"JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA",
|
||||
"JR NZ,@h","LD HL,#h","LD (#h),HL","INC HL","INC H","DEC H","LD H,*h","DAA",
|
||||
"JR Z,@h","ADD HL,HL","LD HL,(#h)","DEC HL","INC L","DEC L","LD L,*h","CPL",
|
||||
"JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF",
|
||||
"JR C,@h","ADD HL,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF",
|
||||
"LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A",
|
||||
"LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A",
|
||||
"LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A",
|
||||
"LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A",
|
||||
"LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A",
|
||||
"LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A",
|
||||
"LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A",
|
||||
"LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A",
|
||||
"ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A",
|
||||
"ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A",
|
||||
"SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A",
|
||||
"SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A",
|
||||
"AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A",
|
||||
"XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A",
|
||||
"OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A",
|
||||
"CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A",
|
||||
"RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h",
|
||||
"RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h",
|
||||
"RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h",
|
||||
"RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h",
|
||||
"RET PO","POP HL","JP PO,#h","EX HL,(SP)","CALL PO,#h","PUSH HL","AND *h","RST 20h",
|
||||
"RET PE","LD PC,HL","JP PE,#h","EX DE,HL","CALL PE,#h","PFX_ED","XOR *h","RST 28h",
|
||||
"RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h",
|
||||
"RET M","LD SP,HL","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h"
|
||||
};
|
||||
|
||||
static const char *MnemonicsCB[256] =
|
||||
{
|
||||
"RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A",
|
||||
"RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A",
|
||||
"RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A",
|
||||
"RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A",
|
||||
"SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A",
|
||||
"SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A",
|
||||
"SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (HL)","SLL A",
|
||||
"SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A",
|
||||
"BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A",
|
||||
"BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A",
|
||||
"BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A",
|
||||
"BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A",
|
||||
"BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A",
|
||||
"BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A",
|
||||
"BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A",
|
||||
"BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A",
|
||||
"RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A",
|
||||
"RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A",
|
||||
"RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A",
|
||||
"RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A",
|
||||
"RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A",
|
||||
"RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A",
|
||||
"RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A",
|
||||
"RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A",
|
||||
"SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A",
|
||||
"SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A",
|
||||
"SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A",
|
||||
"SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A",
|
||||
"SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A",
|
||||
"SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A",
|
||||
"SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A",
|
||||
"SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A"
|
||||
};
|
||||
|
||||
static const char *MnemonicsED[256] =
|
||||
{
|
||||
"DB EDh,00h","DB EDh,01h","DB EDh,02h","DB EDh,03h",
|
||||
"DB EDh,04h","DB EDh,05h","DB EDh,06h","DB EDh,07h",
|
||||
"DB EDh,08h","DB EDh,09h","DB EDh,0Ah","DB EDh,0Bh",
|
||||
"DB EDh,0Ch","DB EDh,0Dh","DB EDh,0Eh","DB EDh,0Fh",
|
||||
"DB EDh,10h","DB EDh,11h","DB EDh,12h","DB EDh,13h",
|
||||
"DB EDh,14h","DB EDh,15h","DB EDh,16h","DB EDh,17h",
|
||||
"DB EDh,18h","DB EDh,19h","DB EDh,1Ah","DB EDh,1Bh",
|
||||
"DB EDh,1Ch","DB EDh,1Dh","DB EDh,1Eh","DB EDh,1Fh",
|
||||
"DB EDh,20h","DB EDh,21h","DB EDh,22h","DB EDh,23h",
|
||||
"DB EDh,24h","DB EDh,25h","DB EDh,26h","DB EDh,27h",
|
||||
"DB EDh,28h","DB EDh,29h","DB EDh,2Ah","DB EDh,2Bh",
|
||||
"DB EDh,2Ch","DB EDh,2Dh","DB EDh,2Eh","DB EDh,2Fh",
|
||||
"DB EDh,30h","DB EDh,31h","DB EDh,32h","DB EDh,33h",
|
||||
"DB EDh,34h","DB EDh,35h","DB EDh,36h","DB EDh,37h",
|
||||
"DB EDh,38h","DB EDh,39h","DB EDh,3Ah","DB EDh,3Bh",
|
||||
"DB EDh,3Ch","DB EDh,3Dh","DB EDh,3Eh","DB EDh,3Fh",
|
||||
"IN B,(C)","OUT (C),B","SBC HL,BC","LD (#h),BC",
|
||||
"NEG","RETN","IM 0","LD I,A",
|
||||
"IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(#h)",
|
||||
"DB EDh,4Ch","RETI","DB EDh,4Eh","LD R,A",
|
||||
"IN D,(C)","OUT (C),D","SBC HL,DE","LD (#h),DE",
|
||||
"DB EDh,54h","DB EDh,55h","IM 1","LD A,I",
|
||||
"IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(#h)",
|
||||
"DB EDh,5Ch","DB EDh,5Dh","IM 2","LD A,R",
|
||||
"IN H,(C)","OUT (C),H","SBC HL,HL","LD (#h),HL",
|
||||
"DB EDh,64h","DB EDh,65h","DB EDh,66h","RRD",
|
||||
"IN L,(C)","OUT (C),L","ADC HL,HL","LD HL,(#h)",
|
||||
"DB EDh,6Ch","DB EDh,6Dh","DB EDh,6Eh","RLD",
|
||||
"IN F,(C)","DB EDh,71h","SBC HL,SP","LD (#h),SP",
|
||||
"DB EDh,74h","DB EDh,75h","DB EDh,76h","DB EDh,77h",
|
||||
"IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(#h)",
|
||||
"DB EDh,7Ch","DB EDh,7Dh","DB EDh,7Eh","DB EDh,7Fh",
|
||||
"DB EDh,80h","DB EDh,81h","DB EDh,82h","DB EDh,83h",
|
||||
"DB EDh,84h","DB EDh,85h","DB EDh,86h","DB EDh,87h",
|
||||
"DB EDh,88h","DB EDh,89h","DB EDh,8Ah","DB EDh,8Bh",
|
||||
"DB EDh,8Ch","DB EDh,8Dh","DB EDh,8Eh","DB EDh,8Fh",
|
||||
"DB EDh,90h","DB EDh,91h","DB EDh,92h","DB EDh,93h",
|
||||
"DB EDh,94h","DB EDh,95h","DB EDh,96h","DB EDh,97h",
|
||||
"DB EDh,98h","DB EDh,99h","DB EDh,9Ah","DB EDh,9Bh",
|
||||
"DB EDh,9Ch","DB EDh,9Dh","DB EDh,9Eh","DB EDh,9Fh",
|
||||
"LDI","CPI","INI","OUTI",
|
||||
"DB EDh,A4h","DB EDh,A5h","DB EDh,A6h","DB EDh,A7h",
|
||||
"LDD","CPD","IND","OUTD",
|
||||
"DB EDh,ACh","DB EDh,ADh","DB EDh,AEh","DB EDh,AFh",
|
||||
"LDIR","CPIR","INIR","OTIR",
|
||||
"DB EDh,B4h","DB EDh,B5h","DB EDh,B6h","DB EDh,B7h",
|
||||
"LDDR","CPDR","INDR","OTDR",
|
||||
"DB EDh,BCh","DB EDh,BDh","DB EDh,BEh","DB EDh,BFh",
|
||||
"DB EDh,C0h","DB EDh,C1h","DB EDh,C2h","DB EDh,C3h",
|
||||
"DB EDh,C4h","DB EDh,C5h","DB EDh,C6h","DB EDh,C7h",
|
||||
"DB EDh,C8h","DB EDh,C9h","DB EDh,CAh","DB EDh,CBh",
|
||||
"DB EDh,CCh","DB EDh,CDh","DB EDh,CEh","DB EDh,CFh",
|
||||
"DB EDh,D0h","DB EDh,D1h","DB EDh,D2h","DB EDh,D3h",
|
||||
"DB EDh,D4h","DB EDh,D5h","DB EDh,D6h","DB EDh,D7h",
|
||||
"DB EDh,D8h","DB EDh,D9h","DB EDh,DAh","DB EDh,DBh",
|
||||
"DB EDh,DCh","DB EDh,DDh","DB EDh,DEh","DB EDh,DFh",
|
||||
"DB EDh,E0h","DB EDh,E1h","DB EDh,E2h","DB EDh,E3h",
|
||||
"DB EDh,E4h","DB EDh,E5h","DB EDh,E6h","DB EDh,E7h",
|
||||
"DB EDh,E8h","DB EDh,E9h","DB EDh,EAh","DB EDh,EBh",
|
||||
"DB EDh,ECh","DB EDh,EDh","DB EDh,EEh","DB EDh,EFh",
|
||||
"DB EDh,F0h","DB EDh,F1h","DB EDh,F2h","DB EDh,F3h",
|
||||
"DB EDh,F4h","DB EDh,F5h","DB EDh,F6h","DB EDh,F7h",
|
||||
"DB EDh,F8h","DB EDh,F9h","DB EDh,FAh","DB EDh,FBh",
|
||||
"DB EDh,FCh","DB EDh,FDh","DB EDh,FEh","DB EDh,FFh"
|
||||
};
|
||||
|
||||
static const char *MnemonicsXX[256] =
|
||||
{
|
||||
"NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA",
|
||||
"EX AF,AF'","ADD I%,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA",
|
||||
"DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA",
|
||||
"JR @h","ADD I%,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA",
|
||||
"JR NZ,@h","LD I%,#h","LD (#h),I%","INC I%","INC I%h","DEC I%h","LD I%h,*h","DAA",
|
||||
"JR Z,@h","ADD I%,I%","LD I%,(#h)","DEC I%","INC I%l","DEC I%l","LD I%l,*h","CPL",
|
||||
"JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (I%+^h)","DEC (I%+^h)","LD (I%+^h),*h","SCF",
|
||||
"JR C,@h","ADD I%,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF",
|
||||
"LD B,B","LD B,C","LD B,D","LD B,E","LD B,I%h","LD B,I%l","LD B,(I%+^h)","LD B,A",
|
||||
"LD C,B","LD C,C","LD C,D","LD C,E","LD C,I%h","LD C,I%l","LD C,(I%+^h)","LD C,A",
|
||||
"LD D,B","LD D,C","LD D,D","LD D,E","LD D,I%h","LD D,I%l","LD D,(I%+^h)","LD D,A",
|
||||
"LD E,B","LD E,C","LD E,D","LD E,E","LD E,I%h","LD E,I%l","LD E,(I%+^h)","LD E,A",
|
||||
"LD I%h,B","LD I%h,C","LD I%h,D","LD I%h,E","LD I%h,I%h","LD I%h,I%l","LD H,(I%+^h)","LD I%h,A",
|
||||
"LD I%l,B","LD I%l,C","LD I%l,D","LD I%l,E","LD I%l,I%h","LD I%l,I%l","LD L,(I%+^h)","LD I%l,A",
|
||||
"LD (I%+^h),B","LD (I%+^h),C","LD (I%+^h),D","LD (I%+^h),E","LD (I%+^h),H","LD (I%+^h),L","HALT","LD (I%+^h),A",
|
||||
"LD A,B","LD A,C","LD A,D","LD A,E","LD A,I%h","LD A,I%l","LD A,(I%+^h)","LD A,A",
|
||||
"ADD B","ADD C","ADD D","ADD E","ADD I%h","ADD I%l","ADD (I%+^h)","ADD A",
|
||||
"ADC B","ADC C","ADC D","ADC E","ADC I%h","ADC I%l","ADC (I%+^h)","ADC,A",
|
||||
"SUB B","SUB C","SUB D","SUB E","SUB I%h","SUB I%l","SUB (I%+^h)","SUB A",
|
||||
"SBC B","SBC C","SBC D","SBC E","SBC I%h","SBC I%l","SBC (I%+^h)","SBC A",
|
||||
"AND B","AND C","AND D","AND E","AND I%h","AND I%l","AND (I%+^h)","AND A",
|
||||
"XOR B","XOR C","XOR D","XOR E","XOR I%h","XOR I%l","XOR (I%+^h)","XOR A",
|
||||
"OR B","OR C","OR D","OR E","OR I%h","OR I%l","OR (I%+^h)","OR A",
|
||||
"CP B","CP C","CP D","CP E","CP I%h","CP I%l","CP (I%+^h)","CP A",
|
||||
"RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h",
|
||||
"RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h",
|
||||
"RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h",
|
||||
"RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h",
|
||||
"RET PO","POP I%","JP PO,#h","EX I%,(SP)","CALL PO,#h","PUSH I%","AND *h","RST 20h",
|
||||
"RET PE","LD PC,I%","JP PE,#h","EX DE,I%","CALL PE,#h","PFX_ED","XOR *h","RST 28h",
|
||||
"RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h",
|
||||
"RET M","LD SP,I%","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h"
|
||||
};
|
||||
|
||||
static const char *MnemonicsXCB[256] =
|
||||
{
|
||||
"RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (I%@h)","RLC A",
|
||||
"RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (I%@h)","RRC A",
|
||||
"RL B","RL C","RL D","RL E","RL H","RL L","RL (I%@h)","RL A",
|
||||
"RR B","RR C","RR D","RR E","RR H","RR L","RR (I%@h)","RR A",
|
||||
"SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (I%@h)","SLA A",
|
||||
"SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (I%@h)","SRA A",
|
||||
"SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (I%@h)","SLL A",
|
||||
"SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (I%@h)","SRL A",
|
||||
"BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(I%@h)","BIT 0,A",
|
||||
"BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(I%@h)","BIT 1,A",
|
||||
"BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(I%@h)","BIT 2,A",
|
||||
"BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(I%@h)","BIT 3,A",
|
||||
"BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(I%@h)","BIT 4,A",
|
||||
"BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(I%@h)","BIT 5,A",
|
||||
"BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(I%@h)","BIT 6,A",
|
||||
"BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(I%@h)","BIT 7,A",
|
||||
"RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(I%@h)","RES 0,A",
|
||||
"RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(I%@h)","RES 1,A",
|
||||
"RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(I%@h)","RES 2,A",
|
||||
"RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(I%@h)","RES 3,A",
|
||||
"RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(I%@h)","RES 4,A",
|
||||
"RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(I%@h)","RES 5,A",
|
||||
"RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(I%@h)","RES 6,A",
|
||||
"RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(I%@h)","RES 7,A",
|
||||
"SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(I%@h)","SET 0,A",
|
||||
"SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(I%@h)","SET 1,A",
|
||||
"SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(I%@h)","SET 2,A",
|
||||
"SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(I%@h)","SET 3,A",
|
||||
"SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(I%@h)","SET 4,A",
|
||||
"SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(I%@h)","SET 5,A",
|
||||
"SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(I%@h)","SET 6,A",
|
||||
"SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(I%@h)","SET 7,A"
|
||||
};
|
||||
|
||||
/** DAsm() ***************************************************/
|
||||
/** DAsm() will disassemble the code at adress A and put **/
|
||||
/** the output text into S. It will return the number of **/
|
||||
/** bytes disassembled. **/
|
||||
/*************************************************************/
|
||||
static int DAsm(char *S,word A)
|
||||
{
|
||||
char R[128],H[10],C,*P;
|
||||
const char *T;
|
||||
byte J,Offset;
|
||||
word B;
|
||||
|
||||
Offset=0;
|
||||
B=A;
|
||||
C='\0';
|
||||
J=0;
|
||||
|
||||
switch(RdZ80(B))
|
||||
{
|
||||
case 0xCB: B++;T=MnemonicsCB[RdZ80(B++)];break;
|
||||
case 0xED: B++;T=MnemonicsED[RdZ80(B++)];break;
|
||||
case 0xDD: B++;C='X';
|
||||
if(RdZ80(B)!=0xCB) T=MnemonicsXX[RdZ80(B++)];
|
||||
else
|
||||
{ B++;Offset=RdZ80(B++);J=1;T=MnemonicsXCB[RdZ80(B++)]; }
|
||||
break;
|
||||
case 0xFD: B++;C='Y';
|
||||
if(RdZ80(B)!=0xCB) T=MnemonicsXX[RdZ80(B++)];
|
||||
else
|
||||
{ B++;Offset=RdZ80(B++);J=1;T=MnemonicsXCB[RdZ80(B++)]; }
|
||||
break;
|
||||
default: T=Mnemonics[RdZ80(B++)];
|
||||
}
|
||||
|
||||
if(P=strchr(T,'^'))
|
||||
{
|
||||
strncpy(R,T,P-T);R[P-T]='\0';
|
||||
sprintf(H,"%02X",RdZ80(B++));
|
||||
strcat(R,H);strcat(R,P+1);
|
||||
}
|
||||
else strcpy(R,T);
|
||||
if(P=strchr(R,'%')) *P=C;
|
||||
|
||||
if(P=strchr(R,'*'))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
sprintf(H,"%02X",RdZ80(B++));
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
}
|
||||
else
|
||||
if(P=strchr(R,'@'))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
if(!J) Offset=RdZ80(B++);
|
||||
strcat(S,Offset&0x80? "-":"+");
|
||||
J=Offset&0x80? 256-Offset:Offset;
|
||||
sprintf(H,"%02X",J);
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
}
|
||||
else
|
||||
if(P=strchr(R,'#'))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
sprintf(H,"%04X",RdZ80(B)+256*RdZ80(B+1));
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
B+=2;
|
||||
}
|
||||
else strcpy(S,R);
|
||||
|
||||
return(B-A);
|
||||
}
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. **/
|
||||
/*************************************************************/
|
||||
byte DebugZ80(Z80 *R)
|
||||
{
|
||||
static const char Flags[9] = "SZ.H.PNC";
|
||||
char S[128],T[10];
|
||||
byte J,I;
|
||||
|
||||
DAsm(S,R->PC.W);
|
||||
for(J=0,I=R->AF.B.l;J<8;J++,I<<=1) T[J]=I&0x80? Flags[J]:'.';
|
||||
T[8]='\0';
|
||||
|
||||
printf
|
||||
(
|
||||
"AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X IX:%04X IY:%04X I:%02X\n",
|
||||
R->AF.W,R->HL.W,R->DE.W,R->BC.W,R->PC.W,R->SP.W,R->IX.W,R->IY.W,R->I
|
||||
);
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%04X] FLAGS: [%s] %s: %s\n\n",
|
||||
RdZ80(R->PC.W),S,RdZ80(R->SP.W)+RdZ80(R->SP.W+1)*256,T,
|
||||
R->IFF&0x04? "IM2":R->IFF&0x02? "IM1":"IM0",
|
||||
R->IFF&0x01? "EI":"DI"
|
||||
);
|
||||
|
||||
while(1)
|
||||
{
|
||||
printf("\n[Command,'?']-> ");
|
||||
fflush(stdout);fflush(stdin);
|
||||
|
||||
fgets(S,50,stdin);
|
||||
for(J=0;S[J]>=' ';J++)
|
||||
S[J]=toupper(S[J]);
|
||||
S[J]='\0';
|
||||
|
||||
switch(S[0])
|
||||
{
|
||||
case 'H':
|
||||
case '?':
|
||||
puts("\n***** Built-in Z80 Debugger Commands *****");
|
||||
puts("<CR> : Break at next instruction");
|
||||
puts("= <addr> : Break at addr");
|
||||
puts("+ <offset> : Break at PC + offset");
|
||||
puts("c : Continue without break");
|
||||
puts("j <addr> : Continue from addr");
|
||||
puts("m <addr> : Memory dump at addr");
|
||||
puts("d <addr> : Disassembly at addr");
|
||||
puts("?,h : Show this help text");
|
||||
puts("q : Exit Z80 emulation");
|
||||
break;
|
||||
|
||||
case '\0': return(1);
|
||||
case '=': if(strlen(S)>=2)
|
||||
{ sscanf(S+1,"%hX",&(R->Trap));R->Trace=0;return(1); }
|
||||
break;
|
||||
case '+': if(strlen(S)>=2)
|
||||
{
|
||||
sscanf(S+1,"%hX",&(R->Trap));
|
||||
R->Trap+=R->PC.W;R->Trace=0;
|
||||
return(1);
|
||||
}
|
||||
break;
|
||||
case 'J': if(strlen(S)>=2)
|
||||
{ sscanf(S+1,"%hX",&(R->PC.W));R->Trace=0;return(1); }
|
||||
break;
|
||||
case 'C': R->Trap=0xFFFF;R->Trace=0;return(1);
|
||||
case 'Q': return(0);
|
||||
|
||||
case 'M':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
|
||||
puts("");
|
||||
for(J=0;J<16;J++)
|
||||
{
|
||||
printf("%04X: ",Addr);
|
||||
for(I=0;I<16;I++,Addr++)
|
||||
printf("%02X ",RdZ80(Addr));
|
||||
printf(" | ");Addr-=16;
|
||||
for(I=0;I<16;I++,Addr++)
|
||||
putchar(isprint(RdZ80(Addr))? RdZ80(Addr):'.');
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
|
||||
puts("");
|
||||
for(J=0;J<16;J++)
|
||||
{
|
||||
printf("%04X: ",Addr);
|
||||
Addr+=DAsm(S,Addr);
|
||||
puts(S);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef FMSX
|
||||
case 'S':
|
||||
for(J=0;J<AY8910_CHANNELS;J++)
|
||||
{
|
||||
printf("Channel %d: Volume %d, Frequency %dHz",J,PSG.Volume[J],PSG.Freq[J]);
|
||||
if(!(PSG.R[8+(J%3)]&0x10)) printf("\n");
|
||||
else printf(", Envelope %d\n",PSG.R[8+(J%3)]&0x0F);
|
||||
}
|
||||
printf("Envelope period %dms\n",PSG.EPeriod);
|
||||
break;
|
||||
#endif /* FMSX */
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue emulation */
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
|
@ -1,447 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Tables.h **/
|
||||
/** **/
|
||||
/** This file contains tables of used by Z80 emulation to **/
|
||||
/** compute SIGN,ZERO, PARITY flags, and decimal correction **/
|
||||
/** There are also timing tables for Z80 opcodes. This file **/
|
||||
/** is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
static const byte Cycles[256] =
|
||||
{
|
||||
4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4,
|
||||
8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4,
|
||||
7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4,
|
||||
7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11,
|
||||
5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11,
|
||||
5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11,
|
||||
5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11
|
||||
};
|
||||
|
||||
static const byte CyclesCB[256] =
|
||||
{
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8
|
||||
};
|
||||
|
||||
static const byte CyclesED[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9,
|
||||
12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9,
|
||||
12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18,
|
||||
12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const byte CyclesXX[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0,
|
||||
0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9,
|
||||
19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const byte CyclesXXCB[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0
|
||||
};
|
||||
|
||||
static const byte ZSTable[256] =
|
||||
{
|
||||
Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG
|
||||
};
|
||||
|
||||
static const byte PZSTable[256] =
|
||||
{
|
||||
Z_FLAG|P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG
|
||||
};
|
||||
|
||||
static const word DAATable[2048] =
|
||||
{
|
||||
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,
|
||||
0x0808,0x090C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704,
|
||||
0x180C,0x1908,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
|
||||
0x282C,0x2928,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,
|
||||
0x3828,0x392C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704,
|
||||
0x480C,0x4908,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,
|
||||
0x5808,0x590C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720,
|
||||
0x6828,0x692C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
|
||||
0x782C,0x7928,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,
|
||||
0x888C,0x8988,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780,
|
||||
0x9888,0x998C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6025,0x6121,0x6221,0x6325,0x6421,0x6525,0x6625,0x6721,
|
||||
0x6829,0x692D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7021,0x7125,0x7225,0x7321,0x7425,0x7521,0x7621,0x7725,
|
||||
0x782D,0x7929,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8081,0x8185,0x8285,0x8381,0x8485,0x8581,0x8681,0x8785,
|
||||
0x888D,0x8989,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9085,0x9181,0x9281,0x9385,0x9481,0x9585,0x9685,0x9781,
|
||||
0x9889,0x998D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA0A5,0xA1A1,0xA2A1,0xA3A5,0xA4A1,0xA5A5,0xA6A5,0xA7A1,
|
||||
0xA8A9,0xA9AD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB0A1,0xB1A5,0xB2A5,0xB3A1,0xB4A5,0xB5A1,0xB6A1,0xB7A5,
|
||||
0xB8AD,0xB9A9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC085,0xC181,0xC281,0xC385,0xC481,0xC585,0xC685,0xC781,
|
||||
0xC889,0xC98D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD081,0xD185,0xD285,0xD381,0xD485,0xD581,0xD681,0xD785,
|
||||
0xD88D,0xD989,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE0A1,0xE1A5,0xE2A5,0xE3A1,0xE4A5,0xE5A1,0xE6A1,0xE7A5,
|
||||
0xE8AD,0xE9A9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF0A5,0xF1A1,0xF2A1,0xF3A5,0xF4A1,0xF5A5,0xF6A5,0xF7A1,
|
||||
0xF8A9,0xF9AD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0604,0x0700,0x0808,0x090C,0x0A0C,0x0B08,0x0C0C,0x0D08,
|
||||
0x0E08,0x0F0C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1600,0x1704,0x180C,0x1908,0x1A08,0x1B0C,0x1C08,0x1D0C,
|
||||
0x1E0C,0x1F08,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2620,0x2724,0x282C,0x2928,0x2A28,0x2B2C,0x2C28,0x2D2C,
|
||||
0x2E2C,0x2F28,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3624,0x3720,0x3828,0x392C,0x3A2C,0x3B28,0x3C2C,0x3D28,
|
||||
0x3E28,0x3F2C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4600,0x4704,0x480C,0x4908,0x4A08,0x4B0C,0x4C08,0x4D0C,
|
||||
0x4E0C,0x4F08,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5604,0x5700,0x5808,0x590C,0x5A0C,0x5B08,0x5C0C,0x5D08,
|
||||
0x5E08,0x5F0C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6624,0x6720,0x6828,0x692C,0x6A2C,0x6B28,0x6C2C,0x6D28,
|
||||
0x6E28,0x6F2C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7620,0x7724,0x782C,0x7928,0x7A28,0x7B2C,0x7C28,0x7D2C,
|
||||
0x7E2C,0x7F28,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8680,0x8784,0x888C,0x8988,0x8A88,0x8B8C,0x8C88,0x8D8C,
|
||||
0x8E8C,0x8F88,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9684,0x9780,0x9888,0x998C,0x9A8C,0x9B88,0x9C8C,0x9D88,
|
||||
0x9E88,0x9F8C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6625,0x6721,0x6829,0x692D,0x6A2D,0x6B29,0x6C2D,0x6D29,
|
||||
0x6E29,0x6F2D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7621,0x7725,0x782D,0x7929,0x7A29,0x7B2D,0x7C29,0x7D2D,
|
||||
0x7E2D,0x7F29,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8681,0x8785,0x888D,0x8989,0x8A89,0x8B8D,0x8C89,0x8D8D,
|
||||
0x8E8D,0x8F89,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9685,0x9781,0x9889,0x998D,0x9A8D,0x9B89,0x9C8D,0x9D89,
|
||||
0x9E89,0x9F8D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA6A5,0xA7A1,0xA8A9,0xA9AD,0xAAAD,0xABA9,0xACAD,0xADA9,
|
||||
0xAEA9,0xAFAD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xBAA9,0xBBAD,0xBCA9,0xBDAD,
|
||||
0xBEAD,0xBFA9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC685,0xC781,0xC889,0xC98D,0xCA8D,0xCB89,0xCC8D,0xCD89,
|
||||
0xCE89,0xCF8D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD681,0xD785,0xD88D,0xD989,0xDA89,0xDB8D,0xDC89,0xDD8D,
|
||||
0xDE8D,0xDF89,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE6A1,0xE7A5,0xE8AD,0xE9A9,0xEAA9,0xEBAD,0xECA9,0xEDAD,
|
||||
0xEEAD,0xEFA9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF6A5,0xF7A1,0xF8A9,0xF9AD,0xFAAD,0xFBA9,0xFCAD,0xFDA9,
|
||||
0xFEA9,0xFFAD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,
|
||||
0x080A,0x090E,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x1002,0x1106,0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,
|
||||
0x180E,0x190A,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,
|
||||
0x282E,0x292A,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,
|
||||
0x382A,0x392E,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x4002,0x4106,0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,
|
||||
0x480E,0x490A,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,
|
||||
0x580A,0x590E,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x6026,0x6122,0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,
|
||||
0x682A,0x692E,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,
|
||||
0x782E,0x792A,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,
|
||||
0x888E,0x898A,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x9086,0x9182,0x9282,0x9386,0x9482,0x9586,0x9686,0x9782,
|
||||
0x988A,0x998E,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xA0A7,0xA1A3,0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,
|
||||
0xA8AB,0xA9AF,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,
|
||||
0xB8AF,0xB9AB,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,
|
||||
0xC88B,0xC98F,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xD083,0xD187,0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,
|
||||
0xD88F,0xD98B,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,
|
||||
0xE8AF,0xE9AB,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xF0A7,0xF1A3,0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,
|
||||
0xF8AB,0xF9AF,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,
|
||||
0x080B,0x090F,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,
|
||||
0x180F,0x190B,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x2023,0x2127,0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,
|
||||
0x282F,0x292B,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xFABE,0xFBBA,0xFCBE,0xFDBA,0xFEBA,0xFFBE,0x0046,0x0102,
|
||||
0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x0A1E,0x0B1A,0x0C1E,0x0D1A,0x0E1A,0x0F1E,0x1002,0x1106,
|
||||
0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x1A1A,0x1B1E,0x1C1A,0x1D1E,0x1E1E,0x1F1A,0x2022,0x2126,
|
||||
0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x2A3A,0x2B3E,0x2C3A,0x2D3E,0x2E3E,0x2F3A,0x3026,0x3122,
|
||||
0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x3A3E,0x3B3A,0x3C3E,0x3D3A,0x3E3A,0x3F3E,0x4002,0x4106,
|
||||
0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x4A1A,0x4B1E,0x4C1A,0x4D1E,0x4E1E,0x4F1A,0x5006,0x5102,
|
||||
0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x5A1E,0x5B1A,0x5C1E,0x5D1A,0x5E1A,0x5F1E,0x6026,0x6122,
|
||||
0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x6A3E,0x6B3A,0x6C3E,0x6D3A,0x6E3A,0x6F3E,0x7022,0x7126,
|
||||
0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x7A3A,0x7B3E,0x7C3A,0x7D3E,0x7E3E,0x7F3A,0x8082,0x8186,
|
||||
0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x8A9A,0x8B9E,0x8C9A,0x8D9E,0x8E9E,0x8F9A,0x9086,0x9182,
|
||||
0x9282,0x9386,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0x9A9F,0x9B9B,0x9C9F,0x9D9B,0x9E9B,0x9F9F,0xA0A7,0xA1A3,
|
||||
0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xAABF,0xABBB,0xACBF,0xADBB,0xAEBB,0xAFBF,0xB0A3,0xB1A7,
|
||||
0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xBABB,0xBBBF,0xBCBB,0xBDBF,0xBEBF,0xBFBB,0xC087,0xC183,
|
||||
0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xCA9F,0xCB9B,0xCC9F,0xCD9B,0xCE9B,0xCF9F,0xD083,0xD187,
|
||||
0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xDA9B,0xDB9F,0xDC9B,0xDD9F,0xDE9F,0xDF9B,0xE0A3,0xE1A7,
|
||||
0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xEABB,0xEBBF,0xECBB,0xEDBF,0xEEBF,0xEFBB,0xF0A7,0xF1A3,
|
||||
0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0xFABF,0xFBBB,0xFCBF,0xFDBB,0xFEBB,0xFFBF,0x0047,0x0103,
|
||||
0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x0A1F,0x0B1B,0x0C1F,0x0D1B,0x0E1B,0x0F1F,0x1003,0x1107,
|
||||
0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x1A1B,0x1B1F,0x1C1B,0x1D1F,0x1E1F,0x1F1B,0x2023,0x2127,
|
||||
0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x2A3B,0x2B3F,0x2C3B,0x2D3F,0x2E3F,0x2F3B,0x3027,0x3123,
|
||||
0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F
|
||||
};
|
||||
|
|
@ -1,703 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.c **/
|
||||
/** **/
|
||||
/** This file contains implementation for Z80 CPU. Don't **/
|
||||
/** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(), **/
|
||||
/** LoopZ80(), and PatchZ80() functions to accomodate the **/
|
||||
/** emulated machine's architecture. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#define GENESIS 1
|
||||
|
||||
#include "Z80.h"
|
||||
#include "Tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** C99 standard has "inline", but older compilers used **/
|
||||
/** __inline for the same purpose. **/
|
||||
/*************************************************************/
|
||||
#ifdef __C99__
|
||||
#define INLINE static inline
|
||||
#else
|
||||
#define INLINE static __inline
|
||||
#endif
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef COLEM
|
||||
#define RdZ80 RDZ80
|
||||
extern byte *ROMPage[];
|
||||
INLINE byte RdZ80(word A) { return(ROMPage[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
#ifdef SPECCY
|
||||
#define RdZ80 RDZ80
|
||||
#define WrZ80 WRZ80
|
||||
extern byte *Page[],*ROM;
|
||||
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
INLINE void WrZ80(word A,byte V) { if(Page[A>>13]<ROM) Page[A>>13][A&0x1FFF]=V; }
|
||||
#endif
|
||||
|
||||
#ifdef MG
|
||||
#define RdZ80 RDZ80
|
||||
extern byte *Page[];
|
||||
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
#ifdef FMSX
|
||||
#define FAST_RDOP
|
||||
extern byte *RAM[];
|
||||
INLINE byte OpZ80(word A) { return(RAM[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
#ifdef GENESIS
|
||||
#define FAST_RDOP
|
||||
extern byte *Z80_RAM[];
|
||||
INLINE byte OpZ80(word A) { return(Z80_RAM[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
/** FAST_RDOP ************************************************/
|
||||
/** With this #define not present, RdZ80() should perform **/
|
||||
/** the functions of OpZ80(). **/
|
||||
/*************************************************************/
|
||||
#ifndef FAST_RDOP
|
||||
#define OpZ80(A) RdZ80(A)
|
||||
#endif
|
||||
|
||||
#define S(Fl) R->AF.B.l|=Fl
|
||||
#define R(Fl) R->AF.B.l&=~(Fl)
|
||||
#define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg]
|
||||
|
||||
#define M_RLC(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RRC(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RL(Rg) \
|
||||
if(Rg&0x80) \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
#define M_RR(Rg) \
|
||||
if(Rg&0x01) \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
|
||||
#define M_SLA(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRA(Rg) \
|
||||
R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_SLL(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRL(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_BIT(Bit,Rg) \
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|H_FLAG|PZSTable[Rg&(1<<Bit)]
|
||||
|
||||
#define M_SET(Bit,Rg) Rg|=1<<Bit
|
||||
#define M_RES(Bit,Rg) Rg&=~(1<<Bit)
|
||||
|
||||
#define M_POP(Rg) \
|
||||
R->Rg.B.l=OpZ80(R->SP.W++);R->Rg.B.h=OpZ80(R->SP.W++)
|
||||
#define M_PUSH(Rg) \
|
||||
WrZ80(--R->SP.W,R->Rg.B.h);WrZ80(--R->SP.W,R->Rg.B.l)
|
||||
|
||||
#define M_CALL \
|
||||
J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W++); \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \
|
||||
R->PC.W=J.W; \
|
||||
JumpZ80(J.W)
|
||||
|
||||
#define M_JP J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W);R->PC.W=J.W;JumpZ80(J.W)
|
||||
#define M_JR R->PC.W+=(offset)OpZ80(R->PC.W)+1;JumpZ80(R->PC.W)
|
||||
#define M_RET R->PC.B.l=OpZ80(R->SP.W++);R->PC.B.h=OpZ80(R->SP.W++);JumpZ80(R->PC.W)
|
||||
|
||||
#define M_RST(Ad) \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l);R->PC.W=Ad;JumpZ80(Ad)
|
||||
|
||||
#define M_LDWORD(Rg) \
|
||||
R->Rg.B.l=OpZ80(R->PC.W++);R->Rg.B.h=OpZ80(R->PC.W++)
|
||||
|
||||
#define M_ADD(Rg) \
|
||||
J.W=R->AF.B.h+Rg; \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SUB(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SBC(Rg) \
|
||||
J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_CP(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG)
|
||||
|
||||
#define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h]
|
||||
#define M_OR(Rg) R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
#define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
|
||||
#define M_IN(Rg) \
|
||||
Rg=InZ80(R->BC.W); \
|
||||
R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG)
|
||||
|
||||
#define M_INC(Rg) \
|
||||
Rg++; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG)
|
||||
|
||||
#define M_DEC(Rg) \
|
||||
Rg--; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0)
|
||||
|
||||
#define M_ADDW(Rg1,Rg2) \
|
||||
J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))| \
|
||||
((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \
|
||||
R->Rg1.W=J.W
|
||||
|
||||
#define M_ADCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \
|
||||
(~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
#define M_SBCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG| \
|
||||
(((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
enum Codes
|
||||
{
|
||||
NOP,LD_BC_WORD,LD_xBC_A,INC_BC,INC_B,DEC_B,LD_B_BYTE,RLCA,
|
||||
EX_AF_AF,ADD_HL_BC,LD_A_xBC,DEC_BC,INC_C,DEC_C,LD_C_BYTE,RRCA,
|
||||
DJNZ,LD_DE_WORD,LD_xDE_A,INC_DE,INC_D,DEC_D,LD_D_BYTE,RLA,
|
||||
JR,ADD_HL_DE,LD_A_xDE,DEC_DE,INC_E,DEC_E,LD_E_BYTE,RRA,
|
||||
JR_NZ,LD_HL_WORD,LD_xWORD_HL,INC_HL,INC_H,DEC_H,LD_H_BYTE,DAA,
|
||||
JR_Z,ADD_HL_HL,LD_HL_xWORD,DEC_HL,INC_L,DEC_L,LD_L_BYTE,CPL,
|
||||
JR_NC,LD_SP_WORD,LD_xWORD_A,INC_SP,INC_xHL,DEC_xHL,LD_xHL_BYTE,SCF,
|
||||
JR_C,ADD_HL_SP,LD_A_xWORD,DEC_SP,INC_A,DEC_A,LD_A_BYTE,CCF,
|
||||
LD_B_B,LD_B_C,LD_B_D,LD_B_E,LD_B_H,LD_B_L,LD_B_xHL,LD_B_A,
|
||||
LD_C_B,LD_C_C,LD_C_D,LD_C_E,LD_C_H,LD_C_L,LD_C_xHL,LD_C_A,
|
||||
LD_D_B,LD_D_C,LD_D_D,LD_D_E,LD_D_H,LD_D_L,LD_D_xHL,LD_D_A,
|
||||
LD_E_B,LD_E_C,LD_E_D,LD_E_E,LD_E_H,LD_E_L,LD_E_xHL,LD_E_A,
|
||||
LD_H_B,LD_H_C,LD_H_D,LD_H_E,LD_H_H,LD_H_L,LD_H_xHL,LD_H_A,
|
||||
LD_L_B,LD_L_C,LD_L_D,LD_L_E,LD_L_H,LD_L_L,LD_L_xHL,LD_L_A,
|
||||
LD_xHL_B,LD_xHL_C,LD_xHL_D,LD_xHL_E,LD_xHL_H,LD_xHL_L,HALT,LD_xHL_A,
|
||||
LD_A_B,LD_A_C,LD_A_D,LD_A_E,LD_A_H,LD_A_L,LD_A_xHL,LD_A_A,
|
||||
ADD_B,ADD_C,ADD_D,ADD_E,ADD_H,ADD_L,ADD_xHL,ADD_A,
|
||||
ADC_B,ADC_C,ADC_D,ADC_E,ADC_H,ADC_L,ADC_xHL,ADC_A,
|
||||
SUB_B,SUB_C,SUB_D,SUB_E,SUB_H,SUB_L,SUB_xHL,SUB_A,
|
||||
SBC_B,SBC_C,SBC_D,SBC_E,SBC_H,SBC_L,SBC_xHL,SBC_A,
|
||||
AND_B,AND_C,AND_D,AND_E,AND_H,AND_L,AND_xHL,AND_A,
|
||||
XOR_B,XOR_C,XOR_D,XOR_E,XOR_H,XOR_L,XOR_xHL,XOR_A,
|
||||
OR_B,OR_C,OR_D,OR_E,OR_H,OR_L,OR_xHL,OR_A,
|
||||
CP_B,CP_C,CP_D,CP_E,CP_H,CP_L,CP_xHL,CP_A,
|
||||
RET_NZ,POP_BC,JP_NZ,JP,CALL_NZ,PUSH_BC,ADD_BYTE,RST00,
|
||||
RET_Z,RET,JP_Z,PFX_CB,CALL_Z,CALL,ADC_BYTE,RST08,
|
||||
RET_NC,POP_DE,JP_NC,OUTA,CALL_NC,PUSH_DE,SUB_BYTE,RST10,
|
||||
RET_C,EXX,JP_C,INA,CALL_C,PFX_DD,SBC_BYTE,RST18,
|
||||
RET_PO,POP_HL,JP_PO,EX_HL_xSP,CALL_PO,PUSH_HL,AND_BYTE,RST20,
|
||||
RET_PE,LD_PC_HL,JP_PE,EX_DE_HL,CALL_PE,PFX_ED,XOR_BYTE,RST28,
|
||||
RET_P,POP_AF,JP_P,DI,CALL_P,PUSH_AF,OR_BYTE,RST30,
|
||||
RET_M,LD_SP_HL,JP_M,EI,CALL_M,PFX_FD,CP_BYTE,RST38
|
||||
};
|
||||
|
||||
enum CodesCB
|
||||
{
|
||||
RLC_B,RLC_C,RLC_D,RLC_E,RLC_H,RLC_L,RLC_xHL,RLC_A,
|
||||
RRC_B,RRC_C,RRC_D,RRC_E,RRC_H,RRC_L,RRC_xHL,RRC_A,
|
||||
RL_B,RL_C,RL_D,RL_E,RL_H,RL_L,RL_xHL,RL_A,
|
||||
RR_B,RR_C,RR_D,RR_E,RR_H,RR_L,RR_xHL,RR_A,
|
||||
SLA_B,SLA_C,SLA_D,SLA_E,SLA_H,SLA_L,SLA_xHL,SLA_A,
|
||||
SRA_B,SRA_C,SRA_D,SRA_E,SRA_H,SRA_L,SRA_xHL,SRA_A,
|
||||
SLL_B,SLL_C,SLL_D,SLL_E,SLL_H,SLL_L,SLL_xHL,SLL_A,
|
||||
SRL_B,SRL_C,SRL_D,SRL_E,SRL_H,SRL_L,SRL_xHL,SRL_A,
|
||||
BIT0_B,BIT0_C,BIT0_D,BIT0_E,BIT0_H,BIT0_L,BIT0_xHL,BIT0_A,
|
||||
BIT1_B,BIT1_C,BIT1_D,BIT1_E,BIT1_H,BIT1_L,BIT1_xHL,BIT1_A,
|
||||
BIT2_B,BIT2_C,BIT2_D,BIT2_E,BIT2_H,BIT2_L,BIT2_xHL,BIT2_A,
|
||||
BIT3_B,BIT3_C,BIT3_D,BIT3_E,BIT3_H,BIT3_L,BIT3_xHL,BIT3_A,
|
||||
BIT4_B,BIT4_C,BIT4_D,BIT4_E,BIT4_H,BIT4_L,BIT4_xHL,BIT4_A,
|
||||
BIT5_B,BIT5_C,BIT5_D,BIT5_E,BIT5_H,BIT5_L,BIT5_xHL,BIT5_A,
|
||||
BIT6_B,BIT6_C,BIT6_D,BIT6_E,BIT6_H,BIT6_L,BIT6_xHL,BIT6_A,
|
||||
BIT7_B,BIT7_C,BIT7_D,BIT7_E,BIT7_H,BIT7_L,BIT7_xHL,BIT7_A,
|
||||
RES0_B,RES0_C,RES0_D,RES0_E,RES0_H,RES0_L,RES0_xHL,RES0_A,
|
||||
RES1_B,RES1_C,RES1_D,RES1_E,RES1_H,RES1_L,RES1_xHL,RES1_A,
|
||||
RES2_B,RES2_C,RES2_D,RES2_E,RES2_H,RES2_L,RES2_xHL,RES2_A,
|
||||
RES3_B,RES3_C,RES3_D,RES3_E,RES3_H,RES3_L,RES3_xHL,RES3_A,
|
||||
RES4_B,RES4_C,RES4_D,RES4_E,RES4_H,RES4_L,RES4_xHL,RES4_A,
|
||||
RES5_B,RES5_C,RES5_D,RES5_E,RES5_H,RES5_L,RES5_xHL,RES5_A,
|
||||
RES6_B,RES6_C,RES6_D,RES6_E,RES6_H,RES6_L,RES6_xHL,RES6_A,
|
||||
RES7_B,RES7_C,RES7_D,RES7_E,RES7_H,RES7_L,RES7_xHL,RES7_A,
|
||||
SET0_B,SET0_C,SET0_D,SET0_E,SET0_H,SET0_L,SET0_xHL,SET0_A,
|
||||
SET1_B,SET1_C,SET1_D,SET1_E,SET1_H,SET1_L,SET1_xHL,SET1_A,
|
||||
SET2_B,SET2_C,SET2_D,SET2_E,SET2_H,SET2_L,SET2_xHL,SET2_A,
|
||||
SET3_B,SET3_C,SET3_D,SET3_E,SET3_H,SET3_L,SET3_xHL,SET3_A,
|
||||
SET4_B,SET4_C,SET4_D,SET4_E,SET4_H,SET4_L,SET4_xHL,SET4_A,
|
||||
SET5_B,SET5_C,SET5_D,SET5_E,SET5_H,SET5_L,SET5_xHL,SET5_A,
|
||||
SET6_B,SET6_C,SET6_D,SET6_E,SET6_H,SET6_L,SET6_xHL,SET6_A,
|
||||
SET7_B,SET7_C,SET7_D,SET7_E,SET7_H,SET7_L,SET7_xHL,SET7_A
|
||||
};
|
||||
|
||||
enum CodesED
|
||||
{
|
||||
DB_00,DB_01,DB_02,DB_03,DB_04,DB_05,DB_06,DB_07,
|
||||
DB_08,DB_09,DB_0A,DB_0B,DB_0C,DB_0D,DB_0E,DB_0F,
|
||||
DB_10,DB_11,DB_12,DB_13,DB_14,DB_15,DB_16,DB_17,
|
||||
DB_18,DB_19,DB_1A,DB_1B,DB_1C,DB_1D,DB_1E,DB_1F,
|
||||
DB_20,DB_21,DB_22,DB_23,DB_24,DB_25,DB_26,DB_27,
|
||||
DB_28,DB_29,DB_2A,DB_2B,DB_2C,DB_2D,DB_2E,DB_2F,
|
||||
DB_30,DB_31,DB_32,DB_33,DB_34,DB_35,DB_36,DB_37,
|
||||
DB_38,DB_39,DB_3A,DB_3B,DB_3C,DB_3D,DB_3E,DB_3F,
|
||||
IN_B_xC,OUT_xC_B,SBC_HL_BC,LD_xWORDe_BC,NEG,RETN,IM_0,LD_I_A,
|
||||
IN_C_xC,OUT_xC_C,ADC_HL_BC,LD_BC_xWORDe,DB_4C,RETI,DB_,LD_R_A,
|
||||
IN_D_xC,OUT_xC_D,SBC_HL_DE,LD_xWORDe_DE,DB_54,DB_55,IM_1,LD_A_I,
|
||||
IN_E_xC,OUT_xC_E,ADC_HL_DE,LD_DE_xWORDe,DB_5C,DB_5D,IM_2,LD_A_R,
|
||||
IN_H_xC,OUT_xC_H,SBC_HL_HL,LD_xWORDe_HL,DB_64,DB_65,DB_66,RRD,
|
||||
IN_L_xC,OUT_xC_L,ADC_HL_HL,LD_HL_xWORDe,DB_6C,DB_6D,DB_6E,RLD,
|
||||
IN_F_xC,DB_71,SBC_HL_SP,LD_xWORDe_SP,DB_74,DB_75,DB_76,DB_77,
|
||||
IN_A_xC,OUT_xC_A,ADC_HL_SP,LD_SP_xWORDe,DB_7C,DB_7D,DB_7E,DB_7F,
|
||||
DB_80,DB_81,DB_82,DB_83,DB_84,DB_85,DB_86,DB_87,
|
||||
DB_88,DB_89,DB_8A,DB_8B,DB_8C,DB_8D,DB_8E,DB_8F,
|
||||
DB_90,DB_91,DB_92,DB_93,DB_94,DB_95,DB_96,DB_97,
|
||||
DB_98,DB_99,DB_9A,DB_9B,DB_9C,DB_9D,DB_9E,DB_9F,
|
||||
LDI,CPI,INI,OUTI,DB_A4,DB_A5,DB_A6,DB_A7,
|
||||
LDD,CPD,IND,OUTD,DB_AC,DB_AD,DB_AE,DB_AF,
|
||||
LDIR,CPIR,INIR,OTIR,DB_B4,DB_B5,DB_B6,DB_B7,
|
||||
LDDR,CPDR,INDR,OTDR,DB_BC,DB_BD,DB_BE,DB_BF,
|
||||
DB_C0,DB_C1,DB_C2,DB_C3,DB_C4,DB_C5,DB_C6,DB_C7,
|
||||
DB_C8,DB_C9,DB_CA,DB_CB,DB_CC,DB_CD,DB_CE,DB_CF,
|
||||
DB_D0,DB_D1,DB_D2,DB_D3,DB_D4,DB_D5,DB_D6,DB_D7,
|
||||
DB_D8,DB_D9,DB_DA,DB_DB,DB_DC,DB_DD,DB_DE,DB_DF,
|
||||
DB_E0,DB_E1,DB_E2,DB_E3,DB_E4,DB_E5,DB_E6,DB_E7,
|
||||
DB_E8,DB_E9,DB_EA,DB_EB,DB_EC,DB_ED,DB_EE,DB_EF,
|
||||
DB_F0,DB_F1,DB_F2,DB_F3,DB_F4,DB_F5,DB_F6,DB_F7,
|
||||
DB_F8,DB_F9,DB_FA,DB_FB,DB_FC,DB_FD,DB_FE,DB_FF
|
||||
};
|
||||
|
||||
static void CodesCB(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\n",
|
||||
(long)(R->User),OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IX
|
||||
J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\n",
|
||||
(long)(R->User),OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IY
|
||||
J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesED(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesED[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesED.h"
|
||||
case PFX_ED:
|
||||
R->PC.W--;break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IX
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesDDCB(R);break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IY
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesFDCB(R);break;
|
||||
default:
|
||||
printf
|
||||
(
|
||||
"Unrecognized instruction: FD %02X at PC=%04X\n",
|
||||
OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the register struct **/
|
||||
/** before starting execution with Z80(). It sets the **/
|
||||
/** registers to their supposed initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(Z80 *R)
|
||||
{
|
||||
R->PC.W = 0x0000;
|
||||
R->SP.W = 0xF000;
|
||||
R->AF.W = 0x0000;
|
||||
R->BC.W = 0x0000;
|
||||
R->DE.W = 0x0000;
|
||||
R->HL.W = 0x0000;
|
||||
R->AF1.W = 0x0000;
|
||||
R->BC1.W = 0x0000;
|
||||
R->DE1.W = 0x0000;
|
||||
R->HL1.W = 0x0000;
|
||||
R->IX.W = 0x0000;
|
||||
R->IY.W = 0x0000;
|
||||
R->I = 0x00;
|
||||
R->R = 0x00;
|
||||
R->IFF = 0x00;
|
||||
R->ICount = R->IPeriod;
|
||||
R->RunCycles =0;
|
||||
R->IRequest = INT_NONE;
|
||||
R->IBackup = 0;
|
||||
|
||||
JumpZ80(R->PC.W);
|
||||
}
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute given number of Z80 cycles. **/
|
||||
/** It will then return the number of cycles left, possibly **/
|
||||
/** negative, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifdef EXECZ80
|
||||
int GetRunCyclesZ80(register Z80 *R)
|
||||
{
|
||||
return(R->ICount - R->RunCycles);
|
||||
}
|
||||
int ExecZ80(register Z80 *R,register int RunCycles)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
R->RunCycles = R->ICount;
|
||||
|
||||
for(R->ICount=RunCycles;;)
|
||||
{
|
||||
while(R->ICount>0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!DebugZ80(R)) return(R->ICount);
|
||||
#endif
|
||||
|
||||
/* Read opcode and count cycles */
|
||||
I=OpZ80(R->PC.W++);
|
||||
/* Count cycles */
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
/* Interpret opcode */
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
|
||||
/* Unless we have come here after EI, exit */
|
||||
if(!(R->IFF&IFF_EI))
|
||||
{
|
||||
/* Interrupt CPU if needed */
|
||||
if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Done with AfterEI state */
|
||||
R->IFF=(R->IFF&~IFF_EI)|IFF_1;
|
||||
/* Restore the ICount */
|
||||
R->ICount+=R->IBackup-1;
|
||||
}
|
||||
}
|
||||
|
||||
return(R->ICount);
|
||||
}
|
||||
}
|
||||
#endif /* EXECZ80 */
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(Z80 *R,word Vector)
|
||||
{
|
||||
/* If HALTed, take CPU off HALT instruction */
|
||||
if(R->IFF&IFF_HALT) { R->PC.W++;R->IFF&=~IFF_HALT; }
|
||||
|
||||
if((R->IFF&IFF_1)||(Vector==INT_NMI))
|
||||
{
|
||||
/* Save PC on stack */
|
||||
M_PUSH(PC);
|
||||
|
||||
/* Automatically reset IRequest if needed */
|
||||
if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE;
|
||||
|
||||
/* If it is NMI... */
|
||||
if(Vector==INT_NMI)
|
||||
{
|
||||
/* Clear IFF1 */
|
||||
R->IFF&=~(IFF_1|IFF_EI);
|
||||
/* Jump to hardwired NMI vector */
|
||||
R->PC.W=0x0066;
|
||||
JumpZ80(0x0066);
|
||||
/* Done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Further interrupts off */
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
|
||||
/* If in IM2 mode... */
|
||||
if(R->IFF&IFF_IM2)
|
||||
{
|
||||
/* Make up the vector address */
|
||||
Vector=(Vector&0xFF)|((word)(R->I)<<8);
|
||||
/* Read the vector */
|
||||
R->PC.B.l=RdZ80(Vector++);
|
||||
R->PC.B.h=RdZ80(Vector);
|
||||
JumpZ80(R->PC.W);
|
||||
/* Done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* If in IM1 mode, just jump to hardwired IRQ vector */
|
||||
if(R->IFF&IFF_IM1) { R->PC.W=0x0038;JumpZ80(0x0038);return; }
|
||||
|
||||
/* If in IM0 mode... */
|
||||
|
||||
/* Jump to a vector */
|
||||
switch(Vector)
|
||||
{
|
||||
case INT_RST00: R->PC.W=0x0000;JumpZ80(0x0000);break;
|
||||
case INT_RST08: R->PC.W=0x0008;JumpZ80(0x0008);break;
|
||||
case INT_RST10: R->PC.W=0x0010;JumpZ80(0x0010);break;
|
||||
case INT_RST18: R->PC.W=0x0018;JumpZ80(0x0018);break;
|
||||
case INT_RST20: R->PC.W=0x0020;JumpZ80(0x0020);break;
|
||||
case INT_RST28: R->PC.W=0x0028;JumpZ80(0x0028);break;
|
||||
case INT_RST30: R->PC.W=0x0030;JumpZ80(0x0030);break;
|
||||
case INT_RST38: R->PC.W=0x0038;JumpZ80(0x0038);break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifndef EXECZ80
|
||||
word RunZ80(Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!DebugZ80(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
|
||||
/* If cycle counter expired... */
|
||||
if(R->ICount<=0)
|
||||
{
|
||||
/* If we have come after EI, get address from IRequest */
|
||||
/* Otherwise, get it from the loop handler */
|
||||
if(R->IFF&IFF_EI)
|
||||
{
|
||||
R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */
|
||||
R->ICount+=R->IBackup-1; /* Restore the ICount */
|
||||
|
||||
/* Call periodic handler or set pending IRQ */
|
||||
if(R->ICount>0) J.W=R->IRequest;
|
||||
else
|
||||
{
|
||||
J.W=LoopZ80(R); /* Call periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
J.W=LoopZ80(R); /* Call periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */
|
||||
}
|
||||
|
||||
if(J.W==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
|
||||
if(J.W!=INT_NONE) IntZ80(R,J.W); /* Int-pt if needed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Execution stopped */
|
||||
return(R->PC.W);
|
||||
}
|
||||
#endif /* !EXECZ80 */
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.h **/
|
||||
/** **/
|
||||
/** This file contains declarations relevant to emulation **/
|
||||
/** of Z80 CPU. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifndef Z80_H
|
||||
#define Z80_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Compilation options: */
|
||||
/* #define DEBUG */ /* Compile debugging version */
|
||||
#define LSB_FIRST /* Compile for low-endian CPU */
|
||||
/* #define MSB_FIRST */ /* Compile for hi-endian CPU */
|
||||
#define EXECZ80
|
||||
|
||||
/* LoopZ80() may return: */
|
||||
#define INT_RST00 0x00C7 /* RST 00h */
|
||||
#define INT_RST08 0x00CF /* RST 08h */
|
||||
#define INT_RST10 0x00D7 /* RST 10h */
|
||||
#define INT_RST18 0x00DF /* RST 18h */
|
||||
#define INT_RST20 0x00E7 /* RST 20h */
|
||||
#define INT_RST28 0x00EF /* RST 28h */
|
||||
#define INT_RST30 0x00F7 /* RST 30h */
|
||||
#define INT_RST38 0x00FF /* RST 38h */
|
||||
#define INT_IRQ INT_RST38 /* Default IRQ opcode is FFh */
|
||||
#define INT_NMI 0xFFFD /* Non-maskable interrupt */
|
||||
#define INT_NONE 0xFFFF /* No interrupt required */
|
||||
#define INT_QUIT 0xFFFE /* Exit the emulation */
|
||||
|
||||
/* Bits in Z80 F register: */
|
||||
#define S_FLAG 0x80 /* 1: Result negative */
|
||||
#define Z_FLAG 0x40 /* 1: Result is zero */
|
||||
#define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */
|
||||
#define P_FLAG 0x04 /* 1: Result is even */
|
||||
#define V_FLAG 0x04 /* 1: Overflow occured */
|
||||
#define N_FLAG 0x02 /* 1: Subtraction occured */
|
||||
#define C_FLAG 0x01 /* 1: Carry/Borrow occured */
|
||||
|
||||
/* Bits in IFF flip-flops: */
|
||||
#define IFF_1 0x01 /* IFF1 flip-flop */
|
||||
#define IFF_IM1 0x02 /* 1: IM1 mode */
|
||||
#define IFF_IM2 0x04 /* 1: IM2 mode */
|
||||
#define IFF_2 0x08 /* IFF2 flip-flop */
|
||||
#define IFF_EI 0x20 /* 1: EI pending */
|
||||
#define IFF_HALT 0x80 /* 1: CPU HALTed */
|
||||
|
||||
/** Simple Datatypes *****************************************/
|
||||
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
|
||||
/*************************************************************/
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
#ifndef WORD_TYPE_DEFINED
|
||||
#define WORD_TYPE_DEFINED
|
||||
typedef unsigned short word;
|
||||
#endif
|
||||
typedef signed char offset;
|
||||
|
||||
/** Structured Datatypes *************************************/
|
||||
/** NOTICE: #define LSB_FIRST for machines where least **/
|
||||
/** signifcant byte goes first. **/
|
||||
/*************************************************************/
|
||||
typedef union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { byte l,h; } B;
|
||||
#else
|
||||
struct { byte h,l; } B;
|
||||
#endif
|
||||
word W;
|
||||
} pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pair AF,BC,DE,HL,IX,IY,PC,SP; /* Main registers */
|
||||
pair AF1,BC1,DE1,HL1; /* Shadow registers */
|
||||
byte IFF,I; /* Interrupt registers */
|
||||
byte R; /* Refresh register */
|
||||
|
||||
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
|
||||
int RunCycles; /* Number of cycle to run */
|
||||
/* between calls to LoopZ80() */
|
||||
int IBackup; /* Private, don't touch */
|
||||
word IRequest; /* Set to address of pending IRQ */
|
||||
byte IAutoReset; /* Set to 1 to autom. reset IRequest */
|
||||
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */
|
||||
word Trap; /* Set Trap to address to trace from */
|
||||
byte Trace; /* Set Trace=1 to start tracing */
|
||||
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
|
||||
} Z80;
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with RunZ80(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(register Z80 *R);
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute given number of Z80 cycles. **/
|
||||
/** It will then return the number of cycles left, possibly **/
|
||||
/** negative, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifdef EXECZ80
|
||||
int ExecZ80(register Z80 *R,register int RunCycles);
|
||||
int GetRunCyclesZ80(register Z80 *R);
|
||||
#endif
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(register Z80 *R,register word Vector);
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifndef EXECZ80
|
||||
word RunZ80(register Z80 *R);
|
||||
#endif
|
||||
|
||||
/** RdZ80()/WrZ80() ******************************************/
|
||||
/** These functions are called when access to RAM occurs. **/
|
||||
/** They allow to control memory access. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void WrZ80(register word Addr,register byte Value);
|
||||
void WrZ80byM68k(register word Addr,register byte Value);
|
||||
byte RdZ80(register word Addr);
|
||||
|
||||
/** InZ80()/OutZ80() *****************************************/
|
||||
/** Z80 emulation calls these functions to read/write from **/
|
||||
/** I/O ports. There can be 65536 I/O ports, but only first **/
|
||||
/** 256 are usually used. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void OutZ80(register word Port,register byte Value);
|
||||
byte InZ80(register word Port);
|
||||
|
||||
/** PatchZ80() ***********************************************/
|
||||
/** Z80 emulation calls this function when it encounters a **/
|
||||
/** special patch command (ED FE) provided for user needs. **/
|
||||
/** For example, it can be called to emulate BIOS calls, **/
|
||||
/** such as disk and tape access. Replace it with an empty **/
|
||||
/** macro for no patching. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void PatchZ80(register Z80 *R);
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. Emulation exits **/
|
||||
/** if DebugZ80() returns 0. **/
|
||||
/*************************************************************/
|
||||
#ifdef DEBUG
|
||||
byte DebugZ80(register Z80 *R);
|
||||
#endif
|
||||
|
||||
/** LoopZ80() ************************************************/
|
||||
/** Z80 emulation calls this function periodically to check **/
|
||||
/** if the system hardware requires any interrupts. This **/
|
||||
/** function must return an address of the interrupt vector **/
|
||||
/** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/
|
||||
/** Return INT_QUIT to exit the emulation loop. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
word LoopZ80(register Z80 *R);
|
||||
|
||||
/** JumpZ80() ************************************************/
|
||||
/** Z80 emulation calls this function when it executes a **/
|
||||
/** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/
|
||||
/** trap these opcodes and switch memory layout. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
#ifndef JUMPZ80
|
||||
#define JumpZ80(PC)
|
||||
#else
|
||||
void JumpZ80(word PC);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* Z80_H */
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "gwenesis_io.h"
|
||||
#include "../savestate/gwenesis_savestate.h"
|
||||
|
||||
unsigned short button_state[3]= {0xff,0xff,0xff};
|
||||
|
||||
/* Button mapping
|
||||
7 6 5 4 3 2 1 0
|
||||
Start A B C R L D U
|
||||
*/
|
||||
static unsigned char gwenesis_io_pad_state[3] = {0x33,0x33,0x33};
|
||||
|
||||
//#define GWENESIS_IO_VERSION 0x81 /* oversea NTSC model version 81 */
|
||||
#define GWENESIS_IO_VERSION 0xC1 /* oversea PAL model version C1 */
|
||||
/*
|
||||
$A10003 : MODE VMOD DISK RSV VER3 VER2 VER1 VER0
|
||||
MODE (R) 0: Domestic Model
|
||||
1: Overseas Model
|
||||
VMOD (R) 0: NTSC CPU clock 7.67 MHz
|
||||
1: PAL CPU clock 7.60 MHz
|
||||
RSV (R) Currently not used
|
||||
VER3-0 (R) MEGA DRIVE version is indicated by $0-$F. The present hardware version is indicated by $0.
|
||||
$A10003 : DATA 1 ( CTRL1 )
|
||||
$A10005 : DATA 2 ( CTRL2 )
|
||||
$A10007 : DATA 3 ( EXP )
|
||||
$A10009 : CTRL 1
|
||||
$A1000B : CTRL 2
|
||||
$A1000D : CTRL 3
|
||||
$A1000F : TxDATA 1
|
||||
$A10011 : RxDATA 1
|
||||
$A10013 : S-CTRL 1
|
||||
$A10015 : TxDATA 2
|
||||
$A10017 : RxDATA 2
|
||||
$A10019 : S-CTRL 2
|
||||
$A1001B : TxDATA 3
|
||||
$A1001D : RxDATA 3
|
||||
$A1001F : S-CTRL 3
|
||||
|
||||
DATA shows the status of each port. The I/O direction of each bit is set by CTRL and S-CTRL.
|
||||
DATA = PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
|
||||
|
||||
PD7 (RW)
|
||||
PD6 (RW) TH
|
||||
PD5 (RW) TR
|
||||
PD4 (RW) TL
|
||||
PD3 (RW) RIGHT
|
||||
PD2 (RW) LEFT
|
||||
PD1 (RW) DOWN
|
||||
PD0 (RW) UP
|
||||
|
||||
TH = 0
|
||||
PD7 0
|
||||
PD6 TH=0
|
||||
PD5 Start
|
||||
PD4 A
|
||||
PD3 0
|
||||
PD2 0
|
||||
PD1 DOWN
|
||||
PD0 UP
|
||||
|
||||
TH = 1
|
||||
PD7 0
|
||||
PD6 TH=1
|
||||
PD5 B
|
||||
PD4 C
|
||||
PD3 RIGHT
|
||||
PD2 LEFT
|
||||
PD1 DOWN
|
||||
PD0 UP
|
||||
|
||||
|
||||
CTRL designates the I/O direction of each port and the INTERRUPT CONTROL of TH.
|
||||
CTRL = INT PC6 PC5 PC4 PC3 PC2 PC1 PC0
|
||||
|
||||
INT (RW) 0: TH-INT PROHIBITED
|
||||
1: TH-INT ALLOWED
|
||||
PC6 (RW) 0: PD6 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC5 (RW) 0: PD5 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC4 (RW) 0: PD4 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC3 (RW) 0: PD3 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC2 (RW) 0: PD2 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC1 (RW) 0: PD1 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
PC0 (RW) 0: PD0 INPUT MODE
|
||||
1: OUTPUT MODE
|
||||
|
||||
S-CTRL is for the status, etc. of each port's mode change, baud rate and SERIAL.
|
||||
|
||||
S-CTRL = BPS1 BPS0 SIN SOUT RINT RERR RRDY TFUL
|
||||
|
||||
SIN (RW) 0: TR-PARALLEL MODE
|
||||
1: SERIAL IN
|
||||
SOUT (RW) 0: TL-PARALLEL MODE
|
||||
1: SERIAL OUT
|
||||
RINT (RW) 0: Rxd READY INTERRUPT PROHIBITED
|
||||
1: Rxd READY INTERRUPT ALLOWED
|
||||
RERR (R) 0:
|
||||
1: Rxd ERROR
|
||||
RRDY (R) 0:
|
||||
1: Rxd READY
|
||||
TFUL (R) 0:
|
||||
1: Txd FULL
|
||||
*/
|
||||
|
||||
unsigned char io_reg[16] = {GWENESIS_IO_VERSION, /* 0x1 Version */
|
||||
0x7f, 0x7f, 0x7f, /* 0x3-5-7 JOYPAD DATA 1 2 & EXT */
|
||||
0x00, 0x00, 0x00, /* 0x9-A-C JOYPAD CTRL 1 2 & EXT */
|
||||
0xff, 0, 0, /* PORT 1 */
|
||||
0xff, 0, 0, /* PORT 2 */
|
||||
0xff, 0, 0}; /* PORT 3 */
|
||||
|
||||
void gwenesis_io_pad_release_button(int pad, int button)
|
||||
{
|
||||
button_state[pad] |= (1 << button);
|
||||
}
|
||||
|
||||
void gwenesis_io_pad_press_button(int pad, int button)
|
||||
{
|
||||
button_state[pad] &= ~(1 << button);
|
||||
}
|
||||
|
||||
static inline void gwenesis_io_pad_write(int pad, int value)
|
||||
{
|
||||
unsigned char mask = io_reg[pad + 4];
|
||||
|
||||
gwenesis_io_pad_state[pad] &= ~mask;
|
||||
gwenesis_io_pad_state[pad] |= value & mask;
|
||||
|
||||
}
|
||||
|
||||
static inline unsigned char gwenesis_io_pad_read(int pad)
|
||||
{
|
||||
unsigned char value;
|
||||
|
||||
/* get host button */
|
||||
gwenesis_io_get_buttons();
|
||||
|
||||
value = gwenesis_io_pad_state[pad] & 0x40;
|
||||
value |= 0x3f;
|
||||
|
||||
if (value & 0x40)
|
||||
{
|
||||
value &= (button_state[pad] & 0x3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
value &= ((button_state[pad] & 3) | ((button_state[pad] >> 2) & 0x30));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void gwenesis_io_write_ctrl(unsigned int address, unsigned int value)
|
||||
{
|
||||
|
||||
address >>= 1;
|
||||
|
||||
// JOYPAD DATA
|
||||
if (address >= 0x1 && address <= 0x3)
|
||||
{
|
||||
|
||||
io_reg[address] = value;
|
||||
gwenesis_io_pad_write(address - 1, value);
|
||||
return;
|
||||
}
|
||||
// JOYPAD CTRL
|
||||
else if (address >= 0x4 && address <= 0x6)
|
||||
{
|
||||
if (io_reg[address] != value)
|
||||
{
|
||||
io_reg[address] = value;
|
||||
gwenesis_io_pad_write(address - 4, io_reg[address - 3]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int gwenesis_io_read_ctrl(unsigned int address)
|
||||
{
|
||||
address >>= 1;
|
||||
if (address >= 0x1 && address < 0x4)
|
||||
{
|
||||
unsigned char mask = 0x80 | io_reg[address + 3];
|
||||
unsigned char value;
|
||||
value = io_reg[address] & mask;
|
||||
value |= gwenesis_io_pad_read(address - 1) & ~mask;
|
||||
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return io_reg[address];
|
||||
}
|
||||
}
|
||||
|
||||
void gwenesis_io_set_reg(unsigned int reg, unsigned int value) {
|
||||
io_reg[reg] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
void gwenesis_io_save_state() {
|
||||
SaveState* state;
|
||||
state = saveGwenesisStateOpenForWrite("io");
|
||||
saveGwenesisStateSetBuffer(state, "button_state", button_state, sizeof(button_state));
|
||||
saveGwenesisStateSetBuffer(state, "gwenesis_io_pad_state", gwenesis_io_pad_state, sizeof(gwenesis_io_pad_state));
|
||||
saveGwenesisStateSetBuffer(state, "io_reg", io_reg, sizeof(io_reg));
|
||||
}
|
||||
|
||||
void gwenesis_io_load_state() {
|
||||
SaveState* state = saveGwenesisStateOpenForRead("io");
|
||||
saveGwenesisStateGetBuffer(state, "button_state", button_state, sizeof(button_state));
|
||||
saveGwenesisStateGetBuffer(state, "gwenesis_io_pad_state", gwenesis_io_pad_state, sizeof(gwenesis_io_pad_state));
|
||||
saveGwenesisStateGetBuffer(state, "io_reg", io_reg, sizeof(io_reg));
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#ifndef _gwenesis_io_H_
|
||||
#define _gwenesis_io_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
void gwenesis_io_pad_press_button(int pad, int button);
|
||||
void gwenesis_io_pad_release_button(int pad, int button);
|
||||
|
||||
void gwenesis_io_write_ctrl(unsigned int address, unsigned int value);
|
||||
unsigned int gwenesis_io_read_ctrl(unsigned int address);
|
||||
|
||||
void gwenesis_io_set_reg(unsigned int reg, unsigned int value);
|
||||
void gwenesis_io_get_buttons();
|
||||
|
||||
void gwenesis_io_save_state();
|
||||
void gwenesis_io_load_state();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../cpus/M68K/m68k.h"
|
||||
#include "../io/gwenesis_io.h"
|
||||
#include "../bus/gwenesis_bus.h"
|
||||
#include "../vdp/gwenesis_vdp.h"
|
||||
#include "../sound/z80inst.h"
|
||||
|
||||
#include "../savestate/gwenesis_savestate.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
void gwenesis_save_state() {
|
||||
/* DO NOT CHANGE ORDER - NEEDS TO BE SAME AS IN LOAD */
|
||||
gwenesis_m68k_save_state();
|
||||
gwenesis_io_save_state();
|
||||
gwenesis_bus_save_state();
|
||||
gwenesis_vdp_gfx_save_state();
|
||||
gwenesis_vdp_mem_save_state();
|
||||
|
||||
}
|
||||
|
||||
void gwenesis_load_state() {
|
||||
/* DO NOT CHANGE ORDER - NEEDS TO BE SAME AS IN SAVE */
|
||||
gwenesis_m68k_load_state();
|
||||
gwenesis_io_load_state();
|
||||
gwenesis_bus_load_state();
|
||||
gwenesis_vdp_gfx_load_state();
|
||||
gwenesis_vdp_mem_load_state();
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#ifndef _gwenesis_savestate_H_
|
||||
#define _gwenesis_savestate_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct SaveState SaveState;
|
||||
|
||||
bool initLoadGwenesisState(unsigned char *srcBuffer);
|
||||
int saveGwenesisState(unsigned char *destBuffer, int save_size);
|
||||
int loadGwenesisState(unsigned char *srcBuffer);
|
||||
|
||||
SaveState* saveGwenesisStateOpenForRead(const char* fileName);
|
||||
SaveState* saveGwenesisStateOpenForWrite(const char* fileName);
|
||||
|
||||
int saveGwenesisStateGet(SaveState* state, const char* tagName);
|
||||
void saveGwenesisStateSet(SaveState* state, const char* tagName, int value);
|
||||
|
||||
void saveGwenesisStateGetBuffer(SaveState* state, const char* tagName, void* buffer, int length);
|
||||
void saveGwenesisStateSetBuffer(SaveState* state, const char* tagName, void* buffer, int length);
|
||||
|
||||
void gwenesis_save_state();
|
||||
void gwenesis_load_state();
|
||||
#endif
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
const unsigned int __in_flash() __aligned(4) fn_table[] = {
|
||||
// freqbase: 6.000000
|
||||
0, 12288, 24576, 36864, 49152, 61440, 73728, 86016, 98304, 110592, 122880, 135168, 147456, 159744, 172032, 184320 // 0x00000000
|
||||
, 196608, 208896, 221184, 233472, 245760, 258048, 270336, 282624, 294912, 307200, 319488, 331776, 344064, 356352, 368640, 380928 // 0x00000040
|
||||
, 393216, 405504, 417792, 430080, 442368, 454656, 466944, 479232, 491520, 503808, 516096, 528384, 540672, 552960, 565248, 577536 // 0x00000080
|
||||
, 589824, 602112, 614400, 626688, 638976, 651264, 663552, 675840, 688128, 700416, 712704, 724992, 737280, 749568, 761856, 774144 // 0x000000C0
|
||||
, 786432, 798720, 811008, 823296, 835584, 847872, 860160, 872448, 884736, 897024, 909312, 921600, 933888, 946176, 958464, 970752 // 0x00000100
|
||||
, 983040, 995328, 1007616, 1019904, 1032192, 1044480, 1056768, 1069056, 1081344, 1093632, 1105920, 1118208, 1130496, 1142784, 1155072, 1167360 // 0x00000140
|
||||
, 1179648, 1191936, 1204224, 1216512, 1228800, 1241088, 1253376, 1265664, 1277952, 1290240, 1302528, 1314816, 1327104, 1339392, 1351680, 1363968 // 0x00000180
|
||||
, 1376256, 1388544, 1400832, 1413120, 1425408, 1437696, 1449984, 1462272, 1474560, 1486848, 1499136, 1511424, 1523712, 1536000, 1548288, 1560576 // 0x000001C0
|
||||
, 1572864, 1585152, 1597440, 1609728, 1622016, 1634304, 1646592, 1658880, 1671168, 1683456, 1695744, 1708032, 1720320, 1732608, 1744896, 1757184 // 0x00000200
|
||||
, 1769472, 1781760, 1794048, 1806336, 1818624, 1830912, 1843200, 1855488, 1867776, 1880064, 1892352, 1904640, 1916928, 1929216, 1941504, 1953792 // 0x00000240
|
||||
, 1966080, 1978368, 1990656, 2002944, 2015232, 2027520, 2039808, 2052096, 2064384, 2076672, 2088960, 2101248, 2113536, 2125824, 2138112, 2150400 // 0x00000280
|
||||
, 2162688, 2174976, 2187264, 2199552, 2211840, 2224128, 2236416, 2248704, 2260992, 2273280, 2285568, 2297856, 2310144, 2322432, 2334720, 2347008 // 0x000002C0
|
||||
, 2359296, 2371584, 2383872, 2396160, 2408448, 2420736, 2433024, 2445312, 2457600, 2469888, 2482176, 2494464, 2506752, 2519040, 2531328, 2543616 // 0x00000300
|
||||
, 2555904, 2568192, 2580480, 2592768, 2605056, 2617344, 2629632, 2641920, 2654208, 2666496, 2678784, 2691072, 2703360, 2715648, 2727936, 2740224 // 0x00000340
|
||||
, 2752512, 2764800, 2777088, 2789376, 2801664, 2813952, 2826240, 2838528, 2850816, 2863104, 2875392, 2887680, 2899968, 2912256, 2924544, 2936832 // 0x00000380
|
||||
, 2949120, 2961408, 2973696, 2985984, 2998272, 3010560, 3022848, 3035136, 3047424, 3059712, 3072000, 3084288, 3096576, 3108864, 3121152, 3133440 // 0x000003C0
|
||||
, 3145728, 3158016, 3170304, 3182592, 3194880, 3207168, 3219456, 3231744, 3244032, 3256320, 3268608, 3280896, 3293184, 3305472, 3317760, 3330048 // 0x00000400
|
||||
, 3342336, 3354624, 3366912, 3379200, 3391488, 3403776, 3416064, 3428352, 3440640, 3452928, 3465216, 3477504, 3489792, 3502080, 3514368, 3526656 // 0x00000440
|
||||
, 3538944, 3551232, 3563520, 3575808, 3588096, 3600384, 3612672, 3624960, 3637248, 3649536, 3661824, 3674112, 3686400, 3698688, 3710976, 3723264 // 0x00000480
|
||||
, 3735552, 3747840, 3760128, 3772416, 3784704, 3796992, 3809280, 3821568, 3833856, 3846144, 3858432, 3870720, 3883008, 3895296, 3907584, 3919872 // 0x000004C0
|
||||
, 3932160, 3944448, 3956736, 3969024, 3981312, 3993600, 4005888, 4018176, 4030464, 4042752, 4055040, 4067328, 4079616, 4091904, 4104192, 4116480 // 0x00000500
|
||||
, 4128768, 4141056, 4153344, 4165632, 4177920, 4190208, 4202496, 4214784, 4227072, 4239360, 4251648, 4263936, 4276224, 4288512, 4300800, 4313088 // 0x00000540
|
||||
, 4325376, 4337664, 4349952, 4362240, 4374528, 4386816, 4399104, 4411392, 4423680, 4435968, 4448256, 4460544, 4472832, 4485120, 4497408, 4509696 // 0x00000580
|
||||
, 4521984, 4534272, 4546560, 4558848, 4571136, 4583424, 4595712, 4608000, 4620288, 4632576, 4644864, 4657152, 4669440, 4681728, 4694016, 4706304 // 0x000005C0
|
||||
, 4718592, 4730880, 4743168, 4755456, 4767744, 4780032, 4792320, 4804608, 4816896, 4829184, 4841472, 4853760, 4866048, 4878336, 4890624, 4902912 // 0x00000600
|
||||
, 4915200, 4927488, 4939776, 4952064, 4964352, 4976640, 4988928, 5001216, 5013504, 5025792, 5038080, 5050368, 5062656, 5074944, 5087232, 5099520 // 0x00000640
|
||||
, 5111808, 5124096, 5136384, 5148672, 5160960, 5173248, 5185536, 5197824, 5210112, 5222400, 5234688, 5246976, 5259264, 5271552, 5283840, 5296128 // 0x00000680
|
||||
, 5308416, 5320704, 5332992, 5345280, 5357568, 5369856, 5382144, 5394432, 5406720, 5419008, 5431296, 5443584, 5455872, 5468160, 5480448, 5492736 // 0x000006C0
|
||||
, 5505024, 5517312, 5529600, 5541888, 5554176, 5566464, 5578752, 5591040, 5603328, 5615616, 5627904, 5640192, 5652480, 5664768, 5677056, 5689344 // 0x00000700
|
||||
, 5701632, 5713920, 5726208, 5738496, 5750784, 5763072, 5775360, 5787648, 5799936, 5812224, 5824512, 5836800, 5849088, 5861376, 5873664, 5885952 // 0x00000740
|
||||
, 5898240, 5910528, 5922816, 5935104, 5947392, 5959680, 5971968, 5984256, 5996544, 6008832, 6021120, 6033408, 6045696, 6057984, 6070272, 6082560 // 0x00000780
|
||||
, 6094848, 6107136, 6119424, 6131712, 6144000, 6156288, 6168576, 6180864, 6193152, 6205440, 6217728, 6230016, 6242304, 6254592, 6266880, 6279168 // 0x000007C0
|
||||
, 6291456, 6303744, 6316032, 6328320, 6340608, 6352896, 6365184, 6377472, 6389760, 6402048, 6414336, 6426624, 6438912, 6451200, 6463488, 6475776 // 0x00000800
|
||||
, 6488064, 6500352, 6512640, 6524928, 6537216, 6549504, 6561792, 6574080, 6586368, 6598656, 6610944, 6623232, 6635520, 6647808, 6660096, 6672384 // 0x00000840
|
||||
, 6684672, 6696960, 6709248, 6721536, 6733824, 6746112, 6758400, 6770688, 6782976, 6795264, 6807552, 6819840, 6832128, 6844416, 6856704, 6868992 // 0x00000880
|
||||
, 6881280, 6893568, 6905856, 6918144, 6930432, 6942720, 6955008, 6967296, 6979584, 6991872, 7004160, 7016448, 7028736, 7041024, 7053312, 7065600 // 0x000008C0
|
||||
, 7077888, 7090176, 7102464, 7114752, 7127040, 7139328, 7151616, 7163904, 7176192, 7188480, 7200768, 7213056, 7225344, 7237632, 7249920, 7262208 // 0x00000900
|
||||
, 7274496, 7286784, 7299072, 7311360, 7323648, 7335936, 7348224, 7360512, 7372800, 7385088, 7397376, 7409664, 7421952, 7434240, 7446528, 7458816 // 0x00000940
|
||||
, 7471104, 7483392, 7495680, 7507968, 7520256, 7532544, 7544832, 7557120, 7569408, 7581696, 7593984, 7606272, 7618560, 7630848, 7643136, 7655424 // 0x00000980
|
||||
, 7667712, 7680000, 7692288, 7704576, 7716864, 7729152, 7741440, 7753728, 7766016, 7778304, 7790592, 7802880, 7815168, 7827456, 7839744, 7852032 // 0x000009C0
|
||||
, 7864320, 7876608, 7888896, 7901184, 7913472, 7925760, 7938048, 7950336, 7962624, 7974912, 7987200, 7999488, 8011776, 8024064, 8036352, 8048640 // 0x00000A00
|
||||
, 8060928, 8073216, 8085504, 8097792, 8110080, 8122368, 8134656, 8146944, 8159232, 8171520, 8183808, 8196096, 8208384, 8220672, 8232960, 8245248 // 0x00000A40
|
||||
, 8257536, 8269824, 8282112, 8294400, 8306688, 8318976, 8331264, 8343552, 8355840, 8368128, 8380416, 8392704, 8404992, 8417280, 8429568, 8441856 // 0x00000A80
|
||||
, 8454144, 8466432, 8478720, 8491008, 8503296, 8515584, 8527872, 8540160, 8552448, 8564736, 8577024, 8589312, 8601600, 8613888, 8626176, 8638464 // 0x00000AC0
|
||||
, 8650752, 8663040, 8675328, 8687616, 8699904, 8712192, 8724480, 8736768, 8749056, 8761344, 8773632, 8785920, 8798208, 8810496, 8822784, 8835072 // 0x00000B00
|
||||
, 8847360, 8859648, 8871936, 8884224, 8896512, 8908800, 8921088, 8933376, 8945664, 8957952, 8970240, 8982528, 8994816, 9007104, 9019392, 9031680 // 0x00000B40
|
||||
, 9043968, 9056256, 9068544, 9080832, 9093120, 9105408, 9117696, 9129984, 9142272, 9154560, 9166848, 9179136, 9191424, 9203712, 9216000, 9228288 // 0x00000B80
|
||||
, 9240576, 9252864, 9265152, 9277440, 9289728, 9302016, 9314304, 9326592, 9338880, 9351168, 9363456, 9375744, 9388032, 9400320, 9412608, 9424896 // 0x00000BC0
|
||||
, 9437184, 9449472, 9461760, 9474048, 9486336, 9498624, 9510912, 9523200, 9535488, 9547776, 9560064, 9572352, 9584640, 9596928, 9609216, 9621504 // 0x00000C00
|
||||
, 9633792, 9646080, 9658368, 9670656, 9682944, 9695232, 9707520, 9719808, 9732096, 9744384, 9756672, 9768960, 9781248, 9793536, 9805824, 9818112 // 0x00000C40
|
||||
, 9830400, 9842688, 9854976, 9867264, 9879552, 9891840, 9904128, 9916416, 9928704, 9940992, 9953280, 9965568, 9977856, 9990144, 10002432, 10014720 // 0x00000C80
|
||||
, 10027008, 10039296, 10051584, 10063872, 10076160, 10088448, 10100736, 10113024, 10125312, 10137600, 10149888, 10162176, 10174464, 10186752, 10199040, 10211328 // 0x00000CC0
|
||||
, 10223616, 10235904, 10248192, 10260480, 10272768, 10285056, 10297344, 10309632, 10321920, 10334208, 10346496, 10358784, 10371072, 10383360, 10395648, 10407936 // 0x00000D00
|
||||
, 10420224, 10432512, 10444800, 10457088, 10469376, 10481664, 10493952, 10506240, 10518528, 10530816, 10543104, 10555392, 10567680, 10579968, 10592256, 10604544 // 0x00000D40
|
||||
, 10616832, 10629120, 10641408, 10653696, 10665984, 10678272, 10690560, 10702848, 10715136, 10727424, 10739712, 10752000, 10764288, 10776576, 10788864, 10801152 // 0x00000D80
|
||||
, 10813440, 10825728, 10838016, 10850304, 10862592, 10874880, 10887168, 10899456, 10911744, 10924032, 10936320, 10948608, 10960896, 10973184, 10985472, 10997760 // 0x00000DC0
|
||||
, 11010048, 11022336, 11034624, 11046912, 11059200, 11071488, 11083776, 11096064, 11108352, 11120640, 11132928, 11145216, 11157504, 11169792, 11182080, 11194368 // 0x00000E00
|
||||
, 11206656, 11218944, 11231232, 11243520, 11255808, 11268096, 11280384, 11292672, 11304960, 11317248, 11329536, 11341824, 11354112, 11366400, 11378688, 11390976 // 0x00000E40
|
||||
, 11403264, 11415552, 11427840, 11440128, 11452416, 11464704, 11476992, 11489280, 11501568, 11513856, 11526144, 11538432, 11550720, 11563008, 11575296, 11587584 // 0x00000E80
|
||||
, 11599872, 11612160, 11624448, 11636736, 11649024, 11661312, 11673600, 11685888, 11698176, 11710464, 11722752, 11735040, 11747328, 11759616, 11771904, 11784192 // 0x00000EC0
|
||||
, 11796480, 11808768, 11821056, 11833344, 11845632, 11857920, 11870208, 11882496, 11894784, 11907072, 11919360, 11931648, 11943936, 11956224, 11968512, 11980800 // 0x00000F00
|
||||
, 11993088, 12005376, 12017664, 12029952, 12042240, 12054528, 12066816, 12079104, 12091392, 12103680, 12115968, 12128256, 12140544, 12152832, 12165120, 12177408 // 0x00000F40
|
||||
, 12189696, 12201984, 12214272, 12226560, 12238848, 12251136, 12263424, 12275712, 12288000, 12300288, 12312576, 12324864, 12337152, 12349440, 12361728, 12374016 // 0x00000F80
|
||||
, 12386304, 12398592, 12410880, 12423168, 12435456, 12447744, 12460032, 12472320, 12484608, 12496896, 12509184, 12521472, 12533760, 12546048, 12558336, 12570624 // 0x00000FC0
|
||||
, 12582912, 12595200, 12607488, 12619776, 12632064, 12644352, 12656640, 12668928, 12681216, 12693504, 12705792, 12718080, 12730368, 12742656, 12754944, 12767232 // 0x00001000
|
||||
, 12779520, 12791808, 12804096, 12816384, 12828672, 12840960, 12853248, 12865536, 12877824, 12890112, 12902400, 12914688, 12926976, 12939264, 12951552, 12963840 // 0x00001040
|
||||
, 12976128, 12988416, 13000704, 13012992, 13025280, 13037568, 13049856, 13062144, 13074432, 13086720, 13099008, 13111296, 13123584, 13135872, 13148160, 13160448 // 0x00001080
|
||||
, 13172736, 13185024, 13197312, 13209600, 13221888, 13234176, 13246464, 13258752, 13271040, 13283328, 13295616, 13307904, 13320192, 13332480, 13344768, 13357056 // 0x000010C0
|
||||
, 13369344, 13381632, 13393920, 13406208, 13418496, 13430784, 13443072, 13455360, 13467648, 13479936, 13492224, 13504512, 13516800, 13529088, 13541376, 13553664 // 0x00001100
|
||||
, 13565952, 13578240, 13590528, 13602816, 13615104, 13627392, 13639680, 13651968, 13664256, 13676544, 13688832, 13701120, 13713408, 13725696, 13737984, 13750272 // 0x00001140
|
||||
, 13762560, 13774848, 13787136, 13799424, 13811712, 13824000, 13836288, 13848576, 13860864, 13873152, 13885440, 13897728, 13910016, 13922304, 13934592, 13946880 // 0x00001180
|
||||
, 13959168, 13971456, 13983744, 13996032, 14008320, 14020608, 14032896, 14045184, 14057472, 14069760, 14082048, 14094336, 14106624, 14118912, 14131200, 14143488 // 0x000011C0
|
||||
, 14155776, 14168064, 14180352, 14192640, 14204928, 14217216, 14229504, 14241792, 14254080, 14266368, 14278656, 14290944, 14303232, 14315520, 14327808, 14340096 // 0x00001200
|
||||
, 14352384, 14364672, 14376960, 14389248, 14401536, 14413824, 14426112, 14438400, 14450688, 14462976, 14475264, 14487552, 14499840, 14512128, 14524416, 14536704 // 0x00001240
|
||||
, 14548992, 14561280, 14573568, 14585856, 14598144, 14610432, 14622720, 14635008, 14647296, 14659584, 14671872, 14684160, 14696448, 14708736, 14721024, 14733312 // 0x00001280
|
||||
, 14745600, 14757888, 14770176, 14782464, 14794752, 14807040, 14819328, 14831616, 14843904, 14856192, 14868480, 14880768, 14893056, 14905344, 14917632, 14929920 // 0x000012C0
|
||||
, 14942208, 14954496, 14966784, 14979072, 14991360, 15003648, 15015936, 15028224, 15040512, 15052800, 15065088, 15077376, 15089664, 15101952, 15114240, 15126528 // 0x00001300
|
||||
, 15138816, 15151104, 15163392, 15175680, 15187968, 15200256, 15212544, 15224832, 15237120, 15249408, 15261696, 15273984, 15286272, 15298560, 15310848, 15323136 // 0x00001340
|
||||
, 15335424, 15347712, 15360000, 15372288, 15384576, 15396864, 15409152, 15421440, 15433728, 15446016, 15458304, 15470592, 15482880, 15495168, 15507456, 15519744 // 0x00001380
|
||||
, 15532032, 15544320, 15556608, 15568896, 15581184, 15593472, 15605760, 15618048, 15630336, 15642624, 15654912, 15667200, 15679488, 15691776, 15704064, 15716352 // 0x000013C0
|
||||
, 15728640, 15740928, 15753216, 15765504, 15777792, 15790080, 15802368, 15814656, 15826944, 15839232, 15851520, 15863808, 15876096, 15888384, 15900672, 15912960 // 0x00001400
|
||||
, 15925248, 15937536, 15949824, 15962112, 15974400, 15986688, 15998976, 16011264, 16023552, 16035840, 16048128, 16060416, 16072704, 16084992, 16097280, 16109568 // 0x00001440
|
||||
, 16121856, 16134144, 16146432, 16158720, 16171008, 16183296, 16195584, 16207872, 16220160, 16232448, 16244736, 16257024, 16269312, 16281600, 16293888, 16306176 // 0x00001480
|
||||
, 16318464, 16330752, 16343040, 16355328, 16367616, 16379904, 16392192, 16404480, 16416768, 16429056, 16441344, 16453632, 16465920, 16478208, 16490496, 16502784 // 0x000014C0
|
||||
, 16515072, 16527360, 16539648, 16551936, 16564224, 16576512, 16588800, 16601088, 16613376, 16625664, 16637952, 16650240, 16662528, 16674816, 16687104, 16699392 // 0x00001500
|
||||
, 16711680, 16723968, 16736256, 16748544, 16760832, 16773120, 16785408, 16797696, 16809984, 16822272, 16834560, 16846848, 16859136, 16871424, 16883712, 16896000 // 0x00001540
|
||||
, 16908288, 16920576, 16932864, 16945152, 16957440, 16969728, 16982016, 16994304, 17006592, 17018880, 17031168, 17043456, 17055744, 17068032, 17080320, 17092608 // 0x00001580
|
||||
, 17104896, 17117184, 17129472, 17141760, 17154048, 17166336, 17178624, 17190912, 17203200, 17215488, 17227776, 17240064, 17252352, 17264640, 17276928, 17289216 // 0x000015C0
|
||||
, 17301504, 17313792, 17326080, 17338368, 17350656, 17362944, 17375232, 17387520, 17399808, 17412096, 17424384, 17436672, 17448960, 17461248, 17473536, 17485824 // 0x00001600
|
||||
, 17498112, 17510400, 17522688, 17534976, 17547264, 17559552, 17571840, 17584128, 17596416, 17608704, 17620992, 17633280, 17645568, 17657856, 17670144, 17682432 // 0x00001640
|
||||
, 17694720, 17707008, 17719296, 17731584, 17743872, 17756160, 17768448, 17780736, 17793024, 17805312, 17817600, 17829888, 17842176, 17854464, 17866752, 17879040 // 0x00001680
|
||||
, 17891328, 17903616, 17915904, 17928192, 17940480, 17952768, 17965056, 17977344, 17989632, 18001920, 18014208, 18026496, 18038784, 18051072, 18063360, 18075648 // 0x000016C0
|
||||
, 18087936, 18100224, 18112512, 18124800, 18137088, 18149376, 18161664, 18173952, 18186240, 18198528, 18210816, 18223104, 18235392, 18247680, 18259968, 18272256 // 0x00001700
|
||||
, 18284544, 18296832, 18309120, 18321408, 18333696, 18345984, 18358272, 18370560, 18382848, 18395136, 18407424, 18419712, 18432000, 18444288, 18456576, 18468864 // 0x00001740
|
||||
, 18481152, 18493440, 18505728, 18518016, 18530304, 18542592, 18554880, 18567168, 18579456, 18591744, 18604032, 18616320, 18628608, 18640896, 18653184, 18665472 // 0x00001780
|
||||
, 18677760, 18690048, 18702336, 18714624, 18726912, 18739200, 18751488, 18763776, 18776064, 18788352, 18800640, 18812928, 18825216, 18837504, 18849792, 18862080 // 0x000017C0
|
||||
, 18874368, 18886656, 18898944, 18911232, 18923520, 18935808, 18948096, 18960384, 18972672, 18984960, 18997248, 19009536, 19021824, 19034112, 19046400, 19058688 // 0x00001800
|
||||
, 19070976, 19083264, 19095552, 19107840, 19120128, 19132416, 19144704, 19156992, 19169280, 19181568, 19193856, 19206144, 19218432, 19230720, 19243008, 19255296 // 0x00001840
|
||||
, 19267584, 19279872, 19292160, 19304448, 19316736, 19329024, 19341312, 19353600, 19365888, 19378176, 19390464, 19402752, 19415040, 19427328, 19439616, 19451904 // 0x00001880
|
||||
, 19464192, 19476480, 19488768, 19501056, 19513344, 19525632, 19537920, 19550208, 19562496, 19574784, 19587072, 19599360, 19611648, 19623936, 19636224, 19648512 // 0x000018C0
|
||||
, 19660800, 19673088, 19685376, 19697664, 19709952, 19722240, 19734528, 19746816, 19759104, 19771392, 19783680, 19795968, 19808256, 19820544, 19832832, 19845120 // 0x00001900
|
||||
, 19857408, 19869696, 19881984, 19894272, 19906560, 19918848, 19931136, 19943424, 19955712, 19968000, 19980288, 19992576, 20004864, 20017152, 20029440, 20041728 // 0x00001940
|
||||
, 20054016, 20066304, 20078592, 20090880, 20103168, 20115456, 20127744, 20140032, 20152320, 20164608, 20176896, 20189184, 20201472, 20213760, 20226048, 20238336 // 0x00001980
|
||||
, 20250624, 20262912, 20275200, 20287488, 20299776, 20312064, 20324352, 20336640, 20348928, 20361216, 20373504, 20385792, 20398080, 20410368, 20422656, 20434944 // 0x000019C0
|
||||
, 20447232, 20459520, 20471808, 20484096, 20496384, 20508672, 20520960, 20533248, 20545536, 20557824, 20570112, 20582400, 20594688, 20606976, 20619264, 20631552 // 0x00001A00
|
||||
, 20643840, 20656128, 20668416, 20680704, 20692992, 20705280, 20717568, 20729856, 20742144, 20754432, 20766720, 20779008, 20791296, 20803584, 20815872, 20828160 // 0x00001A40
|
||||
, 20840448, 20852736, 20865024, 20877312, 20889600, 20901888, 20914176, 20926464, 20938752, 20951040, 20963328, 20975616, 20987904, 21000192, 21012480, 21024768 // 0x00001A80
|
||||
, 21037056, 21049344, 21061632, 21073920, 21086208, 21098496, 21110784, 21123072, 21135360, 21147648, 21159936, 21172224, 21184512, 21196800, 21209088, 21221376 // 0x00001AC0
|
||||
, 21233664, 21245952, 21258240, 21270528, 21282816, 21295104, 21307392, 21319680, 21331968, 21344256, 21356544, 21368832, 21381120, 21393408, 21405696, 21417984 // 0x00001B00
|
||||
, 21430272, 21442560, 21454848, 21467136, 21479424, 21491712, 21504000, 21516288, 21528576, 21540864, 21553152, 21565440, 21577728, 21590016, 21602304, 21614592 // 0x00001B40
|
||||
, 21626880, 21639168, 21651456, 21663744, 21676032, 21688320, 21700608, 21712896, 21725184, 21737472, 21749760, 21762048, 21774336, 21786624, 21798912, 21811200 // 0x00001B80
|
||||
, 21823488, 21835776, 21848064, 21860352, 21872640, 21884928, 21897216, 21909504, 21921792, 21934080, 21946368, 21958656, 21970944, 21983232, 21995520, 22007808 // 0x00001BC0
|
||||
, 22020096, 22032384, 22044672, 22056960, 22069248, 22081536, 22093824, 22106112, 22118400, 22130688, 22142976, 22155264, 22167552, 22179840, 22192128, 22204416 // 0x00001C00
|
||||
, 22216704, 22228992, 22241280, 22253568, 22265856, 22278144, 22290432, 22302720, 22315008, 22327296, 22339584, 22351872, 22364160, 22376448, 22388736, 22401024 // 0x00001C40
|
||||
, 22413312, 22425600, 22437888, 22450176, 22462464, 22474752, 22487040, 22499328, 22511616, 22523904, 22536192, 22548480, 22560768, 22573056, 22585344, 22597632 // 0x00001C80
|
||||
, 22609920, 22622208, 22634496, 22646784, 22659072, 22671360, 22683648, 22695936, 22708224, 22720512, 22732800, 22745088, 22757376, 22769664, 22781952, 22794240 // 0x00001CC0
|
||||
, 22806528, 22818816, 22831104, 22843392, 22855680, 22867968, 22880256, 22892544, 22904832, 22917120, 22929408, 22941696, 22953984, 22966272, 22978560, 22990848 // 0x00001D00
|
||||
, 23003136, 23015424, 23027712, 23040000, 23052288, 23064576, 23076864, 23089152, 23101440, 23113728, 23126016, 23138304, 23150592, 23162880, 23175168, 23187456 // 0x00001D40
|
||||
, 23199744, 23212032, 23224320, 23236608, 23248896, 23261184, 23273472, 23285760, 23298048, 23310336, 23322624, 23334912, 23347200, 23359488, 23371776, 23384064 // 0x00001D80
|
||||
, 23396352, 23408640, 23420928, 23433216, 23445504, 23457792, 23470080, 23482368, 23494656, 23506944, 23519232, 23531520, 23543808, 23556096, 23568384, 23580672 // 0x00001DC0
|
||||
, 23592960, 23605248, 23617536, 23629824, 23642112, 23654400, 23666688, 23678976, 23691264, 23703552, 23715840, 23728128, 23740416, 23752704, 23764992, 23777280 // 0x00001E00
|
||||
, 23789568, 23801856, 23814144, 23826432, 23838720, 23851008, 23863296, 23875584, 23887872, 23900160, 23912448, 23924736, 23937024, 23949312, 23961600, 23973888 // 0x00001E40
|
||||
, 23986176, 23998464, 24010752, 24023040, 24035328, 24047616, 24059904, 24072192, 24084480, 24096768, 24109056, 24121344, 24133632, 24145920, 24158208, 24170496 // 0x00001E80
|
||||
, 24182784, 24195072, 24207360, 24219648, 24231936, 24244224, 24256512, 24268800, 24281088, 24293376, 24305664, 24317952, 24330240, 24342528, 24354816, 24367104 // 0x00001EC0
|
||||
, 24379392, 24391680, 24403968, 24416256, 24428544, 24440832, 24453120, 24465408, 24477696, 24489984, 24502272, 24514560, 24526848, 24539136, 24551424, 24563712 // 0x00001F00
|
||||
, 24576000, 24588288, 24600576, 24612864, 24625152, 24637440, 24649728, 24662016, 24674304, 24686592, 24698880, 24711168, 24723456, 24735744, 24748032, 24760320 // 0x00001F40
|
||||
, 24772608, 24784896, 24797184, 24809472, 24821760, 24834048, 24846336, 24858624, 24870912, 24883200, 24895488, 24907776, 24920064, 24932352, 24944640, 24956928 // 0x00001F80
|
||||
, 24969216, 24981504, 24993792, 25006080, 25018368, 25030656, 25042944, 25055232, 25067520, 25079808, 25092096, 25104384, 25116672, 25128960, 25141248, 25153536 // 0x00001FC0
|
||||
, 25165824, 25178112, 25190400, 25202688, 25214976, 25227264, 25239552, 25251840, 25264128, 25276416, 25288704, 25300992, 25313280, 25325568, 25337856, 25350144 // 0x00002000
|
||||
, 25362432, 25374720, 25387008, 25399296, 25411584, 25423872, 25436160, 25448448, 25460736, 25473024, 25485312, 25497600, 25509888, 25522176, 25534464, 25546752 // 0x00002040
|
||||
, 25559040, 25571328, 25583616, 25595904, 25608192, 25620480, 25632768, 25645056, 25657344, 25669632, 25681920, 25694208, 25706496, 25718784, 25731072, 25743360 // 0x00002080
|
||||
, 25755648, 25767936, 25780224, 25792512, 25804800, 25817088, 25829376, 25841664, 25853952, 25866240, 25878528, 25890816, 25903104, 25915392, 25927680, 25939968 // 0x000020C0
|
||||
, 25952256, 25964544, 25976832, 25989120, 26001408, 26013696, 26025984, 26038272, 26050560, 26062848, 26075136, 26087424, 26099712, 26112000, 26124288, 26136576 // 0x00002100
|
||||
, 26148864, 26161152, 26173440, 26185728, 26198016, 26210304, 26222592, 26234880, 26247168, 26259456, 26271744, 26284032, 26296320, 26308608, 26320896, 26333184 // 0x00002140
|
||||
, 26345472, 26357760, 26370048, 26382336, 26394624, 26406912, 26419200, 26431488, 26443776, 26456064, 26468352, 26480640, 26492928, 26505216, 26517504, 26529792 // 0x00002180
|
||||
, 26542080, 26554368, 26566656, 26578944, 26591232, 26603520, 26615808, 26628096, 26640384, 26652672, 26664960, 26677248, 26689536, 26701824, 26714112, 26726400 // 0x000021C0
|
||||
, 26738688, 26750976, 26763264, 26775552, 26787840, 26800128, 26812416, 26824704, 26836992, 26849280, 26861568, 26873856, 26886144, 26898432, 26910720, 26923008 // 0x00002200
|
||||
, 26935296, 26947584, 26959872, 26972160, 26984448, 26996736, 27009024, 27021312, 27033600, 27045888, 27058176, 27070464, 27082752, 27095040, 27107328, 27119616 // 0x00002240
|
||||
, 27131904, 27144192, 27156480, 27168768, 27181056, 27193344, 27205632, 27217920, 27230208, 27242496, 27254784, 27267072, 27279360, 27291648, 27303936, 27316224 // 0x00002280
|
||||
, 27328512, 27340800, 27353088, 27365376, 27377664, 27389952, 27402240, 27414528, 27426816, 27439104, 27451392, 27463680, 27475968, 27488256, 27500544, 27512832 // 0x000022C0
|
||||
, 27525120, 27537408, 27549696, 27561984, 27574272, 27586560, 27598848, 27611136, 27623424, 27635712, 27648000, 27660288, 27672576, 27684864, 27697152, 27709440 // 0x00002300
|
||||
, 27721728, 27734016, 27746304, 27758592, 27770880, 27783168, 27795456, 27807744, 27820032, 27832320, 27844608, 27856896, 27869184, 27881472, 27893760, 27906048 // 0x00002340
|
||||
, 27918336, 27930624, 27942912, 27955200, 27967488, 27979776, 27992064, 28004352, 28016640, 28028928, 28041216, 28053504, 28065792, 28078080, 28090368, 28102656 // 0x00002380
|
||||
, 28114944, 28127232, 28139520, 28151808, 28164096, 28176384, 28188672, 28200960, 28213248, 28225536, 28237824, 28250112, 28262400, 28274688, 28286976, 28299264 // 0x000023C0
|
||||
, 28311552, 28323840, 28336128, 28348416, 28360704, 28372992, 28385280, 28397568, 28409856, 28422144, 28434432, 28446720, 28459008, 28471296, 28483584, 28495872 // 0x00002400
|
||||
, 28508160, 28520448, 28532736, 28545024, 28557312, 28569600, 28581888, 28594176, 28606464, 28618752, 28631040, 28643328, 28655616, 28667904, 28680192, 28692480 // 0x00002440
|
||||
, 28704768, 28717056, 28729344, 28741632, 28753920, 28766208, 28778496, 28790784, 28803072, 28815360, 28827648, 28839936, 28852224, 28864512, 28876800, 28889088 // 0x00002480
|
||||
, 28901376, 28913664, 28925952, 28938240, 28950528, 28962816, 28975104, 28987392, 28999680, 29011968, 29024256, 29036544, 29048832, 29061120, 29073408, 29085696 // 0x000024C0
|
||||
, 29097984, 29110272, 29122560, 29134848, 29147136, 29159424, 29171712, 29184000, 29196288, 29208576, 29220864, 29233152, 29245440, 29257728, 29270016, 29282304 // 0x00002500
|
||||
, 29294592, 29306880, 29319168, 29331456, 29343744, 29356032, 29368320, 29380608, 29392896, 29405184, 29417472, 29429760, 29442048, 29454336, 29466624, 29478912 // 0x00002540
|
||||
, 29491200, 29503488, 29515776, 29528064, 29540352, 29552640, 29564928, 29577216, 29589504, 29601792, 29614080, 29626368, 29638656, 29650944, 29663232, 29675520 // 0x00002580
|
||||
, 29687808, 29700096, 29712384, 29724672, 29736960, 29749248, 29761536, 29773824, 29786112, 29798400, 29810688, 29822976, 29835264, 29847552, 29859840, 29872128 // 0x000025C0
|
||||
, 29884416, 29896704, 29908992, 29921280, 29933568, 29945856, 29958144, 29970432, 29982720, 29995008, 30007296, 30019584, 30031872, 30044160, 30056448, 30068736 // 0x00002600
|
||||
, 30081024, 30093312, 30105600, 30117888, 30130176, 30142464, 30154752, 30167040, 30179328, 30191616, 30203904, 30216192, 30228480, 30240768, 30253056, 30265344 // 0x00002640
|
||||
, 30277632, 30289920, 30302208, 30314496, 30326784, 30339072, 30351360, 30363648, 30375936, 30388224, 30400512, 30412800, 30425088, 30437376, 30449664, 30461952 // 0x00002680
|
||||
, 30474240, 30486528, 30498816, 30511104, 30523392, 30535680, 30547968, 30560256, 30572544, 30584832, 30597120, 30609408, 30621696, 30633984, 30646272, 30658560 // 0x000026C0
|
||||
, 30670848, 30683136, 30695424, 30707712, 30720000, 30732288, 30744576, 30756864, 30769152, 30781440, 30793728, 30806016, 30818304, 30830592, 30842880, 30855168 // 0x00002700
|
||||
, 30867456, 30879744, 30892032, 30904320, 30916608, 30928896, 30941184, 30953472, 30965760, 30978048, 30990336, 31002624, 31014912, 31027200, 31039488, 31051776 // 0x00002740
|
||||
, 31064064, 31076352, 31088640, 31100928, 31113216, 31125504, 31137792, 31150080, 31162368, 31174656, 31186944, 31199232, 31211520, 31223808, 31236096, 31248384 // 0x00002780
|
||||
, 31260672, 31272960, 31285248, 31297536, 31309824, 31322112, 31334400, 31346688, 31358976, 31371264, 31383552, 31395840, 31408128, 31420416, 31432704, 31444992 // 0x000027C0
|
||||
, 31457280, 31469568, 31481856, 31494144, 31506432, 31518720, 31531008, 31543296, 31555584, 31567872, 31580160, 31592448, 31604736, 31617024, 31629312, 31641600 // 0x00002800
|
||||
, 31653888, 31666176, 31678464, 31690752, 31703040, 31715328, 31727616, 31739904, 31752192, 31764480, 31776768, 31789056, 31801344, 31813632, 31825920, 31838208 // 0x00002840
|
||||
, 31850496, 31862784, 31875072, 31887360, 31899648, 31911936, 31924224, 31936512, 31948800, 31961088, 31973376, 31985664, 31997952, 32010240, 32022528, 32034816 // 0x00002880
|
||||
, 32047104, 32059392, 32071680, 32083968, 32096256, 32108544, 32120832, 32133120, 32145408, 32157696, 32169984, 32182272, 32194560, 32206848, 32219136, 32231424 // 0x000028C0
|
||||
, 32243712, 32256000, 32268288, 32280576, 32292864, 32305152, 32317440, 32329728, 32342016, 32354304, 32366592, 32378880, 32391168, 32403456, 32415744, 32428032 // 0x00002900
|
||||
, 32440320, 32452608, 32464896, 32477184, 32489472, 32501760, 32514048, 32526336, 32538624, 32550912, 32563200, 32575488, 32587776, 32600064, 32612352, 32624640 // 0x00002940
|
||||
, 32636928, 32649216, 32661504, 32673792, 32686080, 32698368, 32710656, 32722944, 32735232, 32747520, 32759808, 32772096, 32784384, 32796672, 32808960, 32821248 // 0x00002980
|
||||
, 32833536, 32845824, 32858112, 32870400, 32882688, 32894976, 32907264, 32919552, 32931840, 32944128, 32956416, 32968704, 32980992, 32993280, 33005568, 33017856 // 0x000029C0
|
||||
, 33030144, 33042432, 33054720, 33067008, 33079296, 33091584, 33103872, 33116160, 33128448, 33140736, 33153024, 33165312, 33177600, 33189888, 33202176, 33214464 // 0x00002A00
|
||||
, 33226752, 33239040, 33251328, 33263616, 33275904, 33288192, 33300480, 33312768, 33325056, 33337344, 33349632, 33361920, 33374208, 33386496, 33398784, 33411072 // 0x00002A40
|
||||
, 33423360, 33435648, 33447936, 33460224, 33472512, 33484800, 33497088, 33509376, 33521664, 33533952, 33546240, 33558528, 33570816, 33583104, 33595392, 33607680 // 0x00002A80
|
||||
, 33619968, 33632256, 33644544, 33656832, 33669120, 33681408, 33693696, 33705984, 33718272, 33730560, 33742848, 33755136, 33767424, 33779712, 33792000, 33804288 // 0x00002AC0
|
||||
, 33816576, 33828864, 33841152, 33853440, 33865728, 33878016, 33890304, 33902592, 33914880, 33927168, 33939456, 33951744, 33964032, 33976320, 33988608, 34000896 // 0x00002B00
|
||||
, 34013184, 34025472, 34037760, 34050048, 34062336, 34074624, 34086912, 34099200, 34111488, 34123776, 34136064, 34148352, 34160640, 34172928, 34185216, 34197504 // 0x00002B40
|
||||
, 34209792, 34222080, 34234368, 34246656, 34258944, 34271232, 34283520, 34295808, 34308096, 34320384, 34332672, 34344960, 34357248, 34369536, 34381824, 34394112 // 0x00002B80
|
||||
, 34406400, 34418688, 34430976, 34443264, 34455552, 34467840, 34480128, 34492416, 34504704, 34516992, 34529280, 34541568, 34553856, 34566144, 34578432, 34590720 // 0x00002BC0
|
||||
, 34603008, 34615296, 34627584, 34639872, 34652160, 34664448, 34676736, 34689024, 34701312, 34713600, 34725888, 34738176, 34750464, 34762752, 34775040, 34787328 // 0x00002C00
|
||||
, 34799616, 34811904, 34824192, 34836480, 34848768, 34861056, 34873344, 34885632, 34897920, 34910208, 34922496, 34934784, 34947072, 34959360, 34971648, 34983936 // 0x00002C40
|
||||
, 34996224, 35008512, 35020800, 35033088, 35045376, 35057664, 35069952, 35082240, 35094528, 35106816, 35119104, 35131392, 35143680, 35155968, 35168256, 35180544 // 0x00002C80
|
||||
, 35192832, 35205120, 35217408, 35229696, 35241984, 35254272, 35266560, 35278848, 35291136, 35303424, 35315712, 35328000, 35340288, 35352576, 35364864, 35377152 // 0x00002CC0
|
||||
, 35389440, 35401728, 35414016, 35426304, 35438592, 35450880, 35463168, 35475456, 35487744, 35500032, 35512320, 35524608, 35536896, 35549184, 35561472, 35573760 // 0x00002D00
|
||||
, 35586048, 35598336, 35610624, 35622912, 35635200, 35647488, 35659776, 35672064, 35684352, 35696640, 35708928, 35721216, 35733504, 35745792, 35758080, 35770368 // 0x00002D40
|
||||
, 35782656, 35794944, 35807232, 35819520, 35831808, 35844096, 35856384, 35868672, 35880960, 35893248, 35905536, 35917824, 35930112, 35942400, 35954688, 35966976 // 0x00002D80
|
||||
, 35979264, 35991552, 36003840, 36016128, 36028416, 36040704, 36052992, 36065280, 36077568, 36089856, 36102144, 36114432, 36126720, 36139008, 36151296, 36163584 // 0x00002DC0
|
||||
, 36175872, 36188160, 36200448, 36212736, 36225024, 36237312, 36249600, 36261888, 36274176, 36286464, 36298752, 36311040, 36323328, 36335616, 36347904, 36360192 // 0x00002E00
|
||||
, 36372480, 36384768, 36397056, 36409344, 36421632, 36433920, 36446208, 36458496, 36470784, 36483072, 36495360, 36507648, 36519936, 36532224, 36544512, 36556800 // 0x00002E40
|
||||
, 36569088, 36581376, 36593664, 36605952, 36618240, 36630528, 36642816, 36655104, 36667392, 36679680, 36691968, 36704256, 36716544, 36728832, 36741120, 36753408 // 0x00002E80
|
||||
, 36765696, 36777984, 36790272, 36802560, 36814848, 36827136, 36839424, 36851712, 36864000, 36876288, 36888576, 36900864, 36913152, 36925440, 36937728, 36950016 // 0x00002EC0
|
||||
, 36962304, 36974592, 36986880, 36999168, 37011456, 37023744, 37036032, 37048320, 37060608, 37072896, 37085184, 37097472, 37109760, 37122048, 37134336, 37146624 // 0x00002F00
|
||||
, 37158912, 37171200, 37183488, 37195776, 37208064, 37220352, 37232640, 37244928, 37257216, 37269504, 37281792, 37294080, 37306368, 37318656, 37330944, 37343232 // 0x00002F40
|
||||
, 37355520, 37367808, 37380096, 37392384, 37404672, 37416960, 37429248, 37441536, 37453824, 37466112, 37478400, 37490688, 37502976, 37515264, 37527552, 37539840 // 0x00002F80
|
||||
, 37552128, 37564416, 37576704, 37588992, 37601280, 37613568, 37625856, 37638144, 37650432, 37662720, 37675008, 37687296, 37699584, 37711872, 37724160, 37736448 // 0x00002FC0
|
||||
, 37748736, 37761024, 37773312, 37785600, 37797888, 37810176, 37822464, 37834752, 37847040, 37859328, 37871616, 37883904, 37896192, 37908480, 37920768, 37933056 // 0x00003000
|
||||
, 37945344, 37957632, 37969920, 37982208, 37994496, 38006784, 38019072, 38031360, 38043648, 38055936, 38068224, 38080512, 38092800, 38105088, 38117376, 38129664 // 0x00003040
|
||||
, 38141952, 38154240, 38166528, 38178816, 38191104, 38203392, 38215680, 38227968, 38240256, 38252544, 38264832, 38277120, 38289408, 38301696, 38313984, 38326272 // 0x00003080
|
||||
, 38338560, 38350848, 38363136, 38375424, 38387712, 38400000, 38412288, 38424576, 38436864, 38449152, 38461440, 38473728, 38486016, 38498304, 38510592, 38522880 // 0x000030C0
|
||||
, 38535168, 38547456, 38559744, 38572032, 38584320, 38596608, 38608896, 38621184, 38633472, 38645760, 38658048, 38670336, 38682624, 38694912, 38707200, 38719488 // 0x00003100
|
||||
, 38731776, 38744064, 38756352, 38768640, 38780928, 38793216, 38805504, 38817792, 38830080, 38842368, 38854656, 38866944, 38879232, 38891520, 38903808, 38916096 // 0x00003140
|
||||
, 38928384, 38940672, 38952960, 38965248, 38977536, 38989824, 39002112, 39014400, 39026688, 39038976, 39051264, 39063552, 39075840, 39088128, 39100416, 39112704 // 0x00003180
|
||||
, 39124992, 39137280, 39149568, 39161856, 39174144, 39186432, 39198720, 39211008, 39223296, 39235584, 39247872, 39260160, 39272448, 39284736, 39297024, 39309312 // 0x000031C0
|
||||
, 39321600, 39333888, 39346176, 39358464, 39370752, 39383040, 39395328, 39407616, 39419904, 39432192, 39444480, 39456768, 39469056, 39481344, 39493632, 39505920 // 0x00003200
|
||||
, 39518208, 39530496, 39542784, 39555072, 39567360, 39579648, 39591936, 39604224, 39616512, 39628800, 39641088, 39653376, 39665664, 39677952, 39690240, 39702528 // 0x00003240
|
||||
, 39714816, 39727104, 39739392, 39751680, 39763968, 39776256, 39788544, 39800832, 39813120, 39825408, 39837696, 39849984, 39862272, 39874560, 39886848, 39899136 // 0x00003280
|
||||
, 39911424, 39923712, 39936000, 39948288, 39960576, 39972864, 39985152, 39997440, 40009728, 40022016, 40034304, 40046592, 40058880, 40071168, 40083456, 40095744 // 0x000032C0
|
||||
, 40108032, 40120320, 40132608, 40144896, 40157184, 40169472, 40181760, 40194048, 40206336, 40218624, 40230912, 40243200, 40255488, 40267776, 40280064, 40292352 // 0x00003300
|
||||
, 40304640, 40316928, 40329216, 40341504, 40353792, 40366080, 40378368, 40390656, 40402944, 40415232, 40427520, 40439808, 40452096, 40464384, 40476672, 40488960 // 0x00003340
|
||||
, 40501248, 40513536, 40525824, 40538112, 40550400, 40562688, 40574976, 40587264, 40599552, 40611840, 40624128, 40636416, 40648704, 40660992, 40673280, 40685568 // 0x00003380
|
||||
, 40697856, 40710144, 40722432, 40734720, 40747008, 40759296, 40771584, 40783872, 40796160, 40808448, 40820736, 40833024, 40845312, 40857600, 40869888, 40882176 // 0x000033C0
|
||||
, 40894464, 40906752, 40919040, 40931328, 40943616, 40955904, 40968192, 40980480, 40992768, 41005056, 41017344, 41029632, 41041920, 41054208, 41066496, 41078784 // 0x00003400
|
||||
, 41091072, 41103360, 41115648, 41127936, 41140224, 41152512, 41164800, 41177088, 41189376, 41201664, 41213952, 41226240, 41238528, 41250816, 41263104, 41275392 // 0x00003440
|
||||
, 41287680, 41299968, 41312256, 41324544, 41336832, 41349120, 41361408, 41373696, 41385984, 41398272, 41410560, 41422848, 41435136, 41447424, 41459712, 41472000 // 0x00003480
|
||||
, 41484288, 41496576, 41508864, 41521152, 41533440, 41545728, 41558016, 41570304, 41582592, 41594880, 41607168, 41619456, 41631744, 41644032, 41656320, 41668608 // 0x000034C0
|
||||
, 41680896, 41693184, 41705472, 41717760, 41730048, 41742336, 41754624, 41766912, 41779200, 41791488, 41803776, 41816064, 41828352, 41840640, 41852928, 41865216 // 0x00003500
|
||||
, 41877504, 41889792, 41902080, 41914368, 41926656, 41938944, 41951232, 41963520, 41975808, 41988096, 42000384, 42012672, 42024960, 42037248, 42049536, 42061824 // 0x00003540
|
||||
, 42074112, 42086400, 42098688, 42110976, 42123264, 42135552, 42147840, 42160128, 42172416, 42184704, 42196992, 42209280, 42221568, 42233856, 42246144, 42258432 // 0x00003580
|
||||
, 42270720, 42283008, 42295296, 42307584, 42319872, 42332160, 42344448, 42356736, 42369024, 42381312, 42393600, 42405888, 42418176, 42430464, 42442752, 42455040 // 0x000035C0
|
||||
, 42467328, 42479616, 42491904, 42504192, 42516480, 42528768, 42541056, 42553344, 42565632, 42577920, 42590208, 42602496, 42614784, 42627072, 42639360, 42651648 // 0x00003600
|
||||
, 42663936, 42676224, 42688512, 42700800, 42713088, 42725376, 42737664, 42749952, 42762240, 42774528, 42786816, 42799104, 42811392, 42823680, 42835968, 42848256 // 0x00003640
|
||||
, 42860544, 42872832, 42885120, 42897408, 42909696, 42921984, 42934272, 42946560, 42958848, 42971136, 42983424, 42995712, 43008000, 43020288, 43032576, 43044864 // 0x00003680
|
||||
, 43057152, 43069440, 43081728, 43094016, 43106304, 43118592, 43130880, 43143168, 43155456, 43167744, 43180032, 43192320, 43204608, 43216896, 43229184, 43241472 // 0x000036C0
|
||||
, 43253760, 43266048, 43278336, 43290624, 43302912, 43315200, 43327488, 43339776, 43352064, 43364352, 43376640, 43388928, 43401216, 43413504, 43425792, 43438080 // 0x00003700
|
||||
, 43450368, 43462656, 43474944, 43487232, 43499520, 43511808, 43524096, 43536384, 43548672, 43560960, 43573248, 43585536, 43597824, 43610112, 43622400, 43634688 // 0x00003740
|
||||
, 43646976, 43659264, 43671552, 43683840, 43696128, 43708416, 43720704, 43732992, 43745280, 43757568, 43769856, 43782144, 43794432, 43806720, 43819008, 43831296 // 0x00003780
|
||||
, 43843584, 43855872, 43868160, 43880448, 43892736, 43905024, 43917312, 43929600, 43941888, 43954176, 43966464, 43978752, 43991040, 44003328, 44015616, 44027904 // 0x000037C0
|
||||
, 44040192, 44052480, 44064768, 44077056, 44089344, 44101632, 44113920, 44126208, 44138496, 44150784, 44163072, 44175360, 44187648, 44199936, 44212224, 44224512 // 0x00003800
|
||||
, 44236800, 44249088, 44261376, 44273664, 44285952, 44298240, 44310528, 44322816, 44335104, 44347392, 44359680, 44371968, 44384256, 44396544, 44408832, 44421120 // 0x00003840
|
||||
, 44433408, 44445696, 44457984, 44470272, 44482560, 44494848, 44507136, 44519424, 44531712, 44544000, 44556288, 44568576, 44580864, 44593152, 44605440, 44617728 // 0x00003880
|
||||
, 44630016, 44642304, 44654592, 44666880, 44679168, 44691456, 44703744, 44716032, 44728320, 44740608, 44752896, 44765184, 44777472, 44789760, 44802048, 44814336 // 0x000038C0
|
||||
, 44826624, 44838912, 44851200, 44863488, 44875776, 44888064, 44900352, 44912640, 44924928, 44937216, 44949504, 44961792, 44974080, 44986368, 44998656, 45010944 // 0x00003900
|
||||
, 45023232, 45035520, 45047808, 45060096, 45072384, 45084672, 45096960, 45109248, 45121536, 45133824, 45146112, 45158400, 45170688, 45182976, 45195264, 45207552 // 0x00003940
|
||||
, 45219840, 45232128, 45244416, 45256704, 45268992, 45281280, 45293568, 45305856, 45318144, 45330432, 45342720, 45355008, 45367296, 45379584, 45391872, 45404160 // 0x00003980
|
||||
, 45416448, 45428736, 45441024, 45453312, 45465600, 45477888, 45490176, 45502464, 45514752, 45527040, 45539328, 45551616, 45563904, 45576192, 45588480, 45600768 // 0x000039C0
|
||||
, 45613056, 45625344, 45637632, 45649920, 45662208, 45674496, 45686784, 45699072, 45711360, 45723648, 45735936, 45748224, 45760512, 45772800, 45785088, 45797376 // 0x00003A00
|
||||
, 45809664, 45821952, 45834240, 45846528, 45858816, 45871104, 45883392, 45895680, 45907968, 45920256, 45932544, 45944832, 45957120, 45969408, 45981696, 45993984 // 0x00003A40
|
||||
, 46006272, 46018560, 46030848, 46043136, 46055424, 46067712, 46080000, 46092288, 46104576, 46116864, 46129152, 46141440, 46153728, 46166016, 46178304, 46190592 // 0x00003A80
|
||||
, 46202880, 46215168, 46227456, 46239744, 46252032, 46264320, 46276608, 46288896, 46301184, 46313472, 46325760, 46338048, 46350336, 46362624, 46374912, 46387200 // 0x00003AC0
|
||||
, 46399488, 46411776, 46424064, 46436352, 46448640, 46460928, 46473216, 46485504, 46497792, 46510080, 46522368, 46534656, 46546944, 46559232, 46571520, 46583808 // 0x00003B00
|
||||
, 46596096, 46608384, 46620672, 46632960, 46645248, 46657536, 46669824, 46682112, 46694400, 46706688, 46718976, 46731264, 46743552, 46755840, 46768128, 46780416 // 0x00003B40
|
||||
, 46792704, 46804992, 46817280, 46829568, 46841856, 46854144, 46866432, 46878720, 46891008, 46903296, 46915584, 46927872, 46940160, 46952448, 46964736, 46977024 // 0x00003B80
|
||||
, 46989312, 47001600, 47013888, 47026176, 47038464, 47050752, 47063040, 47075328, 47087616, 47099904, 47112192, 47124480, 47136768, 47149056, 47161344, 47173632 // 0x00003BC0
|
||||
, 47185920, 47198208, 47210496, 47222784, 47235072, 47247360, 47259648, 47271936, 47284224, 47296512, 47308800, 47321088, 47333376, 47345664, 47357952, 47370240 // 0x00003C00
|
||||
, 47382528, 47394816, 47407104, 47419392, 47431680, 47443968, 47456256, 47468544, 47480832, 47493120, 47505408, 47517696, 47529984, 47542272, 47554560, 47566848 // 0x00003C40
|
||||
, 47579136, 47591424, 47603712, 47616000, 47628288, 47640576, 47652864, 47665152, 47677440, 47689728, 47702016, 47714304, 47726592, 47738880, 47751168, 47763456 // 0x00003C80
|
||||
, 47775744, 47788032, 47800320, 47812608, 47824896, 47837184, 47849472, 47861760, 47874048, 47886336, 47898624, 47910912, 47923200, 47935488, 47947776, 47960064 // 0x00003CC0
|
||||
, 47972352, 47984640, 47996928, 48009216, 48021504, 48033792, 48046080, 48058368, 48070656, 48082944, 48095232, 48107520, 48119808, 48132096, 48144384, 48156672 // 0x00003D00
|
||||
, 48168960, 48181248, 48193536, 48205824, 48218112, 48230400, 48242688, 48254976, 48267264, 48279552, 48291840, 48304128, 48316416, 48328704, 48340992, 48353280 // 0x00003D40
|
||||
, 48365568, 48377856, 48390144, 48402432, 48414720, 48427008, 48439296, 48451584, 48463872, 48476160, 48488448, 48500736, 48513024, 48525312, 48537600, 48549888 // 0x00003D80
|
||||
, 48562176, 48574464, 48586752, 48599040, 48611328, 48623616, 48635904, 48648192, 48660480, 48672768, 48685056, 48697344, 48709632, 48721920, 48734208, 48746496 // 0x00003DC0
|
||||
, 48758784, 48771072, 48783360, 48795648, 48807936, 48820224, 48832512, 48844800, 48857088, 48869376, 48881664, 48893952, 48906240, 48918528, 48930816, 48943104 // 0x00003E00
|
||||
, 48955392, 48967680, 48979968, 48992256, 49004544, 49016832, 49029120, 49041408, 49053696, 49065984, 49078272, 49090560, 49102848, 49115136, 49127424, 49139712 // 0x00003E40
|
||||
, 49152000, 49164288, 49176576, 49188864, 49201152, 49213440, 49225728, 49238016, 49250304, 49262592, 49274880, 49287168, 49299456, 49311744, 49324032, 49336320 // 0x00003E80
|
||||
, 49348608, 49360896, 49373184, 49385472, 49397760, 49410048, 49422336, 49434624, 49446912, 49459200, 49471488, 49483776, 49496064, 49508352, 49520640, 49532928 // 0x00003EC0
|
||||
, 49545216, 49557504, 49569792, 49582080, 49594368, 49606656, 49618944, 49631232, 49643520, 49655808, 49668096, 49680384, 49692672, 49704960, 49717248, 49729536 // 0x00003F00
|
||||
, 49741824, 49754112, 49766400, 49778688, 49790976, 49803264, 49815552, 49827840, 49840128, 49852416, 49864704, 49876992, 49889280, 49901568, 49913856, 49926144 // 0x00003F40
|
||||
, 49938432, 49950720, 49963008, 49975296, 49987584, 49999872, 50012160, 50024448, 50036736, 50049024, 50061312, 50073600, 50085888, 50098176, 50110464, 50122752 // 0x00003F80
|
||||
, 50135040, 50147328, 50159616, 50171904, 50184192, 50196480, 50208768, 50221056, 50233344, 50245632, 50257920, 50270208, 50282496, 50294784, 50307072, 50319360};
|
||||
|
|
@ -1,299 +0,0 @@
|
|||
#pragma GCC optimize("Ofast")
|
||||
/*
|
||||
SN76489 emulation
|
||||
by Maxim in 2001 and 2002
|
||||
converted from my original Delphi implementation
|
||||
|
||||
I'm a C newbie so I'm sure there are loads of stupid things
|
||||
in here which I'll come back to some day and redo
|
||||
|
||||
Includes:
|
||||
- Super-high quality tone channel "oversampling" by calculating fractional positions on transitions
|
||||
- Noise output pattern reverse engineered from actual SMS output
|
||||
- Volume levels taken from actual SMS output
|
||||
|
||||
07/08/04 Charles MacDonald
|
||||
Modified for use with SMS Plus:
|
||||
- Added support for multiple PSG chips.
|
||||
- Added reset/config/update routines.
|
||||
- Added context management routines.
|
||||
- Removed SN76489_GetValues().
|
||||
- Removed some unused variables.
|
||||
|
||||
07/08/04 bzhxx few simplication for gwenesis to fit on MCU
|
||||
*/
|
||||
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "../bus/gwenesis_bus.h"
|
||||
#include "../sound/gwenesis_sn76489.h"
|
||||
|
||||
#include <pico.h>
|
||||
|
||||
extern int audio_enabled;
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef INLINE
|
||||
#define INLINE static __always_inline
|
||||
#endif
|
||||
#define NoiseInitialState 0x8000 /* Initial state of shift register */
|
||||
#define PSG_CUTOFF 0x6 /* Value below which PSG does not output */
|
||||
// #define PSG_MAX_VOLUME 2800
|
||||
// static const uint16 chanVolume[16] = {
|
||||
// PSG_MAX_VOLUME, /* MAX */
|
||||
// PSG_MAX_VOLUME * 0.794328234, /* -2dB */
|
||||
// PSG_MAX_VOLUME * 0.630957344, /* -4dB */
|
||||
// PSG_MAX_VOLUME * 0.501187233, /* -6dB */
|
||||
// PSG_MAX_VOLUME * 0.398107170, /* -8dB */
|
||||
// PSG_MAX_VOLUME * 0.316227766, /* -10dB */
|
||||
// PSG_MAX_VOLUME * 0.251188643, /* -12dB */
|
||||
// PSG_MAX_VOLUME * 0.199526231, /* -14dB */
|
||||
// PSG_MAX_VOLUME * 0.158489319, /* -16dB */
|
||||
// PSG_MAX_VOLUME * 0.125892541, /* -18dB */
|
||||
// PSG_MAX_VOLUME * 0.1, /* -20dB */
|
||||
// PSG_MAX_VOLUME * 0.079432823, /* -22dB */
|
||||
// PSG_MAX_VOLUME * 0.063095734, /* -24dB */
|
||||
// PSG_MAX_VOLUME * 0.050118723, /* -26dB */
|
||||
// PSG_MAX_VOLUME * 0.039810717, /* -28dB */
|
||||
// 0 /* OFF */
|
||||
// };
|
||||
|
||||
#define PSG_MAX_VOLUME_MAX 3100
|
||||
#define PSG_MAX_VOLUME_2dB (int)(PSG_MAX_VOLUME_MAX*0.794328234)
|
||||
#define PSG_MAX_VOLUME_4dB (int)(PSG_MAX_VOLUME_MAX*0.630957344)
|
||||
|
||||
static const int PSGVolumeValues[16] = {
|
||||
PSG_MAX_VOLUME_MAX,PSG_MAX_VOLUME_2dB,PSG_MAX_VOLUME_4dB,
|
||||
PSG_MAX_VOLUME_MAX / 2,PSG_MAX_VOLUME_2dB / 2,PSG_MAX_VOLUME_4dB / 2,
|
||||
PSG_MAX_VOLUME_MAX / 4,PSG_MAX_VOLUME_2dB / 4,PSG_MAX_VOLUME_4dB / 4,
|
||||
PSG_MAX_VOLUME_MAX / 8,PSG_MAX_VOLUME_2dB / 8,PSG_MAX_VOLUME_4dB / 8,
|
||||
PSG_MAX_VOLUME_MAX / 16,PSG_MAX_VOLUME_2dB / 16,PSG_MAX_VOLUME_4dB / 16,
|
||||
0
|
||||
};
|
||||
|
||||
extern uint8_t snd_accurate;
|
||||
|
||||
|
||||
static SN76489_Context gwenesis_SN76489;
|
||||
|
||||
void gwenesis_SN76489_Init(int PSGClockValue, int SamplingRate, int freq_divisor) {
|
||||
gwenesis_SN76489.dClock = (float)PSGClockValue / 16 / SamplingRate * GWENESIS_AUDIO_SAMPLING_DIVISOR;
|
||||
gwenesis_SN76489.divisor = freq_divisor;
|
||||
|
||||
gwenesis_SN76489_Reset();
|
||||
}
|
||||
|
||||
void gwenesis_SN76489_Reset() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= 3; i++) {
|
||||
/* Initialise PSG state */
|
||||
gwenesis_SN76489.Registers[2 * i] = 1; /* tone freq=1 */
|
||||
gwenesis_SN76489.Registers[2 * i + 1] = 0xf; /* vol=off */
|
||||
gwenesis_SN76489.NoiseFreq = 0x10;
|
||||
|
||||
/* Set counters to 0 */
|
||||
gwenesis_SN76489.ToneFreqVals[i] = 0;
|
||||
|
||||
/* Set flip-flops to 1 */
|
||||
gwenesis_SN76489.ToneFreqPos[i] = 1;
|
||||
|
||||
/* Set intermediate positions to do-not-use value */
|
||||
gwenesis_SN76489.IntermediatePos[i] = LONG_MIN;
|
||||
}
|
||||
|
||||
gwenesis_SN76489.LatchedRegister = 0;
|
||||
|
||||
/* Initialise noise generator */
|
||||
gwenesis_SN76489.NoiseShiftRegister = NoiseInitialState;
|
||||
|
||||
/* Zero clock */
|
||||
gwenesis_SN76489.Clock = 0;
|
||||
sn76489_index = 0;
|
||||
sn76489_clock = 0;
|
||||
}
|
||||
|
||||
void gwenesis_SN76489_SetContext(uint8* data) {
|
||||
memcpy(&gwenesis_SN76489, data, sizeof(SN76489_Context));
|
||||
}
|
||||
|
||||
void gwenesis_SN76489_GetContext(uint8* data) {
|
||||
memcpy(data, &gwenesis_SN76489, sizeof(SN76489_Context));
|
||||
}
|
||||
|
||||
uint8* gwenesis_SN76489_GetContextPtr() {
|
||||
return (uint8 *)&gwenesis_SN76489;
|
||||
}
|
||||
|
||||
int gwenesis_SN76489_GetContextSize(void) {
|
||||
return sizeof(SN76489_Context);
|
||||
}
|
||||
|
||||
INLINE void gwenesis_SN76489_Update(INT16* buffer, int length) {
|
||||
int i, j;
|
||||
|
||||
#pragma gcc unroll
|
||||
for (j = 0; j < length; j++) {
|
||||
#pragma gcc unroll(2)
|
||||
for (i = 0; i <= 2; ++i)
|
||||
if (gwenesis_SN76489.IntermediatePos[i] != LONG_MIN)
|
||||
gwenesis_SN76489.Channels[i] = __mul_instruction(gwenesis_SN76489.IntermediatePos[i],
|
||||
PSGVolumeValues[gwenesis_SN76489.Registers[__fast_mul(i, 2) + 1]]
|
||||
) / 65536;
|
||||
else
|
||||
gwenesis_SN76489.Channels[i] = __mul_instruction(gwenesis_SN76489.ToneFreqPos[i], PSGVolumeValues[gwenesis_SN76489.Registers[__fast_mul(i, 2) + 1]]);
|
||||
|
||||
gwenesis_SN76489.Channels[3] = (short)(__mul_instruction(PSGVolumeValues[gwenesis_SN76489.Registers[7]], (
|
||||
gwenesis_SN76489.NoiseShiftRegister & 0x1)));
|
||||
|
||||
gwenesis_SN76489.Channels[3] <<= 1; /* Double noise volume to make some people happy */
|
||||
|
||||
buffer[j] = (gwenesis_SN76489.Channels[0]);
|
||||
buffer[j] += (gwenesis_SN76489.Channels[1]);
|
||||
buffer[j] += (gwenesis_SN76489.Channels[2]);
|
||||
buffer[j] += (gwenesis_SN76489.Channels[3]);
|
||||
|
||||
gwenesis_SN76489.Clock += gwenesis_SN76489.dClock;
|
||||
gwenesis_SN76489.NumClocksForSample = (int)gwenesis_SN76489.Clock; /* truncates */
|
||||
gwenesis_SN76489.Clock -= gwenesis_SN76489.NumClocksForSample; /* remove integer part */
|
||||
|
||||
/* Decrement tone channel counters */
|
||||
for (i = 0; i <= 2; ++i)
|
||||
gwenesis_SN76489.ToneFreqVals[i] -= gwenesis_SN76489.NumClocksForSample;
|
||||
|
||||
/* Noise channel: match to tone2 or decrement its counter */
|
||||
if (gwenesis_SN76489.NoiseFreq == 0x80) gwenesis_SN76489.ToneFreqVals[3] = gwenesis_SN76489.ToneFreqVals[2];
|
||||
else gwenesis_SN76489.ToneFreqVals[3] -= gwenesis_SN76489.NumClocksForSample;
|
||||
|
||||
/* Tone channels: */
|
||||
#pragma gcc unroll(4)
|
||||
for (i = 0; i <= 2; ++i) {
|
||||
if (gwenesis_SN76489.ToneFreqVals[i] <= 0) {
|
||||
/* If it gets below 0... */
|
||||
if (gwenesis_SN76489.Registers[__fast_mul(i, 2)] > PSG_CUTOFF) {
|
||||
/* Calculate how much of the sample is + and how much is - */
|
||||
/* Go to floating point and include the clock fraction for extreme accuracy :D */
|
||||
/* Store as long int, maybe it's faster? I'm not very good at this */
|
||||
gwenesis_SN76489.IntermediatePos[i] = (long)(
|
||||
(gwenesis_SN76489.NumClocksForSample - gwenesis_SN76489.Clock +
|
||||
__fast_mul(gwenesis_SN76489.ToneFreqVals[i], 2)
|
||||
)
|
||||
* gwenesis_SN76489.ToneFreqPos[i] / (__fast_mul(gwenesis_SN76489.NumClocksForSample + gwenesis_SN76489.Clock,65536)));
|
||||
gwenesis_SN76489.ToneFreqPos[i] = -gwenesis_SN76489.ToneFreqPos[i]; /* Flip the flip-flop */
|
||||
}
|
||||
else {
|
||||
gwenesis_SN76489.ToneFreqPos[i] = 1; /* stuck value */
|
||||
gwenesis_SN76489.IntermediatePos[i] = LONG_MIN;
|
||||
}
|
||||
gwenesis_SN76489.ToneFreqVals[i] += gwenesis_SN76489.Registers[__fast_mul(i,2)] * (gwenesis_SN76489.NumClocksForSample / gwenesis_SN76489.Registers[__fast_mul(i, 2)] + 1);
|
||||
}
|
||||
else gwenesis_SN76489.IntermediatePos[i] = LONG_MIN;
|
||||
}
|
||||
|
||||
/* Noise channel */
|
||||
if (gwenesis_SN76489.ToneFreqVals[3] <= 0) {
|
||||
/* If it gets below 0... */
|
||||
gwenesis_SN76489.ToneFreqPos[3] = -gwenesis_SN76489.ToneFreqPos[3]; /* Flip the flip-flop */
|
||||
if (gwenesis_SN76489.NoiseFreq != 0x80) /* If not matching tone2, decrement counter */
|
||||
gwenesis_SN76489.ToneFreqVals[3] += __mul_instruction(gwenesis_SN76489.NoiseFreq, (
|
||||
gwenesis_SN76489.NumClocksForSample / gwenesis_SN76489.NoiseFreq + 1));
|
||||
if (gwenesis_SN76489.ToneFreqPos[3] == 1) {
|
||||
/* Only once per cycle... */
|
||||
int Feedback;
|
||||
if (gwenesis_SN76489.Registers[6] & 0x4) {
|
||||
/* White noise */
|
||||
/* Calculate parity of fed-back bits for feedback */
|
||||
|
||||
/* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */
|
||||
/* since that's (one or more bits set) && (not all bits set) */
|
||||
Feedback = ((gwenesis_SN76489.NoiseShiftRegister & gwenesis_SN76489.WhiteNoiseFeedback) && (
|
||||
(gwenesis_SN76489.NoiseShiftRegister & gwenesis_SN76489.WhiteNoiseFeedback) ^
|
||||
gwenesis_SN76489.WhiteNoiseFeedback));
|
||||
}
|
||||
else /* Periodic noise */
|
||||
Feedback = gwenesis_SN76489.NoiseShiftRegister & 1;
|
||||
|
||||
gwenesis_SN76489.NoiseShiftRegister = (gwenesis_SN76489.NoiseShiftRegister >> 1) | (Feedback << 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SN76589 execution */
|
||||
extern int scan_line;
|
||||
extern bool sn76489_enabled;
|
||||
|
||||
void YM2612Update(uint16_t *buffer, int length);
|
||||
|
||||
void gwenesis_SN76489_run(int target) {
|
||||
if (sn76489_clock >= target) return;
|
||||
|
||||
target /= GWENESIS_AUDIO_SAMPLING_DIVISOR;
|
||||
|
||||
int sn76489_prev_index = sn76489_index;
|
||||
sn76489_index += (target - sn76489_clock) / gwenesis_SN76489.divisor;
|
||||
if (sn76489_index > sn76489_prev_index) {
|
||||
int16* buf = gwenesis_sn76489_buffer + sn76489_prev_index;
|
||||
int len = sn76489_index - sn76489_prev_index;
|
||||
if (sn76489_enabled) gwenesis_SN76489_Update(buf, len);
|
||||
YM2612Update(buf, len);
|
||||
sn76489_clock = __mul_instruction(sn76489_index, gwenesis_SN76489.divisor);
|
||||
}
|
||||
else {
|
||||
sn76489_index = sn76489_prev_index;
|
||||
}
|
||||
}
|
||||
|
||||
void gwenesis_SN76489_Write(int data, int target) {
|
||||
if (!audio_enabled)
|
||||
return;
|
||||
|
||||
if (snd_accurate == 1)
|
||||
gwenesis_SN76489_run(target);
|
||||
|
||||
if (data & 0x80) {
|
||||
/* Latch/data byte %1 cc t dddd */
|
||||
gwenesis_SN76489.LatchedRegister = ((data >> 4) & 0x07);
|
||||
gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] =
|
||||
(gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] &
|
||||
0x3f0) /* zero low 4 bits */
|
||||
| (data & 0xf); /* and replace with data */
|
||||
}
|
||||
else {
|
||||
/* Data byte %0 - dddddd */
|
||||
if (!(gwenesis_SN76489.LatchedRegister % 2) && (gwenesis_SN76489.LatchedRegister < 5))
|
||||
/* Tone register */
|
||||
gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] =
|
||||
(gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] & 0x00f) /* zero high 6 bits */
|
||||
| ((data & 0x3f) << 4); /* and replace with data */
|
||||
else
|
||||
/* Other register */
|
||||
gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] = data & 0x0f; /* Replace with data */
|
||||
}
|
||||
switch (gwenesis_SN76489.LatchedRegister) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4: /* Tone channels */
|
||||
if (gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] == 0)
|
||||
gwenesis_SN76489.Registers[gwenesis_SN76489.LatchedRegister] = 1;
|
||||
/* Zero frequency changed to 1 to avoid div/0 */
|
||||
break;
|
||||
case 6: /* Noise */
|
||||
gwenesis_SN76489.NoiseShiftRegister = NoiseInitialState; /* reset shift register */
|
||||
gwenesis_SN76489.NoiseFreq = 0x10 << (gwenesis_SN76489.Registers[6] & 0x3);
|
||||
/* set noise signal generator frequency */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gwenesis_sn76489_save_state() {
|
||||
}
|
||||
|
||||
void gwenesis_sn76489_load_state() {
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
|
||||
#ifndef _GWENESIS_SN76489_H_
|
||||
#define _GWENESIS_SN76489_H_
|
||||
|
||||
/*
|
||||
More testing is needed to find and confirm feedback patterns for
|
||||
SN76489 variants and compatible chips.
|
||||
*/
|
||||
|
||||
#undef uint8
|
||||
#undef uint16
|
||||
#undef uint32
|
||||
#undef uint64
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short int uint16;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef signed short int int16;
|
||||
typedef signed int int32;
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short int UINT16;
|
||||
typedef unsigned int UINT32;
|
||||
|
||||
typedef signed char INT8;
|
||||
typedef signed short int INT16;
|
||||
typedef signed int INT32;
|
||||
typedef long signed int INT641;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Variables */
|
||||
float Clock;
|
||||
float dClock;
|
||||
int NumClocksForSample;
|
||||
int WhiteNoiseFeedback;
|
||||
int divisor;
|
||||
|
||||
/* PSG registers: */
|
||||
UINT16 Registers[8]; /* Tone, vol x4 */
|
||||
int LatchedRegister;
|
||||
UINT16 NoiseShiftRegister;
|
||||
INT16 NoiseFreq; /* Noise channel signal generator frequency */
|
||||
|
||||
/* Output calculation variables */
|
||||
INT16 ToneFreqVals[4]; /* Frequency register values (counters) */
|
||||
INT8 ToneFreqPos[4]; /* Frequency channel flip-flops */
|
||||
INT16 Channels[4]; /* Value of each channel, before stereo is applied */
|
||||
INT641 IntermediatePos[4]; /* intermediate values used at boundaries between + and - */
|
||||
|
||||
} SN76489_Context;
|
||||
|
||||
extern int16 gwenesis_sn76489_buffer[];
|
||||
extern int sn76489_index;
|
||||
extern int sn76489_clock;
|
||||
|
||||
/* Function prototypes */
|
||||
void gwenesis_SN76489_Init( int PSGClockValue, int SamplingRate,int freq_divisor);
|
||||
void gwenesis_SN76489_Reset();
|
||||
void gwenesis_SN76489_start();
|
||||
void gwenesis_SN76489_SetContext(uint8 *data);
|
||||
void gwenesis_SN76489_GetContext(uint8 *data);
|
||||
uint8 *gwenesis_SN76489_GetContextPtr();
|
||||
int gwenesis_SN76489_GetContextSize(void);
|
||||
void gwenesis_SN76489_Write(int data, int target);
|
||||
void gwenesis_SN76489_run(int target);
|
||||
|
||||
void gwenesis_sn76489_save_state();
|
||||
void gwenesis_sn76489_load_state();
|
||||
|
||||
#endif /* _GWENESIS_SN76489_H_ */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,65 +0,0 @@
|
|||
const unsigned int __in_flash() __aligned(4) sin_tab[] = {
|
||||
4274, 3462, 3086, 2838, 2652, 2504, 2380, 2274, 2182, 2100, 2026, 1958, 1898, 1840, 1788, 1738 // 0x00000000
|
||||
, 1692, 1650, 1608, 1570, 1534, 1498, 1464, 1434, 1402, 1374, 1344, 1318, 1292, 1266, 1242, 1218 // 0x00000040
|
||||
, 1196, 1174, 1152, 1132, 1112, 1092, 1072, 1054, 1036, 1018, 1002, 984, 968, 952, 936, 922 // 0x00000080
|
||||
, 906, 892, 878, 864, 850, 836, 822, 810, 798, 784, 772, 760, 750, 738, 726, 716 // 0x000000C0
|
||||
, 704, 694, 682, 672, 662, 652, 642, 632, 622, 614, 604, 594, 586, 578, 568, 560 // 0x00000100
|
||||
, 552, 542, 534, 526, 518, 510, 502, 496, 488, 480, 472, 466, 458, 452, 444, 438 // 0x00000140
|
||||
, 430, 424, 418, 410, 404, 398, 392, 386, 380, 374, 368, 362, 356, 350, 344, 338 // 0x00000180
|
||||
, 334, 328, 322, 318, 312, 306, 302, 296, 292, 286, 282, 276, 272, 268, 262, 258 // 0x000001C0
|
||||
, 254, 250, 244, 240, 236, 232, 228, 224, 220, 216, 212, 208, 204, 200, 196, 192 // 0x00000200
|
||||
, 188, 184, 182, 178, 174, 170, 166, 164, 160, 156, 154, 150, 148, 144, 140, 138 // 0x00000240
|
||||
, 134, 132, 128, 126, 124, 120, 118, 114, 112, 110, 106, 104, 102, 98, 96, 94 // 0x00000280
|
||||
, 92, 90, 86, 84, 82, 80, 78, 76, 74, 72, 70, 68, 66, 64, 62, 60 // 0x000002C0
|
||||
, 58, 56, 54, 52, 50, 48, 46, 46, 44, 42, 40, 40, 38, 36, 34, 34 // 0x00000300
|
||||
, 32, 30, 30, 28, 26, 26, 24, 24, 22, 20, 20, 18, 18, 16, 16, 14 // 0x00000340
|
||||
, 14, 14, 12, 12, 10, 10, 10, 8, 8, 8, 6, 6, 6, 4, 4, 4 // 0x00000380
|
||||
, 4, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 // 0x000003C0
|
||||
, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 4 // 0x00000400
|
||||
, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 14, 14 // 0x00000440
|
||||
, 14, 16, 16, 18, 18, 20, 20, 22, 24, 24, 26, 26, 28, 30, 30, 32 // 0x00000480
|
||||
, 34, 34, 36, 38, 40, 40, 42, 44, 46, 46, 48, 50, 52, 54, 56, 58 // 0x000004C0
|
||||
, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 90, 92 // 0x00000500
|
||||
, 94, 96, 98, 102, 104, 106, 110, 112, 114, 118, 120, 124, 126, 128, 132, 134 // 0x00000540
|
||||
, 138, 140, 144, 148, 150, 154, 156, 160, 164, 166, 170, 174, 178, 182, 184, 188 // 0x00000580
|
||||
, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 250, 254 // 0x000005C0
|
||||
, 258, 262, 268, 272, 276, 282, 286, 292, 296, 302, 306, 312, 318, 322, 328, 334 // 0x00000600
|
||||
, 338, 344, 350, 356, 362, 368, 374, 380, 386, 392, 398, 404, 410, 418, 424, 430 // 0x00000640
|
||||
, 438, 444, 452, 458, 466, 472, 480, 488, 496, 502, 510, 518, 526, 534, 542, 552 // 0x00000680
|
||||
, 560, 568, 578, 586, 594, 604, 614, 622, 632, 642, 652, 662, 672, 682, 694, 704 // 0x000006C0
|
||||
, 716, 726, 738, 750, 760, 772, 784, 798, 810, 822, 836, 850, 864, 878, 892, 906 // 0x00000700
|
||||
, 922, 936, 952, 968, 984, 1002, 1018, 1036, 1054, 1072, 1092, 1112, 1132, 1152, 1174, 1196 // 0x00000740
|
||||
, 1218, 1242, 1266, 1292, 1318, 1344, 1374, 1402, 1434, 1464, 1498, 1534, 1570, 1608, 1650, 1692 // 0x00000780
|
||||
, 1738, 1788, 1840, 1898, 1958, 2026, 2100, 2182, 2274, 2380, 2504, 2652, 2838, 3086, 3462, 4274 // 0x000007C0
|
||||
, 4275, 3463, 3087, 2839, 2653, 2505, 2381, 2275, 2183, 2101, 2027, 1959, 1899, 1841, 1789, 1739 // 0x00000800
|
||||
, 1693, 1651, 1609, 1571, 1535, 1499, 1465, 1435, 1403, 1375, 1345, 1319, 1293, 1267, 1243, 1219 // 0x00000840
|
||||
, 1197, 1175, 1153, 1133, 1113, 1093, 1073, 1055, 1037, 1019, 1003, 985, 969, 953, 937, 923 // 0x00000880
|
||||
, 907, 893, 879, 865, 851, 837, 823, 811, 799, 785, 773, 761, 751, 739, 727, 717 // 0x000008C0
|
||||
, 705, 695, 683, 673, 663, 653, 643, 633, 623, 615, 605, 595, 587, 579, 569, 561 // 0x00000900
|
||||
, 553, 543, 535, 527, 519, 511, 503, 497, 489, 481, 473, 467, 459, 453, 445, 439 // 0x00000940
|
||||
, 431, 425, 419, 411, 405, 399, 393, 387, 381, 375, 369, 363, 357, 351, 345, 339 // 0x00000980
|
||||
, 335, 329, 323, 319, 313, 307, 303, 297, 293, 287, 283, 277, 273, 269, 263, 259 // 0x000009C0
|
||||
, 255, 251, 245, 241, 237, 233, 229, 225, 221, 217, 213, 209, 205, 201, 197, 193 // 0x00000A00
|
||||
, 189, 185, 183, 179, 175, 171, 167, 165, 161, 157, 155, 151, 149, 145, 141, 139 // 0x00000A40
|
||||
, 135, 133, 129, 127, 125, 121, 119, 115, 113, 111, 107, 105, 103, 99, 97, 95 // 0x00000A80
|
||||
, 93, 91, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61 // 0x00000AC0
|
||||
, 59, 57, 55, 53, 51, 49, 47, 47, 45, 43, 41, 41, 39, 37, 35, 35 // 0x00000B00
|
||||
, 33, 31, 31, 29, 27, 27, 25, 25, 23, 21, 21, 19, 19, 17, 17, 15 // 0x00000B40
|
||||
, 15, 15, 13, 13, 11, 11, 11, 9, 9, 9, 7, 7, 7, 5, 5, 5 // 0x00000B80
|
||||
, 5, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1 // 0x00000BC0
|
||||
, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 5 // 0x00000C00
|
||||
, 5, 5, 5, 7, 7, 7, 9, 9, 9, 11, 11, 11, 13, 13, 15, 15 // 0x00000C40
|
||||
, 15, 17, 17, 19, 19, 21, 21, 23, 25, 25, 27, 27, 29, 31, 31, 33 // 0x00000C80
|
||||
, 35, 35, 37, 39, 41, 41, 43, 45, 47, 47, 49, 51, 53, 55, 57, 59 // 0x00000CC0
|
||||
, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 91, 93 // 0x00000D00
|
||||
, 95, 97, 99, 103, 105, 107, 111, 113, 115, 119, 121, 125, 127, 129, 133, 135 // 0x00000D40
|
||||
, 139, 141, 145, 149, 151, 155, 157, 161, 165, 167, 171, 175, 179, 183, 185, 189 // 0x00000D80
|
||||
, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 251, 255 // 0x00000DC0
|
||||
, 259, 263, 269, 273, 277, 283, 287, 293, 297, 303, 307, 313, 319, 323, 329, 335 // 0x00000E00
|
||||
, 339, 345, 351, 357, 363, 369, 375, 381, 387, 393, 399, 405, 411, 419, 425, 431 // 0x00000E40
|
||||
, 439, 445, 453, 459, 467, 473, 481, 489, 497, 503, 511, 519, 527, 535, 543, 553 // 0x00000E80
|
||||
, 561, 569, 579, 587, 595, 605, 615, 623, 633, 643, 653, 663, 673, 683, 695, 705 // 0x00000EC0
|
||||
, 717, 727, 739, 751, 761, 773, 785, 799, 811, 823, 837, 851, 865, 879, 893, 907 // 0x00000F00
|
||||
, 923, 937, 953, 969, 985, 1003, 1019, 1037, 1055, 1073, 1093, 1113, 1133, 1153, 1175, 1197 // 0x00000F40
|
||||
, 1219, 1243, 1267, 1293, 1319, 1345, 1375, 1403, 1435, 1465, 1499, 1535, 1571, 1609, 1651, 1693 // 0x00000F80
|
||||
, 1739, 1789, 1841, 1899, 1959, 2027, 2101, 2183, 2275, 2381, 2505, 2653, 2839, 3087, 3463, 4275};
|
||||
|
|
@ -1,417 +0,0 @@
|
|||
const signed int __in_flash() __aligned(4) tl_tab[] = {
|
||||
8168, -8168, 8148, -8148, 8124, -8124, 8104, -8104, 8080, -8080, 8060, -8060, 8040, -8040, 8016, -8016 // 0x00000000
|
||||
, 7996, -7996, 7972, -7972, 7952, -7952, 7932, -7932, 7908, -7908, 7888, -7888, 7864, -7864, 7844, -7844 // 0x00000040
|
||||
, 7824, -7824, 7804, -7804, 7780, -7780, 7760, -7760, 7740, -7740, 7720, -7720, 7696, -7696, 7676, -7676 // 0x00000080
|
||||
, 7656, -7656, 7636, -7636, 7616, -7616, 7592, -7592, 7572, -7572, 7552, -7552, 7532, -7532, 7512, -7512 // 0x000000C0
|
||||
, 7492, -7492, 7472, -7472, 7452, -7452, 7432, -7432, 7412, -7412, 7392, -7392, 7372, -7372, 7352, -7352 // 0x00000100
|
||||
, 7332, -7332, 7312, -7312, 7292, -7292, 7272, -7272, 7252, -7252, 7232, -7232, 7212, -7212, 7192, -7192 // 0x00000140
|
||||
, 7176, -7176, 7156, -7156, 7136, -7136, 7116, -7116, 7096, -7096, 7076, -7076, 7060, -7060, 7040, -7040 // 0x00000180
|
||||
, 7020, -7020, 7000, -7000, 6984, -6984, 6964, -6964, 6944, -6944, 6928, -6928, 6908, -6908, 6888, -6888 // 0x000001C0
|
||||
, 6868, -6868, 6852, -6852, 6832, -6832, 6816, -6816, 6796, -6796, 6776, -6776, 6760, -6760, 6740, -6740 // 0x00000200
|
||||
, 6724, -6724, 6704, -6704, 6688, -6688, 6668, -6668, 6652, -6652, 6632, -6632, 6616, -6616, 6596, -6596 // 0x00000240
|
||||
, 6580, -6580, 6560, -6560, 6544, -6544, 6524, -6524, 6508, -6508, 6492, -6492, 6472, -6472, 6456, -6456 // 0x00000280
|
||||
, 6436, -6436, 6420, -6420, 6404, -6404, 6384, -6384, 6368, -6368, 6352, -6352, 6336, -6336, 6316, -6316 // 0x000002C0
|
||||
, 6300, -6300, 6284, -6284, 6264, -6264, 6248, -6248, 6232, -6232, 6216, -6216, 6200, -6200, 6180, -6180 // 0x00000300
|
||||
, 6164, -6164, 6148, -6148, 6132, -6132, 6116, -6116, 6100, -6100, 6080, -6080, 6064, -6064, 6048, -6048 // 0x00000340
|
||||
, 6032, -6032, 6016, -6016, 6000, -6000, 5984, -5984, 5968, -5968, 5952, -5952, 5936, -5936, 5920, -5920 // 0x00000380
|
||||
, 5904, -5904, 5888, -5888, 5872, -5872, 5856, -5856, 5840, -5840, 5824, -5824, 5808, -5808, 5792, -5792 // 0x000003C0
|
||||
, 5776, -5776, 5760, -5760, 5744, -5744, 5732, -5732, 5716, -5716, 5700, -5700, 5684, -5684, 5668, -5668 // 0x00000400
|
||||
, 5652, -5652, 5636, -5636, 5624, -5624, 5608, -5608, 5592, -5592, 5576, -5576, 5564, -5564, 5548, -5548 // 0x00000440
|
||||
, 5532, -5532, 5516, -5516, 5504, -5504, 5488, -5488, 5472, -5472, 5456, -5456, 5444, -5444, 5428, -5428 // 0x00000480
|
||||
, 5412, -5412, 5400, -5400, 5384, -5384, 5368, -5368, 5356, -5356, 5340, -5340, 5328, -5328, 5312, -5312 // 0x000004C0
|
||||
, 5296, -5296, 5284, -5284, 5268, -5268, 5256, -5256, 5240, -5240, 5228, -5228, 5212, -5212, 5200, -5200 // 0x00000500
|
||||
, 5184, -5184, 5168, -5168, 5156, -5156, 5144, -5144, 5128, -5128, 5116, -5116, 5100, -5100, 5088, -5088 // 0x00000540
|
||||
, 5072, -5072, 5060, -5060, 5044, -5044, 5032, -5032, 5020, -5020, 5004, -5004, 4992, -4992, 4976, -4976 // 0x00000580
|
||||
, 4964, -4964, 4952, -4952, 4936, -4936, 4924, -4924, 4912, -4912, 4896, -4896, 4884, -4884, 4872, -4872 // 0x000005C0
|
||||
, 4856, -4856, 4844, -4844, 4832, -4832, 4820, -4820, 4804, -4804, 4792, -4792, 4780, -4780, 4768, -4768 // 0x00000600
|
||||
, 4752, -4752, 4740, -4740, 4728, -4728, 4716, -4716, 4704, -4704, 4688, -4688, 4676, -4676, 4664, -4664 // 0x00000640
|
||||
, 4652, -4652, 4640, -4640, 4628, -4628, 4616, -4616, 4600, -4600, 4588, -4588, 4576, -4576, 4564, -4564 // 0x00000680
|
||||
, 4552, -4552, 4540, -4540, 4528, -4528, 4516, -4516, 4504, -4504, 4492, -4492, 4480, -4480, 4468, -4468 // 0x000006C0
|
||||
, 4456, -4456, 4444, -4444, 4432, -4432, 4420, -4420, 4408, -4408, 4396, -4396, 4384, -4384, 4372, -4372 // 0x00000700
|
||||
, 4360, -4360, 4348, -4348, 4336, -4336, 4324, -4324, 4312, -4312, 4300, -4300, 4288, -4288, 4276, -4276 // 0x00000740
|
||||
, 4264, -4264, 4256, -4256, 4244, -4244, 4232, -4232, 4220, -4220, 4208, -4208, 4196, -4196, 4184, -4184 // 0x00000780
|
||||
, 4176, -4176, 4164, -4164, 4152, -4152, 4140, -4140, 4128, -4128, 4120, -4120, 4108, -4108, 4096, -4096 // 0x000007C0
|
||||
, 4084, -4084, 4074, -4074, 4062, -4062, 4052, -4052, 4040, -4040, 4030, -4030, 4020, -4020, 4008, -4008 // 0x00000800
|
||||
, 3998, -3998, 3986, -3986, 3976, -3976, 3966, -3966, 3954, -3954, 3944, -3944, 3932, -3932, 3922, -3922 // 0x00000840
|
||||
, 3912, -3912, 3902, -3902, 3890, -3890, 3880, -3880, 3870, -3870, 3860, -3860, 3848, -3848, 3838, -3838 // 0x00000880
|
||||
, 3828, -3828, 3818, -3818, 3808, -3808, 3796, -3796, 3786, -3786, 3776, -3776, 3766, -3766, 3756, -3756 // 0x000008C0
|
||||
, 3746, -3746, 3736, -3736, 3726, -3726, 3716, -3716, 3706, -3706, 3696, -3696, 3686, -3686, 3676, -3676 // 0x00000900
|
||||
, 3666, -3666, 3656, -3656, 3646, -3646, 3636, -3636, 3626, -3626, 3616, -3616, 3606, -3606, 3596, -3596 // 0x00000940
|
||||
, 3588, -3588, 3578, -3578, 3568, -3568, 3558, -3558, 3548, -3548, 3538, -3538, 3530, -3530, 3520, -3520 // 0x00000980
|
||||
, 3510, -3510, 3500, -3500, 3492, -3492, 3482, -3482, 3472, -3472, 3464, -3464, 3454, -3454, 3444, -3444 // 0x000009C0
|
||||
, 3434, -3434, 3426, -3426, 3416, -3416, 3408, -3408, 3398, -3398, 3388, -3388, 3380, -3380, 3370, -3370 // 0x00000A00
|
||||
, 3362, -3362, 3352, -3352, 3344, -3344, 3334, -3334, 3326, -3326, 3316, -3316, 3308, -3308, 3298, -3298 // 0x00000A40
|
||||
, 3290, -3290, 3280, -3280, 3272, -3272, 3262, -3262, 3254, -3254, 3246, -3246, 3236, -3236, 3228, -3228 // 0x00000A80
|
||||
, 3218, -3218, 3210, -3210, 3202, -3202, 3192, -3192, 3184, -3184, 3176, -3176, 3168, -3168, 3158, -3158 // 0x00000AC0
|
||||
, 3150, -3150, 3142, -3142, 3132, -3132, 3124, -3124, 3116, -3116, 3108, -3108, 3100, -3100, 3090, -3090 // 0x00000B00
|
||||
, 3082, -3082, 3074, -3074, 3066, -3066, 3058, -3058, 3050, -3050, 3040, -3040, 3032, -3032, 3024, -3024 // 0x00000B40
|
||||
, 3016, -3016, 3008, -3008, 3000, -3000, 2992, -2992, 2984, -2984, 2976, -2976, 2968, -2968, 2960, -2960 // 0x00000B80
|
||||
, 2952, -2952, 2944, -2944, 2936, -2936, 2928, -2928, 2920, -2920, 2912, -2912, 2904, -2904, 2896, -2896 // 0x00000BC0
|
||||
, 2888, -2888, 2880, -2880, 2872, -2872, 2866, -2866, 2858, -2858, 2850, -2850, 2842, -2842, 2834, -2834 // 0x00000C00
|
||||
, 2826, -2826, 2818, -2818, 2812, -2812, 2804, -2804, 2796, -2796, 2788, -2788, 2782, -2782, 2774, -2774 // 0x00000C40
|
||||
, 2766, -2766, 2758, -2758, 2752, -2752, 2744, -2744, 2736, -2736, 2728, -2728, 2722, -2722, 2714, -2714 // 0x00000C80
|
||||
, 2706, -2706, 2700, -2700, 2692, -2692, 2684, -2684, 2678, -2678, 2670, -2670, 2664, -2664, 2656, -2656 // 0x00000CC0
|
||||
, 2648, -2648, 2642, -2642, 2634, -2634, 2628, -2628, 2620, -2620, 2614, -2614, 2606, -2606, 2600, -2600 // 0x00000D00
|
||||
, 2592, -2592, 2584, -2584, 2578, -2578, 2572, -2572, 2564, -2564, 2558, -2558, 2550, -2550, 2544, -2544 // 0x00000D40
|
||||
, 2536, -2536, 2530, -2530, 2522, -2522, 2516, -2516, 2510, -2510, 2502, -2502, 2496, -2496, 2488, -2488 // 0x00000D80
|
||||
, 2482, -2482, 2476, -2476, 2468, -2468, 2462, -2462, 2456, -2456, 2448, -2448, 2442, -2442, 2436, -2436 // 0x00000DC0
|
||||
, 2428, -2428, 2422, -2422, 2416, -2416, 2410, -2410, 2402, -2402, 2396, -2396, 2390, -2390, 2384, -2384 // 0x00000E00
|
||||
, 2376, -2376, 2370, -2370, 2364, -2364, 2358, -2358, 2352, -2352, 2344, -2344, 2338, -2338, 2332, -2332 // 0x00000E40
|
||||
, 2326, -2326, 2320, -2320, 2314, -2314, 2308, -2308, 2300, -2300, 2294, -2294, 2288, -2288, 2282, -2282 // 0x00000E80
|
||||
, 2276, -2276, 2270, -2270, 2264, -2264, 2258, -2258, 2252, -2252, 2246, -2246, 2240, -2240, 2234, -2234 // 0x00000EC0
|
||||
, 2228, -2228, 2222, -2222, 2216, -2216, 2210, -2210, 2204, -2204, 2198, -2198, 2192, -2192, 2186, -2186 // 0x00000F00
|
||||
, 2180, -2180, 2174, -2174, 2168, -2168, 2162, -2162, 2156, -2156, 2150, -2150, 2144, -2144, 2138, -2138 // 0x00000F40
|
||||
, 2132, -2132, 2128, -2128, 2122, -2122, 2116, -2116, 2110, -2110, 2104, -2104, 2098, -2098, 2092, -2092 // 0x00000F80
|
||||
, 2088, -2088, 2082, -2082, 2076, -2076, 2070, -2070, 2064, -2064, 2060, -2060, 2054, -2054, 2048, -2048 // 0x00000FC0
|
||||
, 2042, -2042, 2037, -2037, 2031, -2031, 2026, -2026, 2020, -2020, 2015, -2015, 2010, -2010, 2004, -2004 // 0x00001000
|
||||
, 1999, -1999, 1993, -1993, 1988, -1988, 1983, -1983, 1977, -1977, 1972, -1972, 1966, -1966, 1961, -1961 // 0x00001040
|
||||
, 1956, -1956, 1951, -1951, 1945, -1945, 1940, -1940, 1935, -1935, 1930, -1930, 1924, -1924, 1919, -1919 // 0x00001080
|
||||
, 1914, -1914, 1909, -1909, 1904, -1904, 1898, -1898, 1893, -1893, 1888, -1888, 1883, -1883, 1878, -1878 // 0x000010C0
|
||||
, 1873, -1873, 1868, -1868, 1863, -1863, 1858, -1858, 1853, -1853, 1848, -1848, 1843, -1843, 1838, -1838 // 0x00001100
|
||||
, 1833, -1833, 1828, -1828, 1823, -1823, 1818, -1818, 1813, -1813, 1808, -1808, 1803, -1803, 1798, -1798 // 0x00001140
|
||||
, 1794, -1794, 1789, -1789, 1784, -1784, 1779, -1779, 1774, -1774, 1769, -1769, 1765, -1765, 1760, -1760 // 0x00001180
|
||||
, 1755, -1755, 1750, -1750, 1746, -1746, 1741, -1741, 1736, -1736, 1732, -1732, 1727, -1727, 1722, -1722 // 0x000011C0
|
||||
, 1717, -1717, 1713, -1713, 1708, -1708, 1704, -1704, 1699, -1699, 1694, -1694, 1690, -1690, 1685, -1685 // 0x00001200
|
||||
, 1681, -1681, 1676, -1676, 1672, -1672, 1667, -1667, 1663, -1663, 1658, -1658, 1654, -1654, 1649, -1649 // 0x00001240
|
||||
, 1645, -1645, 1640, -1640, 1636, -1636, 1631, -1631, 1627, -1627, 1623, -1623, 1618, -1618, 1614, -1614 // 0x00001280
|
||||
, 1609, -1609, 1605, -1605, 1601, -1601, 1596, -1596, 1592, -1592, 1588, -1588, 1584, -1584, 1579, -1579 // 0x000012C0
|
||||
, 1575, -1575, 1571, -1571, 1566, -1566, 1562, -1562, 1558, -1558, 1554, -1554, 1550, -1550, 1545, -1545 // 0x00001300
|
||||
, 1541, -1541, 1537, -1537, 1533, -1533, 1529, -1529, 1525, -1525, 1520, -1520, 1516, -1516, 1512, -1512 // 0x00001340
|
||||
, 1508, -1508, 1504, -1504, 1500, -1500, 1496, -1496, 1492, -1492, 1488, -1488, 1484, -1484, 1480, -1480 // 0x00001380
|
||||
, 1476, -1476, 1472, -1472, 1468, -1468, 1464, -1464, 1460, -1460, 1456, -1456, 1452, -1452, 1448, -1448 // 0x000013C0
|
||||
, 1444, -1444, 1440, -1440, 1436, -1436, 1433, -1433, 1429, -1429, 1425, -1425, 1421, -1421, 1417, -1417 // 0x00001400
|
||||
, 1413, -1413, 1409, -1409, 1406, -1406, 1402, -1402, 1398, -1398, 1394, -1394, 1391, -1391, 1387, -1387 // 0x00001440
|
||||
, 1383, -1383, 1379, -1379, 1376, -1376, 1372, -1372, 1368, -1368, 1364, -1364, 1361, -1361, 1357, -1357 // 0x00001480
|
||||
, 1353, -1353, 1350, -1350, 1346, -1346, 1342, -1342, 1339, -1339, 1335, -1335, 1332, -1332, 1328, -1328 // 0x000014C0
|
||||
, 1324, -1324, 1321, -1321, 1317, -1317, 1314, -1314, 1310, -1310, 1307, -1307, 1303, -1303, 1300, -1300 // 0x00001500
|
||||
, 1296, -1296, 1292, -1292, 1289, -1289, 1286, -1286, 1282, -1282, 1279, -1279, 1275, -1275, 1272, -1272 // 0x00001540
|
||||
, 1268, -1268, 1265, -1265, 1261, -1261, 1258, -1258, 1255, -1255, 1251, -1251, 1248, -1248, 1244, -1244 // 0x00001580
|
||||
, 1241, -1241, 1238, -1238, 1234, -1234, 1231, -1231, 1228, -1228, 1224, -1224, 1221, -1221, 1218, -1218 // 0x000015C0
|
||||
, 1214, -1214, 1211, -1211, 1208, -1208, 1205, -1205, 1201, -1201, 1198, -1198, 1195, -1195, 1192, -1192 // 0x00001600
|
||||
, 1188, -1188, 1185, -1185, 1182, -1182, 1179, -1179, 1176, -1176, 1172, -1172, 1169, -1169, 1166, -1166 // 0x00001640
|
||||
, 1163, -1163, 1160, -1160, 1157, -1157, 1154, -1154, 1150, -1150, 1147, -1147, 1144, -1144, 1141, -1141 // 0x00001680
|
||||
, 1138, -1138, 1135, -1135, 1132, -1132, 1129, -1129, 1126, -1126, 1123, -1123, 1120, -1120, 1117, -1117 // 0x000016C0
|
||||
, 1114, -1114, 1111, -1111, 1108, -1108, 1105, -1105, 1102, -1102, 1099, -1099, 1096, -1096, 1093, -1093 // 0x00001700
|
||||
, 1090, -1090, 1087, -1087, 1084, -1084, 1081, -1081, 1078, -1078, 1075, -1075, 1072, -1072, 1069, -1069 // 0x00001740
|
||||
, 1066, -1066, 1064, -1064, 1061, -1061, 1058, -1058, 1055, -1055, 1052, -1052, 1049, -1049, 1046, -1046 // 0x00001780
|
||||
, 1044, -1044, 1041, -1041, 1038, -1038, 1035, -1035, 1032, -1032, 1030, -1030, 1027, -1027, 1024, -1024 // 0x000017C0
|
||||
, 1021, -1021, 1018, -1018, 1015, -1015, 1013, -1013, 1010, -1010, 1007, -1007, 1005, -1005, 1002, -1002 // 0x00001800
|
||||
, 999, -999, 996, -996, 994, -994, 991, -991, 988, -988, 986, -986, 983, -983, 980, -980 // 0x00001840
|
||||
, 978, -978, 975, -975, 972, -972, 970, -970, 967, -967, 965, -965, 962, -962, 959, -959 // 0x00001880
|
||||
, 957, -957, 954, -954, 952, -952, 949, -949, 946, -946, 944, -944, 941, -941, 939, -939 // 0x000018C0
|
||||
, 936, -936, 934, -934, 931, -931, 929, -929, 926, -926, 924, -924, 921, -921, 919, -919 // 0x00001900
|
||||
, 916, -916, 914, -914, 911, -911, 909, -909, 906, -906, 904, -904, 901, -901, 899, -899 // 0x00001940
|
||||
, 897, -897, 894, -894, 892, -892, 889, -889, 887, -887, 884, -884, 882, -882, 880, -880 // 0x00001980
|
||||
, 877, -877, 875, -875, 873, -873, 870, -870, 868, -868, 866, -866, 863, -863, 861, -861 // 0x000019C0
|
||||
, 858, -858, 856, -856, 854, -854, 852, -852, 849, -849, 847, -847, 845, -845, 842, -842 // 0x00001A00
|
||||
, 840, -840, 838, -838, 836, -836, 833, -833, 831, -831, 829, -829, 827, -827, 824, -824 // 0x00001A40
|
||||
, 822, -822, 820, -820, 818, -818, 815, -815, 813, -813, 811, -811, 809, -809, 807, -807 // 0x00001A80
|
||||
, 804, -804, 802, -802, 800, -800, 798, -798, 796, -796, 794, -794, 792, -792, 789, -789 // 0x00001AC0
|
||||
, 787, -787, 785, -785, 783, -783, 781, -781, 779, -779, 777, -777, 775, -775, 772, -772 // 0x00001B00
|
||||
, 770, -770, 768, -768, 766, -766, 764, -764, 762, -762, 760, -760, 758, -758, 756, -756 // 0x00001B40
|
||||
, 754, -754, 752, -752, 750, -750, 748, -748, 746, -746, 744, -744, 742, -742, 740, -740 // 0x00001B80
|
||||
, 738, -738, 736, -736, 734, -734, 732, -732, 730, -730, 728, -728, 726, -726, 724, -724 // 0x00001BC0
|
||||
, 722, -722, 720, -720, 718, -718, 716, -716, 714, -714, 712, -712, 710, -710, 708, -708 // 0x00001C00
|
||||
, 706, -706, 704, -704, 703, -703, 701, -701, 699, -699, 697, -697, 695, -695, 693, -693 // 0x00001C40
|
||||
, 691, -691, 689, -689, 688, -688, 686, -686, 684, -684, 682, -682, 680, -680, 678, -678 // 0x00001C80
|
||||
, 676, -676, 675, -675, 673, -673, 671, -671, 669, -669, 667, -667, 666, -666, 664, -664 // 0x00001CC0
|
||||
, 662, -662, 660, -660, 658, -658, 657, -657, 655, -655, 653, -653, 651, -651, 650, -650 // 0x00001D00
|
||||
, 648, -648, 646, -646, 644, -644, 643, -643, 641, -641, 639, -639, 637, -637, 636, -636 // 0x00001D40
|
||||
, 634, -634, 632, -632, 630, -630, 629, -629, 627, -627, 625, -625, 624, -624, 622, -622 // 0x00001D80
|
||||
, 620, -620, 619, -619, 617, -617, 615, -615, 614, -614, 612, -612, 610, -610, 609, -609 // 0x00001DC0
|
||||
, 607, -607, 605, -605, 604, -604, 602, -602, 600, -600, 599, -599, 597, -597, 596, -596 // 0x00001E00
|
||||
, 594, -594, 592, -592, 591, -591, 589, -589, 588, -588, 586, -586, 584, -584, 583, -583 // 0x00001E40
|
||||
, 581, -581, 580, -580, 578, -578, 577, -577, 575, -575, 573, -573, 572, -572, 570, -570 // 0x00001E80
|
||||
, 569, -569, 567, -567, 566, -566, 564, -564, 563, -563, 561, -561, 560, -560, 558, -558 // 0x00001EC0
|
||||
, 557, -557, 555, -555, 554, -554, 552, -552, 551, -551, 549, -549, 548, -548, 546, -546 // 0x00001F00
|
||||
, 545, -545, 543, -543, 542, -542, 540, -540, 539, -539, 537, -537, 536, -536, 534, -534 // 0x00001F40
|
||||
, 533, -533, 532, -532, 530, -530, 529, -529, 527, -527, 526, -526, 524, -524, 523, -523 // 0x00001F80
|
||||
, 522, -522, 520, -520, 519, -519, 517, -517, 516, -516, 515, -515, 513, -513, 512, -512 // 0x00001FC0
|
||||
, 510, -510, 509, -509, 507, -507, 506, -506, 505, -505, 503, -503, 502, -502, 501, -501 // 0x00002000
|
||||
, 499, -499, 498, -498, 497, -497, 495, -495, 494, -494, 493, -493, 491, -491, 490, -490 // 0x00002040
|
||||
, 489, -489, 487, -487, 486, -486, 485, -485, 483, -483, 482, -482, 481, -481, 479, -479 // 0x00002080
|
||||
, 478, -478, 477, -477, 476, -476, 474, -474, 473, -473, 472, -472, 470, -470, 469, -469 // 0x000020C0
|
||||
, 468, -468, 467, -467, 465, -465, 464, -464, 463, -463, 462, -462, 460, -460, 459, -459 // 0x00002100
|
||||
, 458, -458, 457, -457, 455, -455, 454, -454, 453, -453, 452, -452, 450, -450, 449, -449 // 0x00002140
|
||||
, 448, -448, 447, -447, 446, -446, 444, -444, 443, -443, 442, -442, 441, -441, 440, -440 // 0x00002180
|
||||
, 438, -438, 437, -437, 436, -436, 435, -435, 434, -434, 433, -433, 431, -431, 430, -430 // 0x000021C0
|
||||
, 429, -429, 428, -428, 427, -427, 426, -426, 424, -424, 423, -423, 422, -422, 421, -421 // 0x00002200
|
||||
, 420, -420, 419, -419, 418, -418, 416, -416, 415, -415, 414, -414, 413, -413, 412, -412 // 0x00002240
|
||||
, 411, -411, 410, -410, 409, -409, 407, -407, 406, -406, 405, -405, 404, -404, 403, -403 // 0x00002280
|
||||
, 402, -402, 401, -401, 400, -400, 399, -399, 398, -398, 397, -397, 396, -396, 394, -394 // 0x000022C0
|
||||
, 393, -393, 392, -392, 391, -391, 390, -390, 389, -389, 388, -388, 387, -387, 386, -386 // 0x00002300
|
||||
, 385, -385, 384, -384, 383, -383, 382, -382, 381, -381, 380, -380, 379, -379, 378, -378 // 0x00002340
|
||||
, 377, -377, 376, -376, 375, -375, 374, -374, 373, -373, 372, -372, 371, -371, 370, -370 // 0x00002380
|
||||
, 369, -369, 368, -368, 367, -367, 366, -366, 365, -365, 364, -364, 363, -363, 362, -362 // 0x000023C0
|
||||
, 361, -361, 360, -360, 359, -359, 358, -358, 357, -357, 356, -356, 355, -355, 354, -354 // 0x00002400
|
||||
, 353, -353, 352, -352, 351, -351, 350, -350, 349, -349, 348, -348, 347, -347, 346, -346 // 0x00002440
|
||||
, 345, -345, 344, -344, 344, -344, 343, -343, 342, -342, 341, -341, 340, -340, 339, -339 // 0x00002480
|
||||
, 338, -338, 337, -337, 336, -336, 335, -335, 334, -334, 333, -333, 333, -333, 332, -332 // 0x000024C0
|
||||
, 331, -331, 330, -330, 329, -329, 328, -328, 327, -327, 326, -326, 325, -325, 325, -325 // 0x00002500
|
||||
, 324, -324, 323, -323, 322, -322, 321, -321, 320, -320, 319, -319, 318, -318, 318, -318 // 0x00002540
|
||||
, 317, -317, 316, -316, 315, -315, 314, -314, 313, -313, 312, -312, 312, -312, 311, -311 // 0x00002580
|
||||
, 310, -310, 309, -309, 308, -308, 307, -307, 307, -307, 306, -306, 305, -305, 304, -304 // 0x000025C0
|
||||
, 303, -303, 302, -302, 302, -302, 301, -301, 300, -300, 299, -299, 298, -298, 298, -298 // 0x00002600
|
||||
, 297, -297, 296, -296, 295, -295, 294, -294, 294, -294, 293, -293, 292, -292, 291, -291 // 0x00002640
|
||||
, 290, -290, 290, -290, 289, -289, 288, -288, 287, -287, 286, -286, 286, -286, 285, -285 // 0x00002680
|
||||
, 284, -284, 283, -283, 283, -283, 282, -282, 281, -281, 280, -280, 280, -280, 279, -279 // 0x000026C0
|
||||
, 278, -278, 277, -277, 277, -277, 276, -276, 275, -275, 274, -274, 274, -274, 273, -273 // 0x00002700
|
||||
, 272, -272, 271, -271, 271, -271, 270, -270, 269, -269, 268, -268, 268, -268, 267, -267 // 0x00002740
|
||||
, 266, -266, 266, -266, 265, -265, 264, -264, 263, -263, 263, -263, 262, -262, 261, -261 // 0x00002780
|
||||
, 261, -261, 260, -260, 259, -259, 258, -258, 258, -258, 257, -257, 256, -256, 256, -256 // 0x000027C0
|
||||
, 255, -255, 254, -254, 253, -253, 253, -253, 252, -252, 251, -251, 251, -251, 250, -250 // 0x00002800
|
||||
, 249, -249, 249, -249, 248, -248, 247, -247, 247, -247, 246, -246, 245, -245, 245, -245 // 0x00002840
|
||||
, 244, -244, 243, -243, 243, -243, 242, -242, 241, -241, 241, -241, 240, -240, 239, -239 // 0x00002880
|
||||
, 239, -239, 238, -238, 238, -238, 237, -237, 236, -236, 236, -236, 235, -235, 234, -234 // 0x000028C0
|
||||
, 234, -234, 233, -233, 232, -232, 232, -232, 231, -231, 231, -231, 230, -230, 229, -229 // 0x00002900
|
||||
, 229, -229, 228, -228, 227, -227, 227, -227, 226, -226, 226, -226, 225, -225, 224, -224 // 0x00002940
|
||||
, 224, -224, 223, -223, 223, -223, 222, -222, 221, -221, 221, -221, 220, -220, 220, -220 // 0x00002980
|
||||
, 219, -219, 218, -218, 218, -218, 217, -217, 217, -217, 216, -216, 215, -215, 215, -215 // 0x000029C0
|
||||
, 214, -214, 214, -214, 213, -213, 213, -213, 212, -212, 211, -211, 211, -211, 210, -210 // 0x00002A00
|
||||
, 210, -210, 209, -209, 209, -209, 208, -208, 207, -207, 207, -207, 206, -206, 206, -206 // 0x00002A40
|
||||
, 205, -205, 205, -205, 204, -204, 203, -203, 203, -203, 202, -202, 202, -202, 201, -201 // 0x00002A80
|
||||
, 201, -201, 200, -200, 200, -200, 199, -199, 199, -199, 198, -198, 198, -198, 197, -197 // 0x00002AC0
|
||||
, 196, -196, 196, -196, 195, -195, 195, -195, 194, -194, 194, -194, 193, -193, 193, -193 // 0x00002B00
|
||||
, 192, -192, 192, -192, 191, -191, 191, -191, 190, -190, 190, -190, 189, -189, 189, -189 // 0x00002B40
|
||||
, 188, -188, 188, -188, 187, -187, 187, -187, 186, -186, 186, -186, 185, -185, 185, -185 // 0x00002B80
|
||||
, 184, -184, 184, -184, 183, -183, 183, -183, 182, -182, 182, -182, 181, -181, 181, -181 // 0x00002BC0
|
||||
, 180, -180, 180, -180, 179, -179, 179, -179, 178, -178, 178, -178, 177, -177, 177, -177 // 0x00002C00
|
||||
, 176, -176, 176, -176, 175, -175, 175, -175, 174, -174, 174, -174, 173, -173, 173, -173 // 0x00002C40
|
||||
, 172, -172, 172, -172, 172, -172, 171, -171, 171, -171, 170, -170, 170, -170, 169, -169 // 0x00002C80
|
||||
, 169, -169, 168, -168, 168, -168, 167, -167, 167, -167, 166, -166, 166, -166, 166, -166 // 0x00002CC0
|
||||
, 165, -165, 165, -165, 164, -164, 164, -164, 163, -163, 163, -163, 162, -162, 162, -162 // 0x00002D00
|
||||
, 162, -162, 161, -161, 161, -161, 160, -160, 160, -160, 159, -159, 159, -159, 159, -159 // 0x00002D40
|
||||
, 158, -158, 158, -158, 157, -157, 157, -157, 156, -156, 156, -156, 156, -156, 155, -155 // 0x00002D80
|
||||
, 155, -155, 154, -154, 154, -154, 153, -153, 153, -153, 153, -153, 152, -152, 152, -152 // 0x00002DC0
|
||||
, 151, -151, 151, -151, 151, -151, 150, -150, 150, -150, 149, -149, 149, -149, 149, -149 // 0x00002E00
|
||||
, 148, -148, 148, -148, 147, -147, 147, -147, 147, -147, 146, -146, 146, -146, 145, -145 // 0x00002E40
|
||||
, 145, -145, 145, -145, 144, -144, 144, -144, 143, -143, 143, -143, 143, -143, 142, -142 // 0x00002E80
|
||||
, 142, -142, 141, -141, 141, -141, 141, -141, 140, -140, 140, -140, 140, -140, 139, -139 // 0x00002EC0
|
||||
, 139, -139, 138, -138, 138, -138, 138, -138, 137, -137, 137, -137, 137, -137, 136, -136 // 0x00002F00
|
||||
, 136, -136, 135, -135, 135, -135, 135, -135, 134, -134, 134, -134, 134, -134, 133, -133 // 0x00002F40
|
||||
, 133, -133, 133, -133, 132, -132, 132, -132, 131, -131, 131, -131, 131, -131, 130, -130 // 0x00002F80
|
||||
, 130, -130, 130, -130, 129, -129, 129, -129, 129, -129, 128, -128, 128, -128, 128, -128 // 0x00002FC0
|
||||
, 127, -127, 127, -127, 126, -126, 126, -126, 126, -126, 125, -125, 125, -125, 125, -125 // 0x00003000
|
||||
, 124, -124, 124, -124, 124, -124, 123, -123, 123, -123, 123, -123, 122, -122, 122, -122 // 0x00003040
|
||||
, 122, -122, 121, -121, 121, -121, 121, -121, 120, -120, 120, -120, 120, -120, 119, -119 // 0x00003080
|
||||
, 119, -119, 119, -119, 119, -119, 118, -118, 118, -118, 118, -118, 117, -117, 117, -117 // 0x000030C0
|
||||
, 117, -117, 116, -116, 116, -116, 116, -116, 115, -115, 115, -115, 115, -115, 114, -114 // 0x00003100
|
||||
, 114, -114, 114, -114, 113, -113, 113, -113, 113, -113, 113, -113, 112, -112, 112, -112 // 0x00003140
|
||||
, 112, -112, 111, -111, 111, -111, 111, -111, 110, -110, 110, -110, 110, -110, 110, -110 // 0x00003180
|
||||
, 109, -109, 109, -109, 109, -109, 108, -108, 108, -108, 108, -108, 107, -107, 107, -107 // 0x000031C0
|
||||
, 107, -107, 107, -107, 106, -106, 106, -106, 106, -106, 105, -105, 105, -105, 105, -105 // 0x00003200
|
||||
, 105, -105, 104, -104, 104, -104, 104, -104, 103, -103, 103, -103, 103, -103, 103, -103 // 0x00003240
|
||||
, 102, -102, 102, -102, 102, -102, 101, -101, 101, -101, 101, -101, 101, -101, 100, -100 // 0x00003280
|
||||
, 100, -100, 100, -100, 100, -100, 99, -99, 99, -99, 99, -99, 99, -99, 98, -98 // 0x000032C0
|
||||
, 98, -98, 98, -98, 97, -97, 97, -97, 97, -97, 97, -97, 96, -96, 96, -96 // 0x00003300
|
||||
, 96, -96, 96, -96, 95, -95, 95, -95, 95, -95, 95, -95, 94, -94, 94, -94 // 0x00003340
|
||||
, 94, -94, 94, -94, 93, -93, 93, -93, 93, -93, 93, -93, 92, -92, 92, -92 // 0x00003380
|
||||
, 92, -92, 92, -92, 91, -91, 91, -91, 91, -91, 91, -91, 90, -90, 90, -90 // 0x000033C0
|
||||
, 90, -90, 90, -90, 89, -89, 89, -89, 89, -89, 89, -89, 88, -88, 88, -88 // 0x00003400
|
||||
, 88, -88, 88, -88, 87, -87, 87, -87, 87, -87, 87, -87, 86, -86, 86, -86 // 0x00003440
|
||||
, 86, -86, 86, -86, 86, -86, 85, -85, 85, -85, 85, -85, 85, -85, 84, -84 // 0x00003480
|
||||
, 84, -84, 84, -84, 84, -84, 83, -83, 83, -83, 83, -83, 83, -83, 83, -83 // 0x000034C0
|
||||
, 82, -82, 82, -82, 82, -82, 82, -82, 81, -81, 81, -81, 81, -81, 81, -81 // 0x00003500
|
||||
, 81, -81, 80, -80, 80, -80, 80, -80, 80, -80, 79, -79, 79, -79, 79, -79 // 0x00003540
|
||||
, 79, -79, 79, -79, 78, -78, 78, -78, 78, -78, 78, -78, 78, -78, 77, -77 // 0x00003580
|
||||
, 77, -77, 77, -77, 77, -77, 76, -76, 76, -76, 76, -76, 76, -76, 76, -76 // 0x000035C0
|
||||
, 75, -75, 75, -75, 75, -75, 75, -75, 75, -75, 74, -74, 74, -74, 74, -74 // 0x00003600
|
||||
, 74, -74, 74, -74, 73, -73, 73, -73, 73, -73, 73, -73, 73, -73, 72, -72 // 0x00003640
|
||||
, 72, -72, 72, -72, 72, -72, 72, -72, 71, -71, 71, -71, 71, -71, 71, -71 // 0x00003680
|
||||
, 71, -71, 70, -70, 70, -70, 70, -70, 70, -70, 70, -70, 70, -70, 69, -69 // 0x000036C0
|
||||
, 69, -69, 69, -69, 69, -69, 69, -69, 68, -68, 68, -68, 68, -68, 68, -68 // 0x00003700
|
||||
, 68, -68, 67, -67, 67, -67, 67, -67, 67, -67, 67, -67, 67, -67, 66, -66 // 0x00003740
|
||||
, 66, -66, 66, -66, 66, -66, 66, -66, 65, -65, 65, -65, 65, -65, 65, -65 // 0x00003780
|
||||
, 65, -65, 65, -65, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64 // 0x000037C0
|
||||
, 63, -63, 63, -63, 63, -63, 63, -63, 63, -63, 62, -62, 62, -62, 62, -62 // 0x00003800
|
||||
, 62, -62, 62, -62, 62, -62, 61, -61, 61, -61, 61, -61, 61, -61, 61, -61 // 0x00003840
|
||||
, 61, -61, 60, -60, 60, -60, 60, -60, 60, -60, 60, -60, 60, -60, 59, -59 // 0x00003880
|
||||
, 59, -59, 59, -59, 59, -59, 59, -59, 59, -59, 59, -59, 58, -58, 58, -58 // 0x000038C0
|
||||
, 58, -58, 58, -58, 58, -58, 58, -58, 57, -57, 57, -57, 57, -57, 57, -57 // 0x00003900
|
||||
, 57, -57, 57, -57, 56, -56, 56, -56, 56, -56, 56, -56, 56, -56, 56, -56 // 0x00003940
|
||||
, 56, -56, 55, -55, 55, -55, 55, -55, 55, -55, 55, -55, 55, -55, 55, -55 // 0x00003980
|
||||
, 54, -54, 54, -54, 54, -54, 54, -54, 54, -54, 54, -54, 53, -53, 53, -53 // 0x000039C0
|
||||
, 53, -53, 53, -53, 53, -53, 53, -53, 53, -53, 52, -52, 52, -52, 52, -52 // 0x00003A00
|
||||
, 52, -52, 52, -52, 52, -52, 52, -52, 51, -51, 51, -51, 51, -51, 51, -51 // 0x00003A40
|
||||
, 51, -51, 51, -51, 51, -51, 50, -50, 50, -50, 50, -50, 50, -50, 50, -50 // 0x00003A80
|
||||
, 50, -50, 50, -50, 50, -50, 49, -49, 49, -49, 49, -49, 49, -49, 49, -49 // 0x00003AC0
|
||||
, 49, -49, 49, -49, 48, -48, 48, -48, 48, -48, 48, -48, 48, -48, 48, -48 // 0x00003B00
|
||||
, 48, -48, 48, -48, 47, -47, 47, -47, 47, -47, 47, -47, 47, -47, 47, -47 // 0x00003B40
|
||||
, 47, -47, 47, -47, 46, -46, 46, -46, 46, -46, 46, -46, 46, -46, 46, -46 // 0x00003B80
|
||||
, 46, -46, 46, -46, 45, -45, 45, -45, 45, -45, 45, -45, 45, -45, 45, -45 // 0x00003BC0
|
||||
, 45, -45, 45, -45, 44, -44, 44, -44, 44, -44, 44, -44, 44, -44, 44, -44 // 0x00003C00
|
||||
, 44, -44, 44, -44, 43, -43, 43, -43, 43, -43, 43, -43, 43, -43, 43, -43 // 0x00003C40
|
||||
, 43, -43, 43, -43, 43, -43, 42, -42, 42, -42, 42, -42, 42, -42, 42, -42 // 0x00003C80
|
||||
, 42, -42, 42, -42, 42, -42, 41, -41, 41, -41, 41, -41, 41, -41, 41, -41 // 0x00003CC0
|
||||
, 41, -41, 41, -41, 41, -41, 41, -41, 40, -40, 40, -40, 40, -40, 40, -40 // 0x00003D00
|
||||
, 40, -40, 40, -40, 40, -40, 40, -40, 40, -40, 39, -39, 39, -39, 39, -39 // 0x00003D40
|
||||
, 39, -39, 39, -39, 39, -39, 39, -39, 39, -39, 39, -39, 39, -39, 38, -38 // 0x00003D80
|
||||
, 38, -38, 38, -38, 38, -38, 38, -38, 38, -38, 38, -38, 38, -38, 38, -38 // 0x00003DC0
|
||||
, 37, -37, 37, -37, 37, -37, 37, -37, 37, -37, 37, -37, 37, -37, 37, -37 // 0x00003E00
|
||||
, 37, -37, 37, -37, 36, -36, 36, -36, 36, -36, 36, -36, 36, -36, 36, -36 // 0x00003E40
|
||||
, 36, -36, 36, -36, 36, -36, 36, -36, 35, -35, 35, -35, 35, -35, 35, -35 // 0x00003E80
|
||||
, 35, -35, 35, -35, 35, -35, 35, -35, 35, -35, 35, -35, 35, -35, 34, -34 // 0x00003EC0
|
||||
, 34, -34, 34, -34, 34, -34, 34, -34, 34, -34, 34, -34, 34, -34, 34, -34 // 0x00003F00
|
||||
, 34, -34, 33, -33, 33, -33, 33, -33, 33, -33, 33, -33, 33, -33, 33, -33 // 0x00003F40
|
||||
, 33, -33, 33, -33, 33, -33, 33, -33, 32, -32, 32, -32, 32, -32, 32, -32 // 0x00003F80
|
||||
, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32 // 0x00003FC0
|
||||
, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31 // 0x00004000
|
||||
, 31, -31, 31, -31, 31, -31, 30, -30, 30, -30, 30, -30, 30, -30, 30, -30 // 0x00004040
|
||||
, 30, -30, 30, -30, 30, -30, 30, -30, 30, -30, 30, -30, 30, -30, 29, -29 // 0x00004080
|
||||
, 29, -29, 29, -29, 29, -29, 29, -29, 29, -29, 29, -29, 29, -29, 29, -29 // 0x000040C0
|
||||
, 29, -29, 29, -29, 29, -29, 29, -29, 28, -28, 28, -28, 28, -28, 28, -28 // 0x00004100
|
||||
, 28, -28, 28, -28, 28, -28, 28, -28, 28, -28, 28, -28, 28, -28, 28, -28 // 0x00004140
|
||||
, 28, -28, 27, -27, 27, -27, 27, -27, 27, -27, 27, -27, 27, -27, 27, -27 // 0x00004180
|
||||
, 27, -27, 27, -27, 27, -27, 27, -27, 27, -27, 27, -27, 26, -26, 26, -26 // 0x000041C0
|
||||
, 26, -26, 26, -26, 26, -26, 26, -26, 26, -26, 26, -26, 26, -26, 26, -26 // 0x00004200
|
||||
, 26, -26, 26, -26, 26, -26, 26, -26, 25, -25, 25, -25, 25, -25, 25, -25 // 0x00004240
|
||||
, 25, -25, 25, -25, 25, -25, 25, -25, 25, -25, 25, -25, 25, -25, 25, -25 // 0x00004280
|
||||
, 25, -25, 25, -25, 25, -25, 24, -24, 24, -24, 24, -24, 24, -24, 24, -24 // 0x000042C0
|
||||
, 24, -24, 24, -24, 24, -24, 24, -24, 24, -24, 24, -24, 24, -24, 24, -24 // 0x00004300
|
||||
, 24, -24, 24, -24, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23 // 0x00004340
|
||||
, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23, 23, -23 // 0x00004380
|
||||
, 23, -23, 23, -23, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22 // 0x000043C0
|
||||
, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22, 22, -22 // 0x00004400
|
||||
, 22, -22, 22, -22, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21 // 0x00004440
|
||||
, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21, 21, -21 // 0x00004480
|
||||
, 21, -21, 21, -21, 21, -21, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20 // 0x000044C0
|
||||
, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20 // 0x00004500
|
||||
, 20, -20, 20, -20, 20, -20, 20, -20, 20, -20, 19, -19, 19, -19, 19, -19 // 0x00004540
|
||||
, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19 // 0x00004580
|
||||
, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19, 19, -19 // 0x000045C0
|
||||
, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18 // 0x00004600
|
||||
, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18, 18, -18 // 0x00004640
|
||||
, 18, -18, 18, -18, 18, -18, 18, -18, 17, -17, 17, -17, 17, -17, 17, -17 // 0x00004680
|
||||
, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17 // 0x000046C0
|
||||
, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17, 17, -17 // 0x00004700
|
||||
, 17, -17, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16 // 0x00004740
|
||||
, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16 // 0x00004780
|
||||
, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16 // 0x000047C0
|
||||
, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15 // 0x00004800
|
||||
, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15 // 0x00004840
|
||||
, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 15, -15, 14, -14 // 0x00004880
|
||||
, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14 // 0x000048C0
|
||||
, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14 // 0x00004900
|
||||
, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14, 14, -14 // 0x00004940
|
||||
, 14, -14, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13 // 0x00004980
|
||||
, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13 // 0x000049C0
|
||||
, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13, 13, -13 // 0x00004A00
|
||||
, 13, -13, 13, -13, 13, -13, 13, -13, 12, -12, 12, -12, 12, -12, 12, -12 // 0x00004A40
|
||||
, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12 // 0x00004A80
|
||||
, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12 // 0x00004AC0
|
||||
, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12, 12, -12 // 0x00004B00
|
||||
, 12, -12, 12, -12, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11 // 0x00004B40
|
||||
, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11 // 0x00004B80
|
||||
, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11 // 0x00004BC0
|
||||
, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11, 11, -11 // 0x00004C00
|
||||
, 11, -11, 11, -11, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10 // 0x00004C40
|
||||
, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10 // 0x00004C80
|
||||
, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10 // 0x00004CC0
|
||||
, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10 // 0x00004D00
|
||||
, 10, -10, 10, -10, 10, -10, 10, -10, 10, -10, 9, -9, 9, -9, 9, -9 // 0x00004D40
|
||||
, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9 // 0x00004D80
|
||||
, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9 // 0x00004DC0
|
||||
, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9 // 0x00004E00
|
||||
, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9, 9, -9 // 0x00004E40
|
||||
, 9, -9, 9, -9, 9, -9, 9, -9, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004E80
|
||||
, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004EC0
|
||||
, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004F00
|
||||
, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004F40
|
||||
, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004F80
|
||||
, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8 // 0x00004FC0
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x00005000
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x00005040
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x00005080
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x000050C0
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x00005100
|
||||
, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7, 7, -7 // 0x00005140
|
||||
, 7, -7, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x00005180
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x000051C0
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x00005200
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x00005240
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x00005280
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x000052C0
|
||||
, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6, 6, -6 // 0x00005300
|
||||
, 6, -6, 6, -6, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005340
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005380
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x000053C0
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005400
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005440
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005480
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x000054C0
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5 // 0x00005500
|
||||
, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4 // 0x00005540
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005580
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x000055C0
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005600
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005640
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005680
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x000056C0
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005700
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005740
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x00005780
|
||||
, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4 // 0x000057C0
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005800
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005840
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005880
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x000058C0
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005900
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005940
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005980
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x000059C0
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005A00
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005A40
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005A80
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005AC0
|
||||
, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3, 3, -3 // 0x00005B00
|
||||
, 3, -3, 3, -3, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005B40
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005B80
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005BC0
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005C00
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005C40
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005C80
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005CC0
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005D00
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005D40
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005D80
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005DC0
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005E00
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005E40
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005E80
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005EC0
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005F00
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005F40
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005F80
|
||||
, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 2, -2 // 0x00005FC0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006000
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006040
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006080
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000060C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006100
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006140
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006180
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000061C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006200
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006240
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006280
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000062C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006300
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006340
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006380
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000063C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006400
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006440
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006480
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000064C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006500
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006540
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006580
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000065C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006600
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006640
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006680
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x000066C0
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006700
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006740
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 // 0x00006780
|
||||
, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
**
|
||||
** software implementation of Yamaha FM sound generator (YM2612/YM3438)
|
||||
**
|
||||
** Original code (MAME fm.c)
|
||||
**
|
||||
** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
|
||||
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
|
||||
**
|
||||
** Version 1.4 (final beta)
|
||||
**
|
||||
** Additional code & fixes by Eke-Eke for Genesis Plus GX
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef _H_YM2612_
|
||||
#define _H_YM2612_
|
||||
|
||||
extern int16_t gwenesis_sn76489_buffer[];
|
||||
///extern int ym2612_index;
|
||||
///extern int ym2612_clock;
|
||||
|
||||
extern int snd_output_volume;
|
||||
|
||||
extern void YM2612Init();
|
||||
extern void YM2612Config(unsigned char dac_bits); //,unsigned int AUDIO_FREQ_DIVISOR);
|
||||
extern void YM2612ResetChip(void);
|
||||
//extern void YM2612Update(int16_t *buffer, int length);
|
||||
extern void YM2612Write(unsigned int a, unsigned int v, int target);
|
||||
extern void ym2612_run(int target);
|
||||
extern unsigned int YM2612Read(int target);
|
||||
|
||||
#if 0
|
||||
extern int YM2612LoadContext(unsigned char *state);
|
||||
extern int YM2612SaveContext(unsigned char *state);
|
||||
#endif
|
||||
|
||||
//extern void YM2612LoadRegs(uint8_t *regs);
|
||||
//extern void YM2612SaveRegs(uint8_t *regs);
|
||||
|
||||
void gwenesis_ym2612_save_state();
|
||||
void gwenesis_ym2612_load_state();
|
||||
|
||||
#endif /* _YM2612_ */
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
const unsigned int __in_flash() __aligned(4) ym2612_OPN_ST_dt_tab[8][32] = {
|
||||
// freqbase: 6.000000
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 384, 384, 384, 384, 384, 384, 384, 384, 768, 768, 768, 768, 768, 1152, 1152, 1152, 1536, 1536, 1536, 1920, 1920, 2304, 2304, 2688, 3072, 3072, 3072, 3072 },
|
||||
{ 384, 384, 384, 384, 768, 768, 768, 768, 768, 1152, 1152, 1152, 1536, 1536, 1536, 1920, 1920, 2304, 2304, 2688, 3072, 3072, 3456, 3840, 4224, 4608, 4992, 5376, 6144, 6144, 6144, 6144 },
|
||||
{ 768, 768, 768, 768, 768, 1152, 1152, 1152, 1536, 1536, 1536, 1920, 1920, 2304, 2304, 2688, 3072, 3072, 3456, 3840, 4224, 4608, 4992, 5376, 6144, 6528, 7296, 7680, 8448, 8448, 8448, 8448 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, -384, -384, -384, -384, -384, -384, -384, -384, -768, -768, -768, -768, -768, -1152, -1152, -1152, -1536, -1536, -1536, -1920, -1920, -2304, -2304, -2688, -3072, -3072, -3072, -3072 },
|
||||
{ -384, -384, -384, -384, -768, -768, -768, -768, -768, -1152, -1152, -1152, -1536, -1536, -1536, -1920, -1920, -2304, -2304, -2688, -3072, -3072, -3456, -3840, -4224, -4608, -4992, -5376, -6144, -6144, -6144, -6144 },
|
||||
{ -768, -768, -768, -768, -768, -1152, -1152, -1152, -1536, -1536, -1536, -1920, -1920, -2304, -2304, -2688, -3072, -3072, -3456, -3840, -4224, -4608, -4992, -5376, -6144, -6528, -7296, -7680, -8448, -8448, -8448, -8448 }
|
||||
};
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "../cpus/Z80/Z80.h"
|
||||
#include "z80inst.h"
|
||||
#include "../cpus/M68K/m68k.h"
|
||||
#include "../bus/gwenesis_bus.h"
|
||||
// #include "ym2612.h"
|
||||
#include "gwenesis_sn76489.h"
|
||||
#include "ym2612.h"
|
||||
#include "../savestate/gwenesis_savestate.h"
|
||||
|
||||
static int bus_ack = 0;
|
||||
static int reset = 0;
|
||||
static int reset_once = 0;
|
||||
int zclk = 0;
|
||||
static int initialized = 0;
|
||||
|
||||
extern int audio_enabled;
|
||||
extern bool sound_enabled;
|
||||
|
||||
unsigned char *Z80_RAM;
|
||||
|
||||
static Z80 cpu;
|
||||
|
||||
void ResetZ80(register Z80 *R);
|
||||
|
||||
#define Z80_INST_DISABLE_LOGGING 1
|
||||
|
||||
#if !Z80_INST_DISABLE_LOGGING
|
||||
#include <stdarg.h>
|
||||
void z80_log(const char *subs, const char *fmt, ...) {
|
||||
extern int frame_counter;
|
||||
extern int scan_line;
|
||||
|
||||
va_list va;
|
||||
|
||||
printf("%06d:%03d :[%s]", frame_counter, scan_line, subs);
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stdout, fmt, va);
|
||||
va_end(va);
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
#define z80_log(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
// Bank register used by Z80 to access M68K Memory space 1 BANK=32KByte
|
||||
int Z80_BANK;
|
||||
|
||||
|
||||
void z80_start() {
|
||||
cpu.IPeriod = 1;
|
||||
cpu.ICount = 0;
|
||||
cpu.Trace = 0;
|
||||
cpu.Trap = 0x0009;
|
||||
ResetZ80(&cpu);
|
||||
reset=1;
|
||||
reset_once=0;
|
||||
bus_ack=0;
|
||||
zclk=0;
|
||||
}
|
||||
|
||||
void z80_pulse_reset() {
|
||||
ResetZ80(&cpu);
|
||||
}
|
||||
static int current_timeslice = 0;
|
||||
|
||||
void z80_run(int target) {
|
||||
|
||||
// we are in advance,nothind to do
|
||||
current_timeslice = 0;
|
||||
if (zclk >= target) {
|
||||
// z80_log("z80_skip time","%1d%1d%1d||zclk=%d,tgt=%d",reset_once,bus_ack,reset, zclk, target);
|
||||
return;
|
||||
}
|
||||
|
||||
current_timeslice = target - zclk;
|
||||
|
||||
int rem = 0;
|
||||
if ((reset_once == 1) && (bus_ack == 0) && (reset == 0)) {
|
||||
|
||||
// z80_log("z80_run", "%1d%1d%1d||zclk=%d,tgt=%d",reset_once, bus_ack, reset, zclk, target);
|
||||
rem = ExecZ80(&cpu, current_timeslice / Z80_FREQ_DIVISOR);
|
||||
|
||||
}
|
||||
|
||||
zclk = target - rem * Z80_FREQ_DIVISOR;
|
||||
}
|
||||
|
||||
void z80_sync(void) {
|
||||
/*
|
||||
get M68K cycles
|
||||
Execute cycles on z80 to sync with m68K
|
||||
*/
|
||||
|
||||
z80_run(m68k_cycles_master());
|
||||
}
|
||||
|
||||
void z80_set_memory(unsigned char *buffer)
|
||||
{
|
||||
Z80_RAM = buffer;
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
void z80_write_ctrl(unsigned int address, unsigned int value) {
|
||||
z80_sync();
|
||||
|
||||
if (address == 0x1100) // BUSREQ
|
||||
{
|
||||
z80_log(__FUNCTION__,"BUSREQ = %d, current=%d", value,bus_ack);
|
||||
|
||||
// Bus request. Z80 bus on hold.
|
||||
if (value) {
|
||||
bus_ack = 1;
|
||||
|
||||
|
||||
// Bus request cancel. Z80 runs.
|
||||
} else {
|
||||
bus_ack = 0;
|
||||
}
|
||||
|
||||
} else if (address == 0x1200) // RESET
|
||||
{
|
||||
z80_log(__FUNCTION__,"RESET = %d, current=%d", value,reset);
|
||||
|
||||
if (value == 0) {
|
||||
reset = 1;
|
||||
} else {
|
||||
|
||||
z80_pulse_reset();
|
||||
reset = 0;
|
||||
reset_once = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int z80_read_ctrl(unsigned int address) {
|
||||
|
||||
z80_sync();
|
||||
|
||||
if (address == 0x1100) {
|
||||
|
||||
z80_log(__FUNCTION__,"RUNNING = %d ", bus_ack ? 0 : 1);
|
||||
return bus_ack == 1 ? 0 : 1;
|
||||
|
||||
} else if (address == 0x1101) {
|
||||
return 0x00;
|
||||
|
||||
} else if (address == 0x1200) {
|
||||
|
||||
z80_log(__FUNCTION__,"RESET = %d ", reset );
|
||||
return reset;
|
||||
|
||||
} else if (address == 0x1201) {
|
||||
return 0x00;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void z80_irq_line(unsigned int value)
|
||||
{
|
||||
if (reset_once == 0) return;
|
||||
|
||||
if (value)
|
||||
cpu.IRequest = INT_IRQ;
|
||||
else
|
||||
cpu.IRequest = INT_NONE;
|
||||
|
||||
z80_log(__FUNCTION__,"Interrupt = %d ", value);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
word z80_get_reg(int reg_i) {
|
||||
switch(reg_i) {
|
||||
case 0: return cpu.AF.W; break;
|
||||
case 1: return cpu.BC.W; break;
|
||||
case 2: return cpu.DE.W; break;
|
||||
case 3: return cpu.HL.W; break;
|
||||
case 4: return cpu.IX.W; break;
|
||||
case 5: return cpu.IY.W; break;
|
||||
case 6: return cpu.PC.W; break;
|
||||
case 7: return cpu.SP.W; break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************
|
||||
* Z80 Bank
|
||||
********************************************/
|
||||
|
||||
unsigned int zbankreg_mem_r8(unsigned int address)
|
||||
{
|
||||
z80_log(__FUNCTION__,"Z80 bank read pointer : %06x", Z80_BANK);
|
||||
|
||||
return Z80_BANK;
|
||||
}
|
||||
|
||||
static inline void zbankreg_mem_w8(unsigned int value) {
|
||||
Z80_BANK >>= 1;
|
||||
Z80_BANK |= (value & 1) << 8;
|
||||
z80_log(__FUNCTION__,"Z80 bank points to: %06x", Z80_BANK << 15);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline unsigned int zbank_mem_r8(unsigned int address)
|
||||
{
|
||||
address &= 0x7FFF;
|
||||
address |= (Z80_BANK << 15);
|
||||
|
||||
z80_log(__FUNCTION__,"Z80 bank read: %06x", address);
|
||||
return m68k_read_memory_8(address);
|
||||
}
|
||||
|
||||
static inline void zbank_mem_w8(unsigned int address, unsigned int value) {
|
||||
address &= 0x7FFF;
|
||||
address |= (Z80_BANK << 15);
|
||||
|
||||
z80_log(__FUNCTION__,"Z80 bank write %06x: %02x", address, value);
|
||||
m68k_write_memory_8(address, value);
|
||||
|
||||
}
|
||||
|
||||
// TODO ??
|
||||
/*
|
||||
unsigned int zvdp_mem_r8(unsigned int address)
|
||||
{
|
||||
if (address >= 0x7F00 && address < 0x7F20)
|
||||
return vdp_mem_r8(address);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void zvdp_mem_w8(unsigned int address, unsigned int value)
|
||||
{
|
||||
if (address >= 0x7F00 && address < 0x7F20)
|
||||
vdp_mem_w8(address, value);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
word LoopZ80(register Z80 *R)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte RdZ80(register word Addr) {
|
||||
|
||||
if (Addr < 0x4000)
|
||||
return Z80_RAM[Addr & 0x1FFF];
|
||||
|
||||
if (Addr < 0x6000)
|
||||
return (audio_enabled) ? YM2612Read(zclk + current_timeslice - (cpu.ICount * Z80_FREQ_DIVISOR)) : 0x00;
|
||||
|
||||
z80_log(__FUNCTION__, "addr= %x", Addr);
|
||||
|
||||
if (Addr >= 0x8000)
|
||||
return zbank_mem_r8(Addr);
|
||||
|
||||
z80_log(__FUNCTION__, "addr= %x", Addr);
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
extern int system_clock;
|
||||
|
||||
void WrZ80(register word Addr, register byte Value) {
|
||||
|
||||
// ZRAM & mirror
|
||||
if (Addr < 0x4000) {
|
||||
Z80_RAM[Addr&0x1FFF] = Value;
|
||||
return;
|
||||
}
|
||||
|
||||
// @4000-4003
|
||||
if (Addr < 0x6000) {
|
||||
z80_log("Z80","ZZYM(%x,%x) zk=%d,tgt=%d",Addr&0x3,Value, zclk, zclk + current_timeslice -(cpu.ICount * Z80_FREQ_DIVISOR) );
|
||||
if (audio_enabled)
|
||||
YM2612Write(Addr&0x3, Value, zclk + current_timeslice -(cpu.ICount * Z80_FREQ_DIVISOR) );
|
||||
return;
|
||||
}
|
||||
|
||||
// @6000
|
||||
if (Addr == 0x6000) {
|
||||
zbankreg_mem_w8(Value);
|
||||
return;
|
||||
}
|
||||
|
||||
// @7F11
|
||||
if (Addr == 0x7F11) {
|
||||
z80_log("Z80","ZZSN zk=%d,tgt=%d", zclk, zclk + current_timeslice -(cpu.ICount * Z80_FREQ_DIVISOR) );
|
||||
gwenesis_SN76489_Write(Value,zclk + current_timeslice -(cpu.ICount * Z80_FREQ_DIVISOR) );
|
||||
return;
|
||||
}
|
||||
|
||||
z80_log("Z80","WrZ80 %x %x", Addr, Value);
|
||||
|
||||
if (Addr >= 0x8000) {
|
||||
zbank_mem_w8(Addr, Value);
|
||||
return;
|
||||
}
|
||||
z80_log("Z80","WrZ80 %x %x", Addr, Value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
byte InZ80(register word Port) {return 0;}
|
||||
void OutZ80(register word Port, register byte Value) {;}
|
||||
void PatchZ80(register Z80 *R) {;}
|
||||
void DebugZ80(register Z80 *R) {;}
|
||||
|
||||
void gwenesis_z80inst_save_state() {
|
||||
|
||||
}
|
||||
|
||||
void gwenesis_z80inst_load_state() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#ifndef _Z80_INTERFACE_H_
|
||||
#define _Z80_INTERFACE_H_
|
||||
|
||||
void z80_write_ctrl(unsigned int address, unsigned int value);
|
||||
unsigned int z80_read_ctrl(unsigned int address);
|
||||
void z80_start();
|
||||
void z80_pulse_reset();
|
||||
void z80_execute(unsigned int target);
|
||||
void z80_run(int target);
|
||||
extern int zclk;
|
||||
|
||||
void gwenesis_z80inst_save_state();
|
||||
void gwenesis_z80inst_load_state();
|
||||
|
||||
void z80_set_memory(unsigned char *buffer);
|
||||
|
||||
void z80_write_memory_8(unsigned int address, unsigned int value);
|
||||
void z80_write_memory_16(unsigned int address, unsigned int value);
|
||||
unsigned int z80_read_memory_16(unsigned int address);
|
||||
unsigned int z80_read_memory_8(unsigned int address);
|
||||
void z80_irq_line(unsigned int value);
|
||||
|
||||
void gwenesis_z80inst_save_state();
|
||||
void gwenesis_z80inst_load_state();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
#ifndef _gwenesis_vdp_H_
|
||||
#define _gwenesis_vdp_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#define BIT(v, idx) (((v) >> (idx)) & 1)
|
||||
#define BITS(v, idx, n) (((v) >> (idx)) & ((1 << (n)) - 1))
|
||||
|
||||
// VDP registers
|
||||
#define REG0_DISABLE_DISPLAY (gwenesis_vdp_regs[0] & 1)
|
||||
#define REG0_HVLATCH BIT(gwenesis_vdp_regs[0], 1)
|
||||
#define REG0_LINE_INTERRUPT BIT(gwenesis_vdp_regs[0], 4)
|
||||
#define REG1_PAL BIT(gwenesis_vdp_regs[1], 3)
|
||||
#define REG1_240_LINE ((gwenesis_vdp_regs[1] & 0x08) >> 3)
|
||||
#define REG1_DMA_ENABLED BIT(gwenesis_vdp_regs[1], 4)
|
||||
#define REG1_VBLANK_INTERRUPT BIT(gwenesis_vdp_regs[1], 5)
|
||||
#define REG1_DISP_ENABLED BIT(gwenesis_vdp_regs[1], 6)
|
||||
#define REG2_NAMETABLE_A (BITS(gwenesis_vdp_regs[2], 3, 3) << 13)
|
||||
#define REG3_NAMETABLE_W BITS(gwenesis_vdp_regs[3], 1, 5)
|
||||
#define REG4_NAMETABLE_B (BITS(gwenesis_vdp_regs[4], 0, 3) << 13)
|
||||
//#define REG5_SAT_ADDRESS ((gwenesis_vdp_regs[5] & (mode_h40 ? 0x7E : 0x7F)) << 9)
|
||||
//#define REG5_SAT_SIZE (mode_h40 ? (1 << 10) : (1 << 9))
|
||||
#define REG5_SAT_ADDRESS ((gwenesis_vdp_regs[5] & ((gwenesis_vdp_regs[12] & 0x01) ? 0x7E : 0x7F)) << 9)
|
||||
#define REG5_SAT_SIZE ((gwenesis_vdp_regs[12] & 0x01) ? (1 << 10) : (1 << 9))
|
||||
#define REG10_LINE_COUNTER BITS(gwenesis_vdp_regs[10], 0, 8)
|
||||
#define REG10_COLUMN_COUNTER BITS(gwenesis_vdp_regs[10], 8, 15)
|
||||
#define REG11_HSCROLL_MODE ((gwenesis_vdp_regs[11] & 3))
|
||||
#define REG11_VSCROLL_MODE ((gwenesis_vdp_regs[11] & 4) >> 2)
|
||||
#define REG12_RS0 (gwenesis_vdp_regs[12] & 0x80) >> 7
|
||||
#define REG12_RS1 (gwenesis_vdp_regs[12] & 0x01) >> 0
|
||||
#define REG12_MODE_H40 (gwenesis_vdp_regs[12] & 1)
|
||||
#define REG13_HSCROLL_ADDRESS (gwenesis_vdp_regs[13] << 10)
|
||||
#define REG15_DMA_INCREMENT gwenesis_vdp_regs[15]
|
||||
#define REG16_UNUSED1 ((gwenesis_vdp_regs[16] & 0xc0) >> 6)
|
||||
#define REG16_VSCROLL_SIZE ((gwenesis_vdp_regs[16] >> 4) & 3)
|
||||
#define REG16_UNUSED2 ((gwenesis_vdp_regs[16] & 0x0c) >> 2)
|
||||
#define REG16_HSCROLL_SIZE (gwenesis_vdp_regs[16] & 3)
|
||||
#define REG17_WINDOW_HPOS BITS(gwenesis_vdp_regs[17], 0, 5)
|
||||
#define REG17_WINDOW_RIGHT ((gwenesis_vdp_regs[17] & 0x80) >> 7)
|
||||
#define REG18_WINDOW_DOWN ((gwenesis_vdp_regs[0x12] & 0x80) >> 7)
|
||||
#define REG18_WINDOW_VPOS BITS(gwenesis_vdp_regs[18], 0, 5)
|
||||
#define REG19_DMA_LENGTH (gwenesis_vdp_regs[19] | (gwenesis_vdp_regs[20] << 8))
|
||||
#define REG21_DMA_SRCADDR_LOW (gwenesis_vdp_regs[21] | (gwenesis_vdp_regs[22] << 8))
|
||||
#define REG23_DMA_SRCADDR_HIGH ((gwenesis_vdp_regs[23] & 0x7F) << 16)
|
||||
#define REG23_DMA_TYPE BITS(gwenesis_vdp_regs[23], 6, 2)
|
||||
|
||||
//VDP status register
|
||||
#define STATUS_FIFO_EMPTY (1 << 9)
|
||||
#define STATUS_FIFO_FULL (1 << 8)
|
||||
#define STATUS_VIRQPENDING (1 << 7)
|
||||
#define STATUS_SPRITEOVERFLOW (1 << 6)
|
||||
#define STATUS_SPRITECOLLISION (1 << 5)
|
||||
#define STATUS_ODDFRAME (1 << 4)
|
||||
#define STATUS_VBLANK (1 << 3)
|
||||
#define STATUS_HBLANK (1 << 2)
|
||||
#define STATUS_DMAPROGRESS (1 << 1)
|
||||
#define STATUS_PAL (1 << 0)
|
||||
|
||||
#define VRAM_MAX_SIZE 0x10000 // VRAM maximum size
|
||||
#define CRAM_MAX_SIZE 0x40 // CRAM maximum size
|
||||
#define VSRAM_MAX_SIZE 0x40 // VSRAM maximum size
|
||||
#define SAT_CACHE_MAX_SIZE 0x400 // SAT CACHE maximum size
|
||||
#define REG_SIZE 0x20 // REGISTERS total
|
||||
#define FIFO_SIZE 0x4 // FIFO maximum size
|
||||
|
||||
#define COLOR_3B_TO_8B(c) (((c) << 5) | ((c) << 2) | ((c) >> 1))
|
||||
#define CRAM_R(c) COLOR_3B_TO_8B(BITS((c), 1, 3))
|
||||
#define CRAM_G(c) COLOR_3B_TO_8B(BITS((c), 5, 3))
|
||||
#define CRAM_B(c) COLOR_3B_TO_8B(BITS((c), 9, 3))
|
||||
|
||||
#define MODE_SHI BITS(gwenesis_vdp_regs[12], 3, 1)
|
||||
|
||||
#define SHADOW_COLOR(r,g,b) \
|
||||
do { r >>= 1; g >>= 1; b >>= 1; } while (0)
|
||||
#define HIGHLIGHT_COLOR(r,g,b) \
|
||||
do { SHADOW_COLOR(r,g,b); r |= 0x80; g |= 0x80; b |= 0x80; } while(0)
|
||||
|
||||
// While we draw the planes, we use bit 0x80 on each pixel to save the
|
||||
// high-priority flag, so that we can later prioritize.
|
||||
#define PIXATTR_HIPRI 0x80
|
||||
#define PIXATTR_LOWPRI 0x00
|
||||
#define PIXATTR_SPRITE 0x40
|
||||
#define PIXATTR_SPRITE_HIPRI 0xC0
|
||||
|
||||
|
||||
// After mixing code, we use free bits 0x80 and 0x40 to indicate the
|
||||
// shadow/highlight effect to apply on each pixel. Notice that we use
|
||||
// 0x80 to indicate normal drawing and 0x00 to indicate shadowing,
|
||||
// which does match exactly the semantic of PIXATTR_HIPRI. This simplifies
|
||||
// mixing code quite a bit.
|
||||
#define SHI_NORMAL(x) ((x) | 0x80)
|
||||
#define SHI_HIGHLIGHT(x) ((x) | 0x40)
|
||||
#define SHI_SHADOW(x) ((x) & 0x3F)
|
||||
|
||||
#define SHI_IS_SHADOW(x) (!((x) & 0x80))
|
||||
#define SHI_IS_HIGHLIGHT(x) ((x) & 0x40)
|
||||
|
||||
void gwenesis_vdp_reset();
|
||||
void gwenesis_vdp_set_hblank();
|
||||
void gwenesis_vdp_clear_hblank();
|
||||
void gwenesis_vdp_set_vblank();
|
||||
void gwenesis_vdp_clear_vblank();
|
||||
|
||||
unsigned int gwenesis_vdp_get_reg(int reg);
|
||||
void gwenesis_vdp_set_reg(int reg, unsigned char value);
|
||||
|
||||
unsigned int gwenesis_vdp_read_memory_8(unsigned int address);
|
||||
unsigned int gwenesis_vdp_read_memory_16(unsigned int address);
|
||||
|
||||
void gwenesis_vdp_write_memory_8(unsigned int address, unsigned int value);
|
||||
void gwenesis_vdp_write_memory_16(unsigned int address, unsigned int value);
|
||||
|
||||
void gwenesis_vdp_set_buffers(unsigned char *screen_buffer, unsigned char *scaled_buffer);
|
||||
void gwenesis_vdp_set_buffer(uint8_t *ptr_screen_buffer);
|
||||
void gwenesis_vdp_get_buffer(uint16_t** ptr_screen_buffer);
|
||||
void gwenesis_vdp_render_line(int line);
|
||||
|
||||
void gwenesis_vdp_render_config();
|
||||
|
||||
unsigned int gwenesis_vdp_get_status();
|
||||
void gwenesis_vdp_get_debug_status(char *s);
|
||||
unsigned short gwenesis_vdp_get_cram(int index);
|
||||
void gwenesis_vdp_get_vram(unsigned char *raw_buffer, int palette);
|
||||
void gwenesis_vdp_get_vram_raw(unsigned char *raw_buffer);
|
||||
void gwenesis_vdp_get_cram_raw(unsigned char *raw_buffer);
|
||||
|
||||
int gwenesis_vdp_vcounter();
|
||||
int gwenesis_vdp_hcounter();
|
||||
unsigned short gwenesis_vdp_hvcounter();
|
||||
|
||||
void gwenesis_vdp_gfx_save_state();
|
||||
void gwenesis_vdp_gfx_load_state();
|
||||
void gwenesis_vdp_mem_save_state();
|
||||
void gwenesis_vdp_mem_load_state();
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,914 +0,0 @@
|
|||
/*
|
||||
Gwenesis : Genesis & megadrive Emulator.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = "bzhxx"
|
||||
__contact__ = "https://github.com/bzhxx"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "../cpus/M68K/m68k.h"
|
||||
#include "gwenesis_vdp.h"
|
||||
#include "../io/gwenesis_io.h"
|
||||
#include "../bus/gwenesis_bus.h"
|
||||
#include "../savestate/gwenesis_savestate.h"
|
||||
|
||||
#include <assert.h>
|
||||
//#include <graphics.h>
|
||||
#include <gwenesis/sound/gwenesis_sn76489.h>
|
||||
|
||||
#include "pico.h"
|
||||
#pragma GCC optimize("Ofast")
|
||||
|
||||
|
||||
extern void emu_DrawLine16(unsigned short *src, int width , int height, int line);
|
||||
extern void emu_DrawLinePal16(unsigned char * VBuf, int width, int height, int line);
|
||||
extern void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index);
|
||||
|
||||
|
||||
#define VDP_MEM_DISABLE_LOGGING 1
|
||||
|
||||
#if !VDP_MEM_DISABLE_LOGGING
|
||||
#include <stdarg.h>
|
||||
void vdpm_log(const char *subs, const char *fmt, ...) {
|
||||
extern int frame_counter;
|
||||
extern int scan_line;
|
||||
|
||||
va_list va;
|
||||
|
||||
printf("%06d:%03d :[%s] vc:%04x hc:%04x hv:%04x ", frame_counter, scan_line, subs,gwenesis_vdp_vcounter(),gwenesis_vdp_hcounter(),gwenesis_vdp_hvcounter());
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stdout, fmt, va);
|
||||
va_end(va);
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
#define vdpm_log(...)
|
||||
#endif
|
||||
|
||||
//#define _DMA_TRACE_
|
||||
|
||||
/* Setup VDP Memories */
|
||||
|
||||
//extern uint8_t emulator_framebuffer[1024*64];
|
||||
//unsigned char* VRAM = &emulator_framebuffer[0];
|
||||
unsigned char VRAM[VRAM_MAX_SIZE];
|
||||
//unsigned char* VRAM = NULL;
|
||||
|
||||
unsigned short CRAM[CRAM_MAX_SIZE]; // CRAM - Palettes
|
||||
unsigned char SAT_CACHE[SAT_CACHE_MAX_SIZE]; // Sprite cache
|
||||
unsigned char gwenesis_vdp_regs[REG_SIZE]; // Registers
|
||||
unsigned short fifo[FIFO_SIZE]; // Fifo
|
||||
//uint8_t CRAM222[CRAM_MAX_SIZE * 4]; // CRAM - Palettes
|
||||
unsigned short VSRAM[VSRAM_MAX_SIZE]; // VSRAM - Scrolling
|
||||
|
||||
// Define VDP control code and set initial code
|
||||
static unsigned char code_reg = 0;
|
||||
// Define VDP control address and set initial address
|
||||
static unsigned short address_reg = 0;
|
||||
// Define VDP control pending and set initial state
|
||||
int command_word_pending = 0;
|
||||
// Define VDP status and set initial status value
|
||||
unsigned short gwenesis_vdp_status = 0x3C00;
|
||||
|
||||
extern int scan_line;
|
||||
extern bool sn76489_enabled;
|
||||
extern bool audio_enabled;
|
||||
// Define DMA
|
||||
//static unsigned int dma_length;
|
||||
//static unsigned int dma_source;
|
||||
// Define and set DMA FILL pending as initial state
|
||||
int dma_fill_pending = 0;
|
||||
|
||||
// Define HVCounter latch and set initial state
|
||||
static int hvcounter_latch = 0;
|
||||
static int hvcounter_latched = 0;
|
||||
|
||||
int hint_pending;
|
||||
|
||||
|
||||
// Define VIDEO MODE
|
||||
extern int mode_pal;
|
||||
|
||||
extern int sprite_overflow;
|
||||
extern bool sprite_collision;
|
||||
|
||||
// Store last address r/w
|
||||
//static unsigned int gwenesis_vdp_laddress_r=0;
|
||||
//unsigned int gwenesis_vdp_laddress_w=0;
|
||||
|
||||
//static int DMA_RUN=0;
|
||||
|
||||
// 16 bits access to VRAM
|
||||
#define FETCH16(A) ( ( (*(unsigned short *)&VRAM[(A)]) >> 8 ) | ( (*(unsigned short *)&VRAM[(A)]) << 8 ) )
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 Reset
|
||||
* Clear all volatile memory
|
||||
*
|
||||
******************************************************************************/
|
||||
int m68k_irq_acked(int irq) {
|
||||
/* VINT has higher priority (Fatal Rewind) */
|
||||
if (REG1_VBLANK_INTERRUPT && (gwenesis_vdp_status & STATUS_VIRQPENDING)) {
|
||||
/* Clear VINT pending flag */
|
||||
gwenesis_vdp_status &= ~STATUS_VIRQPENDING;
|
||||
|
||||
if (hint_pending && REG0_LINE_INTERRUPT)
|
||||
m68k_set_irq(4);
|
||||
else
|
||||
m68k_set_irq(0);
|
||||
}
|
||||
else {
|
||||
/* Clear HINT pending flag */
|
||||
hint_pending = 0;
|
||||
|
||||
/* Update IRQ status */
|
||||
m68k_set_irq(0);
|
||||
}
|
||||
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
|
||||
void gwenesis_vdp_reset() {
|
||||
memset(VRAM, 0, VRAM_MAX_SIZE);
|
||||
memset(SAT_CACHE, 0, sizeof(SAT_CACHE));
|
||||
memset(CRAM, 0, sizeof(CRAM));
|
||||
// memset(CRAM222, 0, sizeof(CRAM222));
|
||||
memset(VSRAM, 0, sizeof(VSRAM));
|
||||
memset(gwenesis_vdp_regs, 0, sizeof(gwenesis_vdp_regs));
|
||||
command_word_pending = 0;
|
||||
address_reg = 0;
|
||||
code_reg = 0;
|
||||
hint_pending = 0;
|
||||
// _vcounter = 0;
|
||||
gwenesis_vdp_status = 0x3C00;
|
||||
// //line_counter_interrupt = 0;
|
||||
hvcounter_latched = 0;
|
||||
|
||||
// register the M68K interrupt
|
||||
m68k_set_int_ack_callback(m68k_irq_acked);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 HCOUNTER
|
||||
* Process SEGA 315-5313 HCOUNTER based on M68K Cycles
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline __attribute__((always_inline))
|
||||
int gwenesis_vdp_hcounter() {
|
||||
int mclk = m68k_cycles_run();
|
||||
int pixclk;
|
||||
|
||||
// Accurate 9-bit hcounter emulation, from timing posted here:
|
||||
// http://gendev.spritesmind.net/forum/viewtopic.php?p=17683#17683
|
||||
if (REG12_MODE_H40) {
|
||||
pixclk = mclk * 420 / VDP_CYCLES_PER_LINE;
|
||||
pixclk += 0xD;
|
||||
if (pixclk >= 0x16D)
|
||||
pixclk += 0x1C9 - 0x16D;
|
||||
}
|
||||
else {
|
||||
pixclk = mclk * 342 / VDP_CYCLES_PER_LINE;
|
||||
pixclk += 0xB;
|
||||
if (pixclk >= 0x128)
|
||||
pixclk += 0x1D2 - 0x128;
|
||||
}
|
||||
|
||||
return pixclk & 0x1FF;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 VCOUNTER
|
||||
* Process SEGA 315-5313 VCOUNTER based on M68K Cycles
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline __attribute__((always_inline))
|
||||
int gwenesis_vdp_vcounter() {
|
||||
int vc = scan_line;
|
||||
int VERSION_PAL = gwenesis_vdp_status & 1;
|
||||
|
||||
/*
|
||||
if (VERSION_PAL && mode_pal && (vc >= 0x10B))
|
||||
vc += 0x1D2 - 0x10B;
|
||||
else if (VERSION_PAL && (mode_pal==0) && (vc >= 0x103))
|
||||
vc += 0x1CA - 0x103;
|
||||
else if ((VERSION_PAL ==0 ) && (vc >= 0xEB))
|
||||
vc += 0x1E5 - 0xEB;
|
||||
assert(vc < 0x200);
|
||||
*/
|
||||
if (VERSION_PAL && mode_pal && (vc >= 267))
|
||||
vc = scan_line - 58;
|
||||
else if (VERSION_PAL && (mode_pal == 0) && (vc >= 259))
|
||||
vc = scan_line - 42;
|
||||
else if ((VERSION_PAL == 0) && (vc >= 235))
|
||||
vc = scan_line - 6;
|
||||
assert(vc < 0x200);
|
||||
|
||||
// printf("VERSION_PAL:%d , mode_pal:%d,line:%d,vc:%d\n",VERSION_PAL,mode_pal,scan_line,vc);
|
||||
return vc;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 HVCOUNTER
|
||||
* Process SEGA 315-5313 HVCOUNTER based on HCOUNTER and VCOUNTER
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline __attribute__((always_inline))
|
||||
unsigned short gwenesis_vdp_hvcounter() {
|
||||
/* H/V Counter */
|
||||
if (hvcounter_latched == 1)
|
||||
return hvcounter_latch;
|
||||
|
||||
int hc = gwenesis_vdp_hcounter();
|
||||
int vc = gwenesis_vdp_vcounter();
|
||||
assert(vc < 512);
|
||||
assert(hc < 512);
|
||||
|
||||
return ((vc & 0xFF) << 8) | (hc >> 1);
|
||||
}
|
||||
|
||||
//static inline __attribute__((always_inline))
|
||||
bool vblank(void) {
|
||||
int vc = gwenesis_vdp_vcounter();
|
||||
// printf("vc=%d,REG1_DISP_ENABLED=%d,VBLAN?%d\n",vc,REG1_DISP_ENABLED,
|
||||
// mode_pal?((vc >= 0xF0) && (vc < 0x1FF)):((vc >= 0xE0) && (vc < 0x1FF)));
|
||||
|
||||
if (REG1_DISP_ENABLED == 0)
|
||||
return true;
|
||||
|
||||
if (mode_pal)
|
||||
return ((vc >= 0xF0) && (vc < 0x1FF));
|
||||
else
|
||||
return ((vc >= 0xE0) && (vc < 0x1FF));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 Set Register
|
||||
* Write an value to specified register
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline)) void gwenesis_vdp_register_w(int reg, unsigned char value) {
|
||||
// Mode4 is not emulated yet. Anyway, access to registers > 0xA is blocked.
|
||||
if ((BIT(gwenesis_vdp_regs[0x1], 2) == 0) && reg > 0xA)
|
||||
return;
|
||||
|
||||
gwenesis_vdp_regs[reg] = value;
|
||||
vdpm_log(__FUNCTION__, "reg:%02d <- %02x", reg, value);
|
||||
|
||||
|
||||
// Writing a register clear the first command word
|
||||
// (see sonic3d intro wrong colors, and vdpfifotesting)
|
||||
code_reg &= ~0x3;
|
||||
address_reg &= ~0x3FFF;
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
|
||||
if (REG0_HVLATCH && (hvcounter_latched == 0)) {
|
||||
hvcounter_latch = gwenesis_vdp_hvcounter();
|
||||
hvcounter_latched = 1;
|
||||
//printf("HVcounter latched:%x\n",hvcounter_latch);
|
||||
}
|
||||
else if ((REG0_HVLATCH == 0) && (hvcounter_latched == 1)) {
|
||||
//printf("HVcounter released\n");
|
||||
hvcounter_latched = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Simulate FIFO
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void push_fifo(unsigned int value) {
|
||||
fifo[3] = fifo[2];
|
||||
fifo[2] = fifo[1];
|
||||
fifo[1] = fifo[0];
|
||||
fifo[0] = value;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 VRAM Write
|
||||
* Write an value to VRAM on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
//static inline __attribute__((always_inline))
|
||||
void __not_in_flash_func(gwenesis_vdp_vram_write)(unsigned int address, unsigned int value) {
|
||||
VRAM[address] = value;
|
||||
|
||||
// Update internal SAT Cache
|
||||
// used in Castlevania Bloodlines
|
||||
if (address >= REG5_SAT_ADDRESS && address < REG5_SAT_ADDRESS + REG5_SAT_SIZE)
|
||||
SAT_CACHE[address - REG5_SAT_ADDRESS] = value;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
unsigned short status_register_r(void) {
|
||||
unsigned short status = gwenesis_vdp_status; // & 0xF800;
|
||||
// unsigned short status = gwenesis_vdp_status;// & 0xFC00;
|
||||
|
||||
int hc = gwenesis_vdp_hcounter();
|
||||
// int vc = gwenesis_vdp_vcounter();
|
||||
|
||||
// TODO: FIFO not emulated
|
||||
status |= STATUS_FIFO_EMPTY;
|
||||
|
||||
// VBLANK bit
|
||||
if (vblank())
|
||||
status |= STATUS_VBLANK;
|
||||
|
||||
// HBLANK bit (see Nemesis doc, as linked in hcounter())
|
||||
if (REG12_MODE_H40) {
|
||||
if (hc < 0xA || hc >= 0x166)
|
||||
status |= STATUS_HBLANK;
|
||||
}
|
||||
else {
|
||||
if (hc < 0x9 || hc >= 0x126)
|
||||
status |= STATUS_HBLANK;
|
||||
}
|
||||
|
||||
if (sprite_overflow)
|
||||
status |= STATUS_SPRITEOVERFLOW;
|
||||
if (sprite_collision)
|
||||
status |= STATUS_SPRITECOLLISION;
|
||||
|
||||
if (mode_pal)
|
||||
status |= STATUS_PAL;
|
||||
|
||||
// reading the status clears the pending flag for command words
|
||||
command_word_pending = 0;
|
||||
|
||||
//gwenesis_vdp_status = status;
|
||||
|
||||
// printf("VDP status read:%04X H?%d V?%d line=%d\n",status, status & STATUS_HBLANK ,status & STATUS_VBLANK,scan_line);
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 Get Register
|
||||
* Read an value from specified register
|
||||
*
|
||||
******************************************************************************/
|
||||
unsigned int gwenesis_vdp_get_reg(int reg) {
|
||||
return gwenesis_vdp_regs[reg];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 DMA Fill
|
||||
* DMA process to fill memory
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void gwenesis_vdp_dma_fill(unsigned short value) {
|
||||
//vdpm_log(__FUNCTION__,"@%x len:%x val:%x",REG21_DMA_SRCADDR_LOW,REG19_DMA_LENGTH,value);
|
||||
int dma_length = REG19_DMA_LENGTH;
|
||||
|
||||
// This address is not required for fills,
|
||||
// but it's still updated by the DMA engine.
|
||||
unsigned short src_addr_low = REG21_DMA_SRCADDR_LOW;
|
||||
|
||||
if (dma_length == 0)
|
||||
dma_length = 0xFFFF;
|
||||
|
||||
/*
|
||||
vdpm_log(__FUNCTION__, "DMA %s fill: dst:%04x, length:%d, increment:%d, value=%02x",
|
||||
(code_reg&0xF)==1 ? "VRAM" : ( (code_reg&0xF)==3 ? "CRAM" : "VSRAM"),
|
||||
address_reg, dma_length, REG15_DMA_INCREMENT, value>>8);
|
||||
*/
|
||||
|
||||
switch (code_reg & 0xF) {
|
||||
case 0x1:
|
||||
do {
|
||||
gwenesis_vdp_vram_write((address_reg ^ 1) & 0xFFFF, value >> 8);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr_low++;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
case 0x3: // undocumented and buggy, see vdpfifotesting
|
||||
do {
|
||||
uint8_t addr = (address_reg & 0x7f) >> 1;
|
||||
CRAM[addr] = fifo[3];
|
||||
//graphics_set_palette(addr, RGB888(CRAM_R(CRAM[addr]), CRAM_G(CRAM[addr]), CRAM_B(CRAM[addr])));
|
||||
emu_SetPaletteEntry(CRAM_R(CRAM[addr]), CRAM_G(CRAM[addr]), CRAM_B(CRAM[addr]),addr);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr_low++;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
case 0x5: // undocumented and buggy, see vdpfifotesting:
|
||||
do {
|
||||
VSRAM[(address_reg & 0x7f) >> 1] = fifo[3] & 0x03FF;
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr_low++;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
default:
|
||||
printf("Invalid code during DMA fill\n");
|
||||
}
|
||||
|
||||
|
||||
// Clear DMA length at the end of transfer
|
||||
gwenesis_vdp_regs[19] = gwenesis_vdp_regs[20] = 0;
|
||||
|
||||
// Update DMA source address after end of transfer
|
||||
gwenesis_vdp_regs[21] = src_addr_low & 0xFF;
|
||||
gwenesis_vdp_regs[22] = src_addr_low >> 8;
|
||||
|
||||
// gwenesis_vdp_regs[21] = src_addr_low >> 1 & 0xFF;
|
||||
// gwenesis_vdp_regs[22] = src_addr_low >> 9 & 0xFF;
|
||||
// gwenesis_vdp_regs[23] = src_addr_low >> 17 & 0xFF;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 DMA M68K
|
||||
* DMA process to copy from m68k to memory
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void gwenesis_vdp_dma_m68k() {
|
||||
int dma_length = REG19_DMA_LENGTH;
|
||||
|
||||
// This address is not required for fills,
|
||||
// but it's still updated by the DMA engine.
|
||||
unsigned short src_addr_low = REG21_DMA_SRCADDR_LOW;
|
||||
unsigned int src_addr_high = REG23_DMA_SRCADDR_HIGH;
|
||||
unsigned int src_addr = (src_addr_high | src_addr_low) << 1;
|
||||
unsigned int value;
|
||||
|
||||
if (dma_length == 0)
|
||||
dma_length = 0xFFFF;
|
||||
|
||||
/*
|
||||
vdpm_log(__FUNCTION__,"DMA M68k->%s copy: src:%04x, dst:%04x, length:%d, increment:%d",
|
||||
(code_reg&0xF)==1 ? "VRAM" : ( (code_reg&0xF)==3 ? "CRAM" : "VSRAM"),
|
||||
(src_addr_high | src_addr_low) << 1, address_reg, dma_length, REG15_DMA_INCREMENT);
|
||||
*/
|
||||
|
||||
/* Source is :
|
||||
68K_RAM if dma_source_high == 0x00FF : FETCH16RAM(dma_source_low << 1)
|
||||
68K_ROM otherwise : FETCH16ROM((dma_source_high | dma_source_low) << 1))
|
||||
*/
|
||||
|
||||
/* Source is 68K RAM */
|
||||
if (src_addr & 0x800000) {
|
||||
switch (code_reg & 0xF) {
|
||||
case 0x1: // dest is VRAM
|
||||
do {
|
||||
value = FETCH16RAM(src_addr);
|
||||
push_fifo(value);
|
||||
gwenesis_vdp_vram_write((address_reg) & 0xFFFF, value >> 8);
|
||||
gwenesis_vdp_vram_write((address_reg ^ 1) & 0xFFFF, value & 0xFF);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
|
||||
case 0x3: // dest is CRAM
|
||||
do {
|
||||
value = FETCH16RAM(src_addr);
|
||||
push_fifo(value);
|
||||
uint8_t addr = (address_reg & 0x7f) >> 1;
|
||||
CRAM[addr] = value;
|
||||
|
||||
//graphics_set_palette(addr, RGB888(CRAM_R(value), CRAM_G(value), CRAM_B(value)));
|
||||
emu_SetPaletteEntry(CRAM_R(CRAM[addr]), CRAM_G(CRAM[addr]), CRAM_B(CRAM[addr]),addr);
|
||||
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
|
||||
case 0x5: // dest is VSRAM
|
||||
|
||||
do {
|
||||
value = FETCH16RAM(src_addr);
|
||||
push_fifo(value);
|
||||
VSRAM[(address_reg & 0x7f) >> 1] = value & 0x03FF;
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
default: // dest in unknown
|
||||
break;
|
||||
}
|
||||
|
||||
/* source is 68K ROM */
|
||||
}
|
||||
else {
|
||||
// unsigned int dma_source_address = (dma_source_high | dma_source_low) << 1;
|
||||
|
||||
switch (code_reg & 0xF) {
|
||||
case 0x1: // dest is VRAM
|
||||
|
||||
do {
|
||||
value = FETCH16ROM(src_addr);
|
||||
push_fifo(value);
|
||||
gwenesis_vdp_vram_write((address_reg) & 0xFFFF, value >> 8);
|
||||
gwenesis_vdp_vram_write((address_reg ^ 1) & 0xFFFF, value & 0xFF);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
|
||||
case 0x3: // dest is CRAM
|
||||
|
||||
do {
|
||||
value = FETCH16ROM(src_addr);
|
||||
push_fifo(value);
|
||||
uint8_t addr = (address_reg & 0x7f) >> 1;
|
||||
CRAM[addr] = value;
|
||||
|
||||
//graphics_set_palette(addr, RGB888(CRAM_R(value), CRAM_G(value), CRAM_B(value)));
|
||||
emu_SetPaletteEntry(CRAM_R(CRAM[addr]), CRAM_G(CRAM[addr]), CRAM_B(CRAM[addr]),addr);
|
||||
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
|
||||
case 0x5: // dest is VSRAM
|
||||
|
||||
do {
|
||||
value = FETCH16ROM(src_addr);
|
||||
push_fifo(value);
|
||||
VSRAM[(address_reg & 0x7f) >> 1] = value & 0x03FF;
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr += 2;
|
||||
}
|
||||
while (--dma_length);
|
||||
break;
|
||||
default: // dest in unknown
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update DMA source address after end of transfer
|
||||
gwenesis_vdp_regs[21] = src_addr & 0xFF; //src_addr_low & 0xFF;
|
||||
gwenesis_vdp_regs[22] = (src_addr >> 8) & 0xFF; //src_addr_low >> 8;
|
||||
|
||||
// Clear DMA length at the end of transfer
|
||||
gwenesis_vdp_regs[19] = gwenesis_vdp_regs[20] = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 DMA Copy
|
||||
* DMA process to copy from memory to memory
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void gwenesis_vdp_dma_copy() {
|
||||
// DMA_RUN=1;
|
||||
|
||||
int dma_length = REG19_DMA_LENGTH;
|
||||
unsigned short src_addr_low = REG21_DMA_SRCADDR_LOW;
|
||||
//vdpm_log(__FUNCTION__,"length:%x src:%x",dma_length,src_addr_low);
|
||||
|
||||
do {
|
||||
unsigned short value = VRAM[src_addr_low ^ 1];
|
||||
gwenesis_vdp_vram_write((address_reg ^ 1) & 0xFFFF, value);
|
||||
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
src_addr_low++;
|
||||
}
|
||||
while (--dma_length);
|
||||
|
||||
// Update DMA source address after end of transfer
|
||||
gwenesis_vdp_regs[21] = src_addr_low & 0xFF;
|
||||
gwenesis_vdp_regs[22] = src_addr_low >> 8;
|
||||
|
||||
// Clear DMA length at the end of transfer
|
||||
gwenesis_vdp_regs[19] = gwenesis_vdp_regs[20] = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 read data R16
|
||||
* Read an data value from mapped memory on specified address
|
||||
* and return as word
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
unsigned int gwenesis_vdp_read_data_port_16() {
|
||||
enum {
|
||||
CRAM_BITMASK = 0x0EEE,
|
||||
VSRAM_BITMASK = 0x07FF,
|
||||
VRAM8_BITMASK = 0x00FF
|
||||
};
|
||||
unsigned int value;
|
||||
command_word_pending = 0;
|
||||
|
||||
//if (code_reg & 1) /* check if write is set */
|
||||
// {
|
||||
switch (code_reg & 0xF) {
|
||||
case 0x0:
|
||||
// No byteswapping here
|
||||
value = VRAM[(address_reg) & 0xFFFE] << 8;
|
||||
value |= VRAM[(address_reg | 1) & 0xFFFF];
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0xFFFF;
|
||||
//vdpm_log(__FUNCTION__,"%04x",value);
|
||||
|
||||
return value;
|
||||
case 0x4:
|
||||
if (((address_reg & 0x7f) >> 1) >= 0x28)
|
||||
value = VSRAM[0];
|
||||
else
|
||||
value = VSRAM[(address_reg & 0x7f) >> 1];
|
||||
value = (value & VSRAM_BITMASK) | (fifo[3] & ~VSRAM_BITMASK);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0x7F;
|
||||
// vdpm_log(__FUNCTION__,"%04x",value);
|
||||
|
||||
return value;
|
||||
case 0x8:
|
||||
value = CRAM[(address_reg & 0x7f) >> 1];
|
||||
value = (value & CRAM_BITMASK) | (fifo[3] & ~CRAM_BITMASK);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0x7F;
|
||||
// vdpm_log(__FUNCTION__,"%04x",value);
|
||||
|
||||
return value;
|
||||
case 0xC: /* 8-Bit memory access */
|
||||
value = VRAM[(address_reg ^ 1) & 0xFFFF];
|
||||
value = (value & VRAM8_BITMASK) | (fifo[3] & ~VRAM8_BITMASK);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0xFFFF;
|
||||
// vdpm_log(__FUNCTION__,"%04x",value);
|
||||
|
||||
return value;
|
||||
default:
|
||||
printf("unhandled gwenesis_vdp_read_data_port_16(%x)\n", address_reg);
|
||||
return 0xFF;
|
||||
}
|
||||
// }
|
||||
// return 0x00;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 write to control port
|
||||
* Write an control value to SEGA 315-5313 control port
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void gwenesis_vdp_control_port_write(unsigned int value) {
|
||||
//vdpm_log(__FUNCTION__,"%04x",value);
|
||||
|
||||
if (command_word_pending == 1) {
|
||||
// second half of the command word
|
||||
code_reg &= ~0x3C;
|
||||
code_reg |= (value >> 2) & 0x3C;
|
||||
address_reg &= 0x3FFF;
|
||||
address_reg |= value << 14;
|
||||
command_word_pending = 0;
|
||||
//vdpm_log(__FUNCTION__,"command word 2nd code:%x address:%x", code_reg, address_reg);
|
||||
|
||||
|
||||
// DMA trigger
|
||||
if (code_reg & (1 << 5)) {
|
||||
// Check master DMA enable, otherwise skip
|
||||
if (REG1_DMA_ENABLED == 0)
|
||||
return;
|
||||
|
||||
// gwenesis_vdp_status |= 0x2;
|
||||
switch (REG23_DMA_TYPE) {
|
||||
case 0:
|
||||
case 1:
|
||||
|
||||
gwenesis_vdp_dma_m68k();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
// VRAM fill will trigger on next data port write
|
||||
dma_fill_pending = 1;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
gwenesis_vdp_dma_copy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((value >> 14) == 2) {
|
||||
gwenesis_vdp_register_w((value >> 8) & 0x1F, value & 0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
// Anything else is treated as first half of the command word
|
||||
// We directly update the code reg and address reg
|
||||
code_reg &= ~0x3;
|
||||
code_reg |= value >> 14;
|
||||
address_reg &= ~0x3FFF;
|
||||
address_reg |= value & 0x3FFF;
|
||||
command_word_pending = 1;
|
||||
// vdpm_log(__FUNCTION__,"command word 1st code:%x address:%x", code_reg, address_reg);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 write data W16
|
||||
* Write an data value to mapped memory on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
static inline __attribute__((always_inline))
|
||||
void gwenesis_vdp_write_data_port_16(unsigned int value) {
|
||||
vdpm_log(__FUNCTION__, "%04x", value);
|
||||
|
||||
command_word_pending = 0;
|
||||
|
||||
push_fifo(value);
|
||||
|
||||
switch (code_reg & 0xF) {
|
||||
case 0x1: /* VRAM write */
|
||||
//vdpm_log(__FUNCTION__,"VRAM write : addr:%x increment:%d value:%04x",
|
||||
// address_reg, REG15_DMA_INCREMENT, value);
|
||||
gwenesis_vdp_vram_write(address_reg & 0xFFFF, (value >> 8) & 0xFF);
|
||||
gwenesis_vdp_vram_write((address_reg ^ 1) & 0xFFFF, (value) & 0xFF);
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0xFFFF;
|
||||
|
||||
break;
|
||||
case 0x3: /* CRAM write */
|
||||
//vdpm_log(__FUNCTION__,"CRAM write : addr:%x increment:%d value:%04x",
|
||||
// address_reg, REG15_DMA_INCREMENT, value);
|
||||
{
|
||||
uint8_t addr = (address_reg & 0x7f) >> 1;
|
||||
CRAM[addr] = value;
|
||||
|
||||
//graphics_set_palette(addr, RGB888(CRAM_R(value), CRAM_G(value), CRAM_B(value)));
|
||||
emu_SetPaletteEntry(CRAM_R(CRAM[addr]), CRAM_G(CRAM[addr]), CRAM_B(CRAM[addr]),addr);
|
||||
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0xFFFF;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x5: /* VSRAM write */
|
||||
//vdpm_log(__FUNCTION__,"VSRAM write : addr:%x increment:%d value:%04x",
|
||||
// address_reg, REG15_DMA_INCREMENT, value);
|
||||
// printf("write dataport 16: VSRAM@%04x:%04x\n",address_reg,value);
|
||||
VSRAM[(address_reg & 0x7f) >> 1] = value & 0X03FF;
|
||||
address_reg += REG15_DMA_INCREMENT;
|
||||
address_reg &= 0xFFFF;
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
case 0x8: // Write operation after setting up
|
||||
// Makes Compatible with Alladin and Ecco 2
|
||||
break;
|
||||
case 0x9: // VDP FIFO TEST
|
||||
break;
|
||||
default:
|
||||
printf("VDP Data Port invalid");
|
||||
}
|
||||
|
||||
/* if a DMA is scheduled, do it */
|
||||
if (dma_fill_pending) {
|
||||
dma_fill_pending = 0;
|
||||
gwenesis_vdp_dma_fill(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 Get Status
|
||||
* Return current VDP Status
|
||||
*
|
||||
******************************************************************************/
|
||||
unsigned int gwenesis_vdp_get_status() {
|
||||
return gwenesis_vdp_status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 read from memory R8
|
||||
* Read an value from mapped memory on specified address
|
||||
* and return as byte
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline
|
||||
unsigned int gwenesis_vdp_read_memory_8(unsigned int address) {
|
||||
unsigned int ret = gwenesis_vdp_read_memory_16(address & ~1);
|
||||
if (address & 1)
|
||||
return ret & 0xFF;
|
||||
|
||||
// vdpm_log(__FUNCTION__,"%04x : %04x",address,ret);
|
||||
|
||||
return ret >> 8;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 read from memory R16
|
||||
* Read an value from mapped memory on specified address
|
||||
* and return as word
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline
|
||||
unsigned int gwenesis_vdp_read_memory_16(unsigned int address) {
|
||||
address &= 0x1F;
|
||||
|
||||
if (address < 0X4)
|
||||
return gwenesis_vdp_read_data_port_16();
|
||||
else if (address < 0x8)
|
||||
return status_register_r();
|
||||
else if (address < 0xf)
|
||||
return gwenesis_vdp_hvcounter();
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 write to memory W8
|
||||
* Write an byte value to mapped memory on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline
|
||||
void gwenesis_vdp_write_memory_8(unsigned int address, unsigned int value) {
|
||||
gwenesis_vdp_write_memory_16(address & ~1, (value << 8) | value);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SEGA 315-5313 write to memory W16
|
||||
* Write an word value to mapped memory on specified address
|
||||
*
|
||||
******************************************************************************/
|
||||
//static inline
|
||||
extern int system_clock;
|
||||
|
||||
void gwenesis_vdp_write_memory_16(unsigned int address, unsigned int value) {
|
||||
address = address & 0x1F;
|
||||
|
||||
if (address < 0x4) {
|
||||
gwenesis_vdp_write_data_port_16(value);
|
||||
return;
|
||||
}
|
||||
if (address < 0x8) {
|
||||
gwenesis_vdp_control_port_write(value);
|
||||
return;
|
||||
}
|
||||
if (address < 0x18) {
|
||||
// PSG 8 bits write
|
||||
vdpm_log(__FUNCTION__, "PSG sclk=%d,mclk=%d", system_clock, m68k_cycles_master());
|
||||
if(audio_enabled && sn76489_enabled)
|
||||
gwenesis_SN76489_Write(value, m68k_cycles_master());
|
||||
return;
|
||||
}
|
||||
// UNHANDLED
|
||||
printf("unhandled gwenesis_vdp_write(%x, %x)\n", address, value);
|
||||
}
|
||||
|
||||
void gwenesis_vdp_mem_save_state() {
|
||||
}
|
||||
|
||||
void gwenesis_vdp_mem_load_state() {
|
||||
|
||||
}
|
||||
|
|
@ -24,23 +24,24 @@ bool show_fps = true;
|
|||
bool limit_fps = true;
|
||||
bool interlace = true;
|
||||
bool frameskip = true;
|
||||
bool flash_line = false;
|
||||
bool flash_frame = false;
|
||||
int z80_enable_mode = 2;
|
||||
bool sn76489_enabled = true;
|
||||
//int z80_enable_mode = 0;
|
||||
//bool sn76489_enabled = false;
|
||||
extern unsigned short button_state[3];
|
||||
|
||||
|
||||
uint8_t snd_accurate = 0;
|
||||
/* shared variables with gwenesis_sn76589 */
|
||||
int16_t gwenesis_sn76489_buffer[GWENESIS_AUDIO_BUFFER_LENGTH_NTSC * 2]; // 888 = NTSC, PAL = 1056 (too big) //GWENESIS_AUDIO_BUFFER_LENGTH_PAL];
|
||||
int sn76489_index; /* sn78649 audio buffer index */
|
||||
int sn76489_clock; /* sn78649 clock in video clock resolution */
|
||||
|
||||
int8_t gwenesis_ym2612_buffer[GWENESIS_AUDIO_BUFFER_LENGTH_NTSC * 2]; //GWENESIS_AUDIO_BUFFER_LENGTH_PAL];
|
||||
int ym2612_index; /* ym2612 audio buffer index */
|
||||
int ym2612_clock;
|
||||
|
||||
int audio_enabled = 1;
|
||||
int snd_output_volume = 9;
|
||||
uint8_t snd_accurate = 0;
|
||||
|
||||
|
||||
static unsigned short screen_line[320];
|
||||
|
||||
|
||||
void gwenesis_io_get_buttons() {
|
||||
}
|
||||
|
|
@ -58,11 +59,9 @@ void gen_Init(void)
|
|||
emu_printf("gen_Init done");
|
||||
}
|
||||
|
||||
|
||||
static int hk = 0;
|
||||
static int k = 0;
|
||||
|
||||
|
||||
void gen_Input(int click) {
|
||||
hk = emu_ReadI2CKeyboard();
|
||||
k = emu_ReadKeys();
|
||||
|
|
@ -74,19 +73,20 @@ void gen_Start(char * filename)
|
|||
{
|
||||
emu_printf("gen_Start");
|
||||
|
||||
int size = flash_load(filename);
|
||||
int size = flash_load_bswap(filename);
|
||||
|
||||
load_cartridge((uintptr_t)flash_start);
|
||||
|
||||
//gwenesis_system_init();
|
||||
power_on();
|
||||
reset_emulation();
|
||||
gwenesis_vdp_set_buffer((uint8_t *) emu_LineBuffer(0));
|
||||
gwenesis_vdp_set_buffer(&screen_line[0]);
|
||||
|
||||
#ifdef SOUND_PRESENT
|
||||
#ifdef HAS_SND
|
||||
emu_sndInit();
|
||||
emu_sndInit();
|
||||
memset(gwenesis_sn76489_buffer, 0, sizeof(gwenesis_sn76489_buffer));
|
||||
memset(gwenesis_ym2612_buffer, 0, sizeof(gwenesis_ym2612_buffer));
|
||||
#endif
|
||||
#else
|
||||
#endif
|
||||
|
||||
emu_printf("gen_Start done");
|
||||
}
|
||||
|
|
@ -98,7 +98,6 @@ int frame_timer_start = 0;
|
|||
/* Clocks and synchronization */
|
||||
/* system clock is video clock */
|
||||
int system_clock;
|
||||
|
||||
unsigned int lines_per_frame = LINES_PER_FRAME_NTSC; //262; /* NTSC: 262, PAL: 313 */
|
||||
int scan_line;
|
||||
unsigned int frame_counter = 0;
|
||||
|
|
@ -110,144 +109,153 @@ extern unsigned int screen_width, screen_height;
|
|||
extern int hint_pending;
|
||||
|
||||
void gen_Step(void) {
|
||||
/* Eumulator loop */
|
||||
int hint_counter = gwenesis_vdp_regs[10];
|
||||
int hint_counter = gwenesis_vdp_regs[10];
|
||||
|
||||
const bool is_pal = REG1_PAL;
|
||||
screen_width = REG12_MODE_H40 ? 320 : 256;
|
||||
screen_height = is_pal ? 240 : 224;
|
||||
lines_per_frame = is_pal ? LINES_PER_FRAME_PAL : LINES_PER_FRAME_NTSC;
|
||||
const bool is_pal = REG1_PAL;
|
||||
screen_width = REG12_MODE_H40 ? 320 : 256;
|
||||
screen_height = is_pal ? 240 : 224;
|
||||
lines_per_frame = is_pal ? LINES_PER_FRAME_PAL : LINES_PER_FRAME_NTSC;
|
||||
|
||||
// graphics_set_buffer(buffer, screen_width, screen_height);
|
||||
// TODO: move to separate function graphics_set_dimensions ?
|
||||
// graphics_set_buffer((uint8_t*)SCREEN, screen_width, screen_height);
|
||||
// graphics_set_offset(screen_width != 320 ? 32 : 0, screen_height != 240 ? 8 : 0);
|
||||
gwenesis_vdp_render_config();
|
||||
|
||||
zclk = 0;
|
||||
/* Reset the difference clocks and audio index */
|
||||
system_clock = 0;
|
||||
sn76489_clock = 0;
|
||||
sn76489_index = 0;
|
||||
scan_line = 0;
|
||||
if (z80_enable_mode == 1)
|
||||
z80_run(lines_per_frame * VDP_CYCLES_PER_LINE);
|
||||
|
||||
while (scan_line < lines_per_frame) {
|
||||
/* CPUs */
|
||||
m68k_run(system_clock + VDP_CYCLES_PER_LINE);
|
||||
if (z80_enable_mode == 2)
|
||||
z80_run(system_clock + VDP_CYCLES_PER_LINE);
|
||||
/* Video */
|
||||
// Interlace mode
|
||||
if (drawFrame && !interlace || (frame % 2 == 0 && scan_line % 2) || scan_line % 2 == 0) {
|
||||
if (scan_line < 200)
|
||||
gwenesis_vdp_render_line(scan_line); /* render scan_line */
|
||||
}
|
||||
|
||||
// On these lines, the line counter interrupt is reloaded
|
||||
if (scan_line == 0 || scan_line > screen_height) {
|
||||
hint_counter = REG10_LINE_COUNTER;
|
||||
}
|
||||
|
||||
// interrupt line counter
|
||||
if (--hint_counter < 0) {
|
||||
if (REG0_LINE_INTERRUPT != 0 && scan_line <= screen_height) {
|
||||
hint_pending = 1;
|
||||
if ((gwenesis_vdp_status & STATUS_VIRQPENDING) == 0)
|
||||
m68k_update_irq(4);
|
||||
}
|
||||
hint_counter = REG10_LINE_COUNTER;
|
||||
}
|
||||
|
||||
scan_line++;
|
||||
|
||||
// vblank begin at the end of last rendered line
|
||||
if (scan_line == screen_height) {
|
||||
if (REG1_VBLANK_INTERRUPT != 0) {
|
||||
gwenesis_vdp_status |= STATUS_VIRQPENDING;
|
||||
m68k_set_irq(6);
|
||||
}
|
||||
z80_irq_line(1);
|
||||
}
|
||||
|
||||
if (!is_pal && scan_line == screen_height + 1) {
|
||||
z80_irq_line(0);
|
||||
// FRAMESKIP every 3rd frame
|
||||
drawFrame = frameskip && frame % 3 != 0;
|
||||
// if (frameskip && frame % 3 == 0) {
|
||||
// drawFrame = 0;
|
||||
// } else {
|
||||
// drawFrame = 1;
|
||||
// }
|
||||
}
|
||||
|
||||
system_clock += VDP_CYCLES_PER_LINE;
|
||||
gwenesis_vdp_render_config();
|
||||
|
||||
zclk = 0;
|
||||
/* Reset the difference clocks and audio index */
|
||||
system_clock = 0;
|
||||
sn76489_clock = 0;
|
||||
sn76489_index = 0;
|
||||
ym2612_clock = 0;
|
||||
ym2612_index = 0;
|
||||
scan_line = 0;
|
||||
//if (z80_enable_mode == 1)
|
||||
//z80_run(lines_per_frame * VDP_CYCLES_PER_LINE);
|
||||
|
||||
//printf("m(%x)\n", frame);
|
||||
while (scan_line < lines_per_frame) {
|
||||
/* CPUs */
|
||||
m68k_run(system_clock + VDP_CYCLES_PER_LINE);
|
||||
if (z80_enable_mode == 2)
|
||||
z80_run(system_clock + VDP_CYCLES_PER_LINE);
|
||||
/* Video */
|
||||
// Interlace mode
|
||||
//if (drawFrame && !interlace || (frame % 2 == 0 && scan_line % 2) || scan_line % 2 == 0) {
|
||||
if (drawFrame) {
|
||||
gwenesis_vdp_set_buffer(&screen_line[0]);
|
||||
gwenesis_vdp_render_line(scan_line); /* render scan_line */
|
||||
if (scan_line < screen_height ) emu_DrawLine16(&screen_line[0], 320, screen_height, scan_line);
|
||||
}
|
||||
/*
|
||||
frame++;
|
||||
if (limit_fps) {
|
||||
frame_cnt++;
|
||||
if (frame_cnt == (is_pal ? 5 : 6)) {
|
||||
while (time_us_64() - frame_timer_start < (is_pal ? 20000 * 5 : 16666 * 6)) {
|
||||
busy_wait_at_least_cycles(10);
|
||||
}; // 60 Hz
|
||||
frame_timer_start = time_us_64();
|
||||
frame_cnt = 0;
|
||||
}
|
||||
|
||||
// On these lines, the line counter interrupt is reloaded
|
||||
if (scan_line == 0 || scan_line > screen_height) {
|
||||
hint_counter = REG10_LINE_COUNTER;
|
||||
}
|
||||
*/
|
||||
#if HDMI | SOFTTV | TV
|
||||
// if (audio_enabled)
|
||||
// gwenesis_SN76489_run(REG1_PAL ? LINES_PER_FRAME_PAL : LINES_PER_FRAME_NTSC * VDP_CYCLES_PER_LINE);
|
||||
#endif
|
||||
// ym2612_run(262 * VDP_CYCLES_PER_LINE);
|
||||
/*
|
||||
gwenesis_SN76489_run(262 * VDP_CYCLES_PER_LINE);
|
||||
|
||||
// interrupt line counter
|
||||
if (--hint_counter < 0) {
|
||||
if (REG0_LINE_INTERRUPT != 0 && scan_line <= screen_height) {
|
||||
hint_pending = 1;
|
||||
if ((gwenesis_vdp_status & STATUS_VIRQPENDING) == 0)
|
||||
m68k_update_irq(4);
|
||||
}
|
||||
hint_counter = REG10_LINE_COUNTER;
|
||||
}
|
||||
|
||||
scan_line++;
|
||||
|
||||
// vblank begin at the end of last rendered line
|
||||
if (scan_line == screen_height) {
|
||||
if (REG1_VBLANK_INTERRUPT != 0) {
|
||||
gwenesis_vdp_status |= STATUS_VIRQPENDING;
|
||||
m68k_set_irq(6);
|
||||
}
|
||||
z80_irq_line(1);
|
||||
}
|
||||
|
||||
if (!is_pal && scan_line == screen_height + 1) {
|
||||
z80_irq_line(0);
|
||||
// FRAMESKIP every 3rd frame
|
||||
//drawFrame = frameskip && frame % 3 != 0;
|
||||
// if (frameskip && frame % 3 == 0) {
|
||||
// drawFrame = 0;
|
||||
// } else {
|
||||
// drawFrame = 1;
|
||||
// }
|
||||
}
|
||||
|
||||
system_clock += VDP_CYCLES_PER_LINE;
|
||||
}
|
||||
frame++;
|
||||
/*
|
||||
if (limit_fps) {
|
||||
frame_cnt++;
|
||||
if (frame_cnt == (is_pal ? 5 : 6)) {
|
||||
while (time_us_64() - frame_timer_start < (is_pal ? 20000 * 5 : 16666 * 6)) {
|
||||
busy_wait_at_least_cycles(10);
|
||||
}; // 60 Hz
|
||||
frame_timer_start = time_us_64();
|
||||
frame_cnt = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef HAS_SND_SYNC
|
||||
if (audio_enabled) {
|
||||
ym2612_run(262 * VDP_CYCLES_PER_LINE);
|
||||
static int16_t snd_buf[GWENESIS_AUDIO_BUFFER_LENGTH_NTSC * 2];
|
||||
for (int h = 0; h < ym2612_index * 2 * GWENESIS_AUDIO_SAMPLING_DIVISOR; h++) {
|
||||
snd_buf[h] = (gwenesis_sn76489_buffer[h / 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR]) << 3;
|
||||
gwenesis_SN76489_run(262 * VDP_CYCLES_PER_LINE);
|
||||
audio_sample * snd_buf = (audio_sample *)emu_sndGetBuffer();
|
||||
for (int h = 0; h < GWENESIS_AUDIO_BUFFER_LENGTH_NTSC * 2; h++) {
|
||||
int16_t s1 = gwenesis_ym2612_buffer[h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR] + gwenesis_sn76489_buffer[h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR]>>8;
|
||||
int16_t s2 = gwenesis_ym2612_buffer[(h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR+1) ] + gwenesis_sn76489_buffer[(h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR+1)]>>8;
|
||||
*snd_buf++ = ((s1+s2)/4)+128;
|
||||
}
|
||||
i2s_dma_write(&i2s_config, snd_buf);*/
|
||||
// reset m68k cycles to the begin of next frame cycle
|
||||
m68k.cycles -= system_clock;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* copy audio samples for DMA */
|
||||
//gwenesis_sound_submit();
|
||||
// reset m68k cycles to the begin of next frame cycle
|
||||
m68k.cycles -= system_clock;
|
||||
|
||||
|
||||
/*
|
||||
uint32_t buttons = 0;
|
||||
button_state[0]=0;
|
||||
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
|
||||
buttons |= JOY_LEFT;
|
||||
button_state[0] |= (1 << PAD_LEFT);
|
||||
}
|
||||
if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
|
||||
buttons |= JOY_RIGHT;
|
||||
button_state[0] |= (1 << PAD_RIGHT);
|
||||
}
|
||||
if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
|
||||
buttons |= JOY_UP;
|
||||
button_state[0] |= (1 << PAD_UP);
|
||||
}
|
||||
if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
|
||||
buttons |= JOY_DOWN;
|
||||
button_state[0] |= (1 << PAD_DOWN);
|
||||
}
|
||||
if ( k & MASK_JOY2_BTN) {
|
||||
buttons |= JOY_A;
|
||||
button_state[0] |= (1 << PAD_B);
|
||||
}
|
||||
if ( k & MASK_KEY_USER3) {
|
||||
button_state[0] |= (1 << PAD_C);
|
||||
}
|
||||
if ( k & MASK_KEY_USER4) {
|
||||
button_state[0] |= (1 << PAD_A);
|
||||
}
|
||||
|
||||
if (k & MASK_KEY_USER1) buttons |= JOY_B;
|
||||
//if (k & MASK_KEY_USER3) buttons |= JOY_SELECT;
|
||||
if (k & MASK_KEY_USER2) buttons |= JOY_RUN;
|
||||
*/
|
||||
if ( k & MASK_KEY_USER1) {
|
||||
button_state[0] |= (1 << PAD_S);
|
||||
}
|
||||
|
||||
//psg_update((int16_t *) audio_buffer, AUDIO_BUFFER_LENGTH, 0xff);
|
||||
//i2s_dma_write(&i2s_config, (const int16_t *) audio_buffer);
|
||||
button_state[0] = ~ button_state[0];
|
||||
|
||||
//emu_DrawVsync();
|
||||
}
|
||||
|
||||
|
||||
void SND_Process(void *stream, int len) {
|
||||
// psg_update((int16*)stream, 0, len);
|
||||
if (audio_enabled) {
|
||||
ym2612_run(262 * VDP_CYCLES_PER_LINE);
|
||||
gwenesis_SN76489_run(262 * VDP_CYCLES_PER_LINE);
|
||||
audio_sample * snd_buf = (audio_sample *)stream;
|
||||
for (int h = 0; h < len*2; h += 2) {
|
||||
int16_t s1 = gwenesis_ym2612_buffer[h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR] + gwenesis_sn76489_buffer[h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR]>>8;
|
||||
int16_t s2 = gwenesis_ym2612_buffer[(h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR+1) ] + gwenesis_sn76489_buffer[(h/ 2 / GWENESIS_AUDIO_SAMPLING_DIVISOR+1)]>>8;
|
||||
*snd_buf++ = ((s1+s2)/4)+128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#ifndef EMUCFG_H
|
||||
#define EMUCFG_H
|
||||
|
||||
#define PALETTE_SIZE 256
|
||||
#define PALETTE_SIZE 0
|
||||
#define VID_FRAME_SKIP 0x0
|
||||
#define TFT_VBUFFER_YCROP 0
|
||||
#define SINGLELINE_RENDERING 1
|
||||
//#define CUSTOM_SND 1
|
||||
#define CUSTOM_SND 1
|
||||
//#define TIMER_REND 1
|
||||
#define EXTRA_HEAP 0x10
|
||||
#define FILEBROWSER
|
||||
|
|
|
|||
BIN
MCUME_pico2/picogen/gwenesis/.DS_Store
vendored
Normal file
BIN
MCUME_pico2/picogen/gwenesis/.DS_Store
vendored
Normal file
Binary file not shown.
|
|
@ -129,7 +129,7 @@ void gwenesis_vdp_write_memory_8(unsigned int address, unsigned int value);
|
|||
void gwenesis_vdp_write_memory_16(unsigned int address, unsigned int value);
|
||||
|
||||
void gwenesis_vdp_set_buffers(unsigned char *screen_buffer, unsigned char *scaled_buffer);
|
||||
void gwenesis_vdp_set_buffer(uint8_t *ptr_screen_buffer);
|
||||
void gwenesis_vdp_set_buffer(unsigned short *ptr_screen_buffer);
|
||||
void gwenesis_vdp_get_buffer(uint16_t** ptr_screen_buffer);
|
||||
void gwenesis_vdp_render_line(int line);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -43,11 +43,12 @@ int main(void) {
|
|||
// set_sys_clock_khz(225000, truxe);
|
||||
// set_sys_clock_khz(250000, true);
|
||||
|
||||
set_sys_clock_khz(125000, true);
|
||||
|
||||
// set_sys_clock_khz(280000, true);
|
||||
// *((uint32_t *)(0x40010000+0x58)) = 2 << 16; //CLK_HSTX_DIV = 2 << 16; // HSTX clock/2
|
||||
|
||||
#ifdef HAS_USBPIO
|
||||
set_sys_clock_khz(140000, true);
|
||||
#else
|
||||
set_sys_clock_khz(280000, true);
|
||||
*((uint32_t *)(0x40010000+0x58)) = 2 << 16; //CLK_HSTX_DIV = 2 << 16; // HSTX clock/2
|
||||
#endif
|
||||
|
||||
emu_init();
|
||||
|
||||
|
|
@ -108,15 +109,15 @@ void emu_DrawVsync(void)
|
|||
{
|
||||
skip += 1;
|
||||
skip &= VID_FRAME_SKIP;
|
||||
|
||||
if ( emu_IsVga() ) {
|
||||
tft.waitSync();
|
||||
}
|
||||
else {
|
||||
volatile bool vb=vbl;
|
||||
while (vbl==vb) {};
|
||||
}
|
||||
|
||||
#ifdef HAS_USBPIO
|
||||
#else
|
||||
#ifdef USE_VGA
|
||||
tft.waitSync();
|
||||
#else
|
||||
volatile bool vb=vbl;
|
||||
while (vbl==vb) {};
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -168,10 +169,15 @@ void * emu_LineBuffer(int line)
|
|||
AudioPlaySystem mymixer;
|
||||
|
||||
void emu_sndInit() {
|
||||
tft.begin_audio(256, mymixer.snd_Mixer);
|
||||
tft.begin_audio(888*2, mymixer.snd_Mixer);
|
||||
mymixer.start();
|
||||
}
|
||||
|
||||
void * emu_sndGetBuffer(void)
|
||||
{
|
||||
return tft.get_buffer_audio();
|
||||
}
|
||||
|
||||
void emu_sndPlaySound(int chan, int volume, int freq)
|
||||
{
|
||||
if (chan < 6) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#ifndef _PROGRAM_CONFIG_H_
|
||||
#define _PROGRAM_CONFIG_H_
|
||||
|
||||
#define FLASH_STORE_START 0x280000
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
|
||||
#ifndef CPUINTRF_H
|
||||
#define CPUINTRF_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define CPU_16BIT_PORT 0x4000
|
||||
#define CPU_FLAGS_MASK 0xff00
|
||||
#define CLEAR_LINE 0
|
||||
#define ASSERT_LINE 1
|
||||
#define REG_PREVIOUSPC -1
|
||||
#define REG_SP_CONTENTS -2
|
||||
|
||||
/* daisy-chain link */
|
||||
typedef struct {
|
||||
void (*reset)(int); /* reset callback */
|
||||
int (*interrupt_entry)(int); /* entry callback */
|
||||
void (*interrupt_reti)(int); /* reti callback */
|
||||
int irq_param; /* callback paramater */
|
||||
} Z80_DaisyChain;
|
||||
|
||||
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
|
||||
|
||||
#define Z80_INT_REQ 0x01 /* interrupt request mask */
|
||||
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
|
||||
|
||||
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
|
||||
|
||||
|
||||
#endif /* CPUINTRF_H */
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "emuapi.h"
|
||||
#include "iopins.h"
|
||||
|
||||
extern "C" {
|
||||
#include "shared.h"
|
||||
#include "system.h"
|
||||
}
|
||||
|
||||
static int frameskip = 2;
|
||||
#define HAS_PSRAM 1
|
||||
|
||||
#ifdef HAS_PSRAM
|
||||
|
||||
#include "psram_t.h"
|
||||
|
||||
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
|
||||
|
||||
extern "C" uint8 read_rom(int address) {
|
||||
return (psram.psread(address));
|
||||
}
|
||||
|
||||
extern "C" uint8 readb_swap_rom(int address) {
|
||||
return(psram.psread(address^1));
|
||||
}
|
||||
|
||||
extern "C" uint16 readw_swap_rom(int address) {
|
||||
return psram.psread_w(address);
|
||||
}
|
||||
extern "C" void write_rom(int address, uint8 val) {
|
||||
psram.pswrite(address,val);
|
||||
}
|
||||
#else
|
||||
#include "flash_t.h"
|
||||
|
||||
static uint8 * flash_start;
|
||||
|
||||
extern "C" uint8 read_rom(int address) {
|
||||
return flash_start[address];
|
||||
}
|
||||
|
||||
extern "C" uint8 readb_swap_rom(int address) {
|
||||
return flash_start[address^1];
|
||||
}
|
||||
|
||||
extern "C" uint16 readw_swap_rom(int address) {
|
||||
uint16 * flash_start16 = (uint16*)flash_start;
|
||||
return flash_start16[address];
|
||||
//return psram.psread_w(address);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static uint8 romversion;
|
||||
extern "C" uint8 rom_version(void) {
|
||||
return romversion;
|
||||
}
|
||||
|
||||
static void deinterleave_block(int offset, int srcoffset)
|
||||
{
|
||||
int i;
|
||||
int srcaddr = offset + srcoffset;
|
||||
uint8 * block = work_ram; // 0x4000 bytes tmp buffer
|
||||
for(i = 0; i < 0x4000; i += 1) {
|
||||
block[i] = read_rom(srcaddr++);
|
||||
}
|
||||
for(i = 0; i < 0x2000; i += 1)
|
||||
{
|
||||
write_rom(srcoffset + i*2+1, block[0x2000 + (i)]);
|
||||
write_rom(srcoffset + i*2+0, block[0x0000 + (i)]);
|
||||
}
|
||||
}
|
||||
|
||||
void emu_KeyboardOnDown(int keymodifer, int key) {
|
||||
}
|
||||
|
||||
void emu_KeyboardOnUp(int keymodifer, int key) {
|
||||
}
|
||||
|
||||
void gen_Init(void)
|
||||
{
|
||||
emu_printf("Allocating MEM");
|
||||
#ifdef HAS_PSRAM
|
||||
psram.begin();
|
||||
#endif
|
||||
mem_init();
|
||||
emu_printf("Allocating MEM done");
|
||||
}
|
||||
|
||||
|
||||
static int hk = 0;
|
||||
static int k = 0;
|
||||
|
||||
|
||||
void gen_Input(int click) {
|
||||
hk = emu_ReadI2CKeyboard();
|
||||
k = emu_ReadKeys();
|
||||
}
|
||||
|
||||
|
||||
void gen_Start(char * filename)
|
||||
{
|
||||
emu_printf("load and init");
|
||||
|
||||
int size;
|
||||
int offset = 0;
|
||||
int i;
|
||||
|
||||
size = emu_FileSize(filename);
|
||||
|
||||
#ifdef HAS_PSRAM
|
||||
int pos = 0;
|
||||
int n;
|
||||
char * buf = (char*)bg_pattern_cache;
|
||||
size = 0;
|
||||
int f = emu_FileOpen(filename,"r+b");
|
||||
if (f) {
|
||||
while ( (n = emu_FileRead(buf,0x40000,f) ) ) {
|
||||
size += n;
|
||||
for (int i=0; i<n; i++) {
|
||||
write_rom(pos++,buf[i]);
|
||||
}
|
||||
emu_printi(size);
|
||||
//emu_printi(n);
|
||||
}
|
||||
emu_FileClose(f);
|
||||
}
|
||||
#else
|
||||
flash_start = (uint8 *)flash_load(filename);
|
||||
#endif
|
||||
|
||||
if((size / 512) & 1)
|
||||
{
|
||||
//emu_printf("deinterleave");
|
||||
size -= 512;
|
||||
offset += 512;
|
||||
for(i = 0; i < (size / 0x4000); i += 1)
|
||||
{
|
||||
deinterleave_block(offset, (i * 0x4000));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(i = 0; i < size; i += 2)
|
||||
{
|
||||
uint8 temp = read_rom(i+0);
|
||||
write_rom(i+0,read_rom(offset+i+1));
|
||||
write_rom(i+1, temp);
|
||||
}
|
||||
}
|
||||
|
||||
romversion = read_rom(0x0001F0);
|
||||
|
||||
|
||||
system_init();
|
||||
|
||||
#ifdef SOUND_PRESENT
|
||||
#ifdef HAS_SND
|
||||
// audio_init(22050);
|
||||
// emu_sndInit();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
system_reset();
|
||||
|
||||
emu_printf("init done");
|
||||
}
|
||||
|
||||
void gen_Step(void) {
|
||||
|
||||
input.pad[0] = 0;
|
||||
|
||||
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
|
||||
input.pad[0] |= INPUT_RIGHT;
|
||||
}
|
||||
if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
|
||||
input.pad[0] |= INPUT_LEFT;
|
||||
}
|
||||
if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
|
||||
input.pad[0] |= INPUT_UP;
|
||||
}
|
||||
if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
|
||||
input.pad[0] |= INPUT_DOWN;
|
||||
}
|
||||
if ( k & MASK_JOY2_BTN) {
|
||||
input.pad[0] |= INPUT_A;
|
||||
}
|
||||
|
||||
if (k & MASK_KEY_USER1) input.pad[0] |= INPUT_B;
|
||||
if (k & MASK_KEY_USER2) input.pad[0] |= INPUT_START;
|
||||
//if (k & MASK_KEY_USER3) input.pad[0] |= INPUT_C;
|
||||
|
||||
system_frame(frameskip);
|
||||
//emu_printi(emu_FrameSkip());
|
||||
|
||||
emu_DrawVsync();
|
||||
}
|
||||
|
||||
void SND_Process(void *stream, int len) {
|
||||
#ifdef SOUND_PRESENT
|
||||
#ifdef HAS_SND
|
||||
//audio_play_sample(stream, 0, len);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
extern void gen_Init(void);
|
||||
extern void gen_Step(void);
|
||||
extern void gen_Start(char * filename);
|
||||
extern void gen_Input(int click);
|
||||
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
#ifndef EMUCFG_H
|
||||
#define EMUCFG_H
|
||||
|
||||
#define PALETTE_SIZE 1
|
||||
#define VID_FRAME_SKIP 0x0
|
||||
#define TFT_VBUFFER_YCROP 0
|
||||
#define SINGLELINE_RENDERING 1
|
||||
//#define CUSTOM_SND 1
|
||||
//#define TIMER_REND 1
|
||||
#define EXTRA_HEAP 0x10000 // 0x10
|
||||
#define FILEBROWSER
|
||||
|
||||
|
||||
// Title: < >
|
||||
#define TITLE " Genesis Emulator "
|
||||
#define ROMSDIR "gen"
|
||||
|
||||
#define emu_Init(ROM) {gen_Init(); gen_Start(ROM);}
|
||||
#define emu_Step(x) {gen_Step();}
|
||||
#define emu_Input(x) {gen_Input(x);}
|
||||
|
||||
#ifdef KEYMAP_PRESENT
|
||||
|
||||
#ifdef PICOZX
|
||||
const unsigned short key_map1[] = {
|
||||
2,3,4,5,6,7,8,9,10,1,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0
|
||||
};
|
||||
|
||||
const unsigned short key_map2[] = {
|
||||
0,0,11,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,12,0,0,0,0,
|
||||
0,0,0,0,0,0
|
||||
};
|
||||
|
||||
const unsigned short key_map3[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0
|
||||
};
|
||||
|
||||
const unsigned short matkeys[] = {
|
||||
0x104,0x101,0x108,0x102,0x110,0x120,0x140,0x204,0x201,0x208, // row 1
|
||||
0x202,0x210,0x220,0x240,0x304,0x301,0x308,0x302,0x310,0x320, // row 2
|
||||
0x340,0x404,0x401,0x408,0x402,0x410,0x420,0x440,0x504,0x501, // row 3
|
||||
0x020,0x508,0x502,0x510,0x520,0x540,0x604,0x601,0x040,0x608, // row 4
|
||||
0x008,0x001,0x002,0x010,0x620,0x640 }; // cursor keys up, left, right, down, <<<, >>>
|
||||
|
||||
#else
|
||||
#define keylables_map1_0 (char *)"1234567890 "
|
||||
#define keylables_map1_1 (char *)" # * "
|
||||
#define keylables_map1_2 (char *)" "
|
||||
const unsigned short key_map1[] = {
|
||||
2,3,4,5,6,7,8,9,10,1,0,
|
||||
0,0,0,11,0,0,0,0,12,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0
|
||||
};
|
||||
|
||||
/*
|
||||
const unsigned short key_map1[] = {
|
||||
2,3,4,
|
||||
5,6,7,
|
||||
8,9,10,
|
||||
11,1,12};
|
||||
*/
|
||||
|
||||
#define keylables_map2_0 (char *)" "
|
||||
#define keylables_map2_1 (char *)" "
|
||||
#define keylables_map2_2 (char *)" "
|
||||
const unsigned short key_map2[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0
|
||||
};
|
||||
|
||||
#define keylables_map3_0 (char *)" "
|
||||
#define keylables_map3_1 (char *)" "
|
||||
#define keylables_map3_2 (char *)" "
|
||||
const unsigned short key_map3[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0, // function keys
|
||||
0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0
|
||||
};
|
||||
|
||||
const unsigned short matkeys[] = {
|
||||
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
|
||||
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
|
||||
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
|
||||
0x508,0x501,0x502,0x504 }; // cursor keys
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,181 +0,0 @@
|
|||
|
||||
#ifndef _H_FM_FM_
|
||||
#define _H_FM_FM_
|
||||
|
||||
#define HAS_YM2612 1
|
||||
|
||||
#define BUILD_YM2612 (HAS_YM2612 || HAS_YM3438)
|
||||
|
||||
#define FM_STEREO_MIX 0
|
||||
#define FM_OUTPUT_BIT 16
|
||||
#define FM_INTERNAL_TIMER 0
|
||||
|
||||
#define FM_LFO_SUPPORT 1
|
||||
#define FM_SEG_SUPPORT 0
|
||||
|
||||
#if BUILD_YM2612
|
||||
/* in 2612intf.c */
|
||||
#define YM2612UpdateReq(chip) YM2612UpdateRequest(chip);
|
||||
#endif
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef OSD_CPU_H
|
||||
#define OSD_CPU_H
|
||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||
typedef signed char INT8; /* signed 8bit */
|
||||
typedef signed short INT16; /* signed 16bit */
|
||||
typedef signed int INT32; /* signed 32bit */
|
||||
#endif
|
||||
|
||||
#define YM2203_NUMBUF 1
|
||||
#if FM_STEREO_MIX
|
||||
#define YM2151_NUMBUF 1
|
||||
#define YM2608_NUMBUF 1
|
||||
#define YM2612_NUMBUF 1
|
||||
#define YM2610_NUMBUF 1
|
||||
#else
|
||||
#define YM2151_NUMBUF 2 /* FM L+R */
|
||||
#define YM2608_NUMBUF 2 /* FM L+R+ADPCM+RYTHM */
|
||||
#define YM2610_NUMBUF 2 /* FM L+R+ADPCMA+ADPCMB */
|
||||
#define YM2612_NUMBUF 2 /* FM L+R */
|
||||
#endif
|
||||
|
||||
#if (FM_OUTPUT_BIT==16)
|
||||
typedef INT16 FMSAMPLE;
|
||||
typedef unsigned long FMSAMPLE_MIX;
|
||||
#endif
|
||||
#if (FM_OUTPUT_BIT==8)
|
||||
typedef unsigned char FMSAMPLE;
|
||||
typedef unsigned short FMSAMPLE_MIX;
|
||||
#endif
|
||||
|
||||
typedef void (*FM_TIMERHANDLER)(int n,int c,int cnt,double stepTime);
|
||||
typedef void (*FM_IRQHANDLER)(int n,int irq);
|
||||
/* FM_TIMERHANDLER : Stop or Start timer */
|
||||
/* int n = chip number */
|
||||
/* int c = Channel 0=TimerA,1=TimerB */
|
||||
/* int count = timer count (0=stop) */
|
||||
/* doube stepTime = step time of one count (sec.)*/
|
||||
|
||||
/* FM_IRQHHANDLER : IRQ level changing sense */
|
||||
/* int n = chip number */
|
||||
/* int irq = IRQ level 0=OFF,1=ON */
|
||||
|
||||
#if BUILD_YM2203
|
||||
/* -------------------- YM2203(OPN) Interface -------------------- */
|
||||
|
||||
/*
|
||||
** Initialize YM2203 emulator(s).
|
||||
**
|
||||
** 'num' is the number of virtual YM2203's to allocate
|
||||
** 'baseclock'
|
||||
** 'rate' is sampling rate
|
||||
** 'TimerHandler' timer callback handler when timer start and clear
|
||||
** 'IRQHandler' IRQ callback handler when changed IRQ level
|
||||
** return 0 = success
|
||||
*/
|
||||
int YM2203Init(int num, int baseclock, int rate,
|
||||
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
|
||||
|
||||
/*
|
||||
** shutdown the YM2203 emulators .. make sure that no sound system stuff
|
||||
** is touching our audio buffers ...
|
||||
*/
|
||||
void YM2203Shutdown(void);
|
||||
|
||||
/*
|
||||
** reset all chip registers for YM2203 number 'num'
|
||||
*/
|
||||
void YM2203ResetChip(int num);
|
||||
/*
|
||||
** update one of chip
|
||||
*/
|
||||
|
||||
void YM2203UpdateOne(int num, INT16 *buffer, int length);
|
||||
|
||||
/*
|
||||
** Write
|
||||
** return : InterruptLevel
|
||||
*/
|
||||
int YM2203Write(int n,int a,unsigned char v);
|
||||
/*
|
||||
** Read
|
||||
** return : InterruptLevel
|
||||
*/
|
||||
unsigned char YM2203Read(int n,int a);
|
||||
|
||||
/*
|
||||
** Timer OverFlow
|
||||
*/
|
||||
int YM2203TimerOver(int n, int c);
|
||||
|
||||
#endif /* BUILD_YM2203 */
|
||||
|
||||
#if BUILD_YM2608
|
||||
/* -------------------- YM2608(OPNA) Interface -------------------- */
|
||||
int YM2608Init(int num, int baseclock, int rate,
|
||||
void **pcmroma,int *pcmsizea,short *rhythmrom,int *rhythmpos,
|
||||
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
|
||||
void YM2608Shutdown(void);
|
||||
void YM2608ResetChip(int num);
|
||||
void YM2608UpdateOne(int num, INT16 **buffer, int length);
|
||||
|
||||
int YM2608Write(int n, int a,unsigned char v);
|
||||
unsigned char YM2608Read(int n,int a);
|
||||
int YM2608TimerOver(int n, int c );
|
||||
#endif /* BUILD_YM2608 */
|
||||
|
||||
#if (BUILD_YM2610||BUILD_YM2610B)
|
||||
/* -------------------- YM2610(OPNB) Interface -------------------- */
|
||||
int YM2610Init(int num, int baseclock, int rate,
|
||||
void **pcmroma,int *pcmasize,void **pcmromb,int *pcmbsize,
|
||||
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
|
||||
void YM2610Shutdown(void);
|
||||
void YM2610ResetChip(int num);
|
||||
void YM2610UpdateOne(int num, INT16 **buffer, int length);
|
||||
#if BUILD_YM2610B
|
||||
void YM2610BUpdateOne(int num, INT16 **buffer, int length);
|
||||
#endif
|
||||
|
||||
int YM2610Write(int n, int a,unsigned char v);
|
||||
unsigned char YM2610Read(int n,int a);
|
||||
int YM2610TimerOver(int n, int c );
|
||||
|
||||
#endif /* BUILD_YM2610 */
|
||||
|
||||
#if BUILD_YM2612
|
||||
int YM2612Init(int num, int baseclock, int rate,
|
||||
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
|
||||
void YM2612Shutdown(void);
|
||||
void YM2612ResetChip(int num);
|
||||
void YM2612UpdateOne(int num, INT16 **buffer, int length);
|
||||
int YM2612Write(int n, int a,unsigned char v);
|
||||
unsigned char YM2612Read(int n,int a);
|
||||
int YM2612TimerOver(int n, int c );
|
||||
|
||||
#endif /* BUILD_YM2612 */
|
||||
|
||||
#if BUILD_YM2151
|
||||
/* -------------------- YM2151(OPM) Interface -------------------- */
|
||||
int OPMInit(int num, int baseclock, int rate,
|
||||
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);
|
||||
void OPMShutdown(void);
|
||||
void OPMResetChip(int num);
|
||||
|
||||
void OPMUpdateOne(int num, INT16 **buffer, int length );
|
||||
/* ---- set callback hander when port CT0/1 write ----- */
|
||||
/* CT.bit0 = CT0 , CT.bit1 = CT1 */
|
||||
/*
|
||||
typedef void (*mem_write_handler)(int offset,int data);
|
||||
*/
|
||||
void OPMSetPortHander(int n,mem_write_handler PortWrite);
|
||||
/* JB 981119 - so it will match MAME's memory write functions scheme*/
|
||||
|
||||
int YM2151Write(int n,int a,unsigned char v);
|
||||
unsigned char YM2151Read(int n,int a);
|
||||
int YM2151TimerOver(int n,int c);
|
||||
#endif /* BUILD_YM2151 */
|
||||
|
||||
#endif /* _H_FM_FM_ */
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
//uint8 work_ram[0x10000]; /* 68K work RAM */
|
||||
//uint8 zram[0x2000]; /* Z80 work RAM */
|
||||
uint8 zbusreq; /* /BUSREQ from Z80 */
|
||||
uint8 zreset; /* /RESET to Z80 */
|
||||
uint8 zbusack; /* /BUSACK to Z80 */
|
||||
uint8 zirq; /* /IRQ to Z80 */
|
||||
uint32 zbank; /* Address of Z80 bank window */
|
||||
uint8 gen_running;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void gen_init(void)
|
||||
{
|
||||
sound_init();
|
||||
memset(&snd, 0, sizeof(snd));
|
||||
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
m68k_pulse_reset();
|
||||
error("PC:%08X\tSP:%08X\n", m68k_get_reg(NULL,M68K_REG_PC), m68k_get_reg(NULL,M68K_REG_SP));
|
||||
gen_running = 1;
|
||||
}
|
||||
|
||||
void gen_reset(void)
|
||||
{
|
||||
/* Clear RAM */
|
||||
memset(work_ram, 0, WORK_RAM_SIZE);
|
||||
memset(zram, 0, Z_RAM_SIZE);
|
||||
|
||||
gen_running = 1;
|
||||
zreset = 0; /* Z80 is reset */
|
||||
zbusreq = 0; /* Z80 has control of the Z bus */
|
||||
zbusack = 1; /* Z80 is busy using the Z bus */
|
||||
zbank = 0; /* Assume default bank is 000000-007FFF */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
|
||||
io_reset();
|
||||
|
||||
/* Reset the 68000 emulator */
|
||||
m68k_pulse_reset();
|
||||
error("PC:%08X\tSP:%08X\n", m68k_get_reg(NULL,M68K_REG_PC), m68k_get_reg(NULL,M68K_REG_SP));
|
||||
z80_reset(0);
|
||||
z80_set_irq_callback(z80_irq_callback);
|
||||
}
|
||||
|
||||
void gen_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Print 68K and Z80 state */
|
||||
error("\n");
|
||||
error("\nPC:%08X\tSP:%08X\tSR:%04X\n", m68k_get_reg(NULL,M68K_REG_PC), m68k_get_reg(NULL,M68K_REG_SP), m68k_get_reg(NULL, M68K_REG_SR));
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
error("D%d:%08X\tA%d:%08X\n",
|
||||
i, m68k_get_reg(NULL, M68K_REG_D0+i),
|
||||
i, m68k_get_reg(NULL, M68K_REG_A0+i));
|
||||
}
|
||||
|
||||
error("\n");
|
||||
error("PC:%04X\tSP:%04X\n", z80_get_reg(Z80_PC), z80_get_reg(Z80_SP));
|
||||
error("AF:%04X\tAF:%04X\n", z80_get_reg(Z80_AF), z80_get_reg(Z80_AF2));
|
||||
error("BC:%04X\tBC:%04X\n", z80_get_reg(Z80_BC), z80_get_reg(Z80_BC2));
|
||||
error("DE:%04X\tDE:%04X\n", z80_get_reg(Z80_DE), z80_get_reg(Z80_DE2));
|
||||
error("HL:%04X\tHL:%04X\n", z80_get_reg(Z80_HL), z80_get_reg(Z80_HL2));
|
||||
error("IX:%04X\tIY:%04X\n", z80_get_reg(Z80_IX), z80_get_reg(Z80_IY));
|
||||
error("\n");
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Bus controller chip functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int gen_busack_r(void)
|
||||
{
|
||||
return (zbusack & 1);
|
||||
}
|
||||
|
||||
void gen_busreq_w(int state)
|
||||
{
|
||||
zbusreq = (state & 1);
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
|
||||
if(zbusreq == 0 && zreset == 1)
|
||||
{
|
||||
z80_execute(32);
|
||||
}
|
||||
}
|
||||
|
||||
void gen_reset_w(int state)
|
||||
{
|
||||
zreset = (state & 1);
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
|
||||
if(zreset == 0)
|
||||
{
|
||||
if(snd.enabled)
|
||||
{
|
||||
YM2612ResetChip(0);
|
||||
}
|
||||
|
||||
z80_reset(0);
|
||||
z80_set_irq_callback(z80_irq_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gen_bank_w(int state)
|
||||
{
|
||||
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int z80_irq_callback(int param)
|
||||
{
|
||||
zirq = 0;
|
||||
z80_set_irq_line(0, CLEAR_LINE);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
int vdp_int_ack_callback(int int_level)
|
||||
{
|
||||
switch(int_level)
|
||||
{
|
||||
case 4:
|
||||
hint_pending = 0;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
status &= ~0x0080;
|
||||
vint_pending = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
#ifndef _GENESIS_H_
|
||||
#define _GENESIS_H_
|
||||
|
||||
/* Global variables */
|
||||
//extern uint8 work_ram[0x10000];
|
||||
//extern uint8 zram[0x2000];
|
||||
extern uint8 zbusreq;
|
||||
extern uint8 zbusack;
|
||||
extern uint8 zreset;
|
||||
extern uint8 zirq;
|
||||
extern uint32 zbank;
|
||||
extern uint8 gen_running;
|
||||
|
||||
/* Function prototypes */
|
||||
void gen_init(void);
|
||||
void gen_reset(void);
|
||||
void gen_shutdown(void);
|
||||
int gen_busack_r(void);
|
||||
void gen_busreq_w(int state);
|
||||
void gen_reset_w(int state);
|
||||
void gen_bank_w(int state);
|
||||
//void bswap(uint8 *mem, int length);
|
||||
int z80_irq_callback(int param);
|
||||
void m68k_irq_ack_callback(int int_level);
|
||||
|
||||
#endif /* _GEN_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,68 +0,0 @@
|
|||
const uint8 cycle2hc32[488] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05,
|
||||
0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A,
|
||||
0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10,
|
||||
0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16,
|
||||
0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B,
|
||||
0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21,
|
||||
0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26,
|
||||
0x27, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
|
||||
0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32,
|
||||
0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37,
|
||||
0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3B, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D,
|
||||
0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42,
|
||||
0x43, 0x43, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48,
|
||||
0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E,
|
||||
0x4E, 0x4E, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53,
|
||||
0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59,
|
||||
0x59, 0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5E, 0x5E, 0x5E, 0x5F,
|
||||
0x5F, 0x5F, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64,
|
||||
0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6A,
|
||||
0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
|
||||
0x70, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
|
||||
0x75, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B,
|
||||
0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80,
|
||||
0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
|
||||
0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8A, 0x8A, 0x8A, 0x8B, 0x8B, 0x8B,
|
||||
0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91,
|
||||
0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0xE9, 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC,
|
||||
0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1,
|
||||
0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF7, 0xF7,
|
||||
0xF7, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD,
|
||||
0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
const uint8 cycle2hc40[488] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
|
||||
0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D,
|
||||
0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14,
|
||||
0x14, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B,
|
||||
0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22,
|
||||
0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29,
|
||||
0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30,
|
||||
0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36,
|
||||
0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
|
||||
0x3E, 0x3E, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44,
|
||||
0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B,
|
||||
0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4F, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52,
|
||||
0x53, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59,
|
||||
0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, 0x5F, 0x5F, 0x60, 0x60,
|
||||
0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67,
|
||||
0x67, 0x68, 0x68, 0x69, 0x69, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E,
|
||||
0x6E, 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75,
|
||||
0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C,
|
||||
0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x83,
|
||||
0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8A,
|
||||
0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x8F, 0x90, 0x90, 0x90,
|
||||
0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x97, 0x97,
|
||||
0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9E,
|
||||
0x9F, 0x9F, 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2, 0xA3, 0xA3, 0xA4, 0xA4, 0xA4, 0xA5, 0xA5,
|
||||
0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA8, 0xA8, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAB, 0xAB, 0xAC, 0xAC,
|
||||
0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAF, 0xAF, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB3, 0xB3,
|
||||
0xB4, 0xB4, 0xB4, 0xB5, 0xB5, 0xB6, 0xB6, 0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7,
|
||||
0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE,
|
||||
0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5,
|
||||
0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC,
|
||||
0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF,
|
||||
};
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
|
||||
#ifndef _HVC_H_
|
||||
#define _HVC_H_
|
||||
|
||||
/* V counter values for NTSC 192-line display */
|
||||
const uint8 vc_ntsc_192[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
|
||||
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 224-line display */
|
||||
const uint8 vc_ntsc_224[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
|
||||
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 240-line display */
|
||||
const uint8 vc_ntsc_240[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
|
||||
};
|
||||
|
||||
/* V counter values for PAL 192-line display */
|
||||
const uint8 vc_pal_192[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2,
|
||||
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 224-line display */
|
||||
const uint8 vc_pal_224[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 240-line display */
|
||||
const uint8 vc_pal_240[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
||||
const uint8 hc_256[171] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* H counter values for a 320-pixel wide display (442 pixels max.) */
|
||||
const uint8 hc_320[211] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
|
||||
0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
uint8 *vc_table[6] = {
|
||||
vc_ntsc_192,
|
||||
vc_ntsc_224,
|
||||
vc_ntsc_240,
|
||||
vc_pal_192,
|
||||
vc_pal_224,
|
||||
vc_pal_240
|
||||
};
|
||||
|
||||
uint8 *hc_table[2] = {
|
||||
hc_256,
|
||||
hc_320,
|
||||
};
|
||||
|
||||
#endif /* _HVC_H_ */
|
||||
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
io.c
|
||||
I/O controller chip emulation
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
port_t port[3];
|
||||
uint8 io_reg[0x10];
|
||||
|
||||
|
||||
void io_reset(void)
|
||||
{
|
||||
/* I/O register default settings */
|
||||
uint8 io_def[0x10] =
|
||||
{
|
||||
0xA0,
|
||||
0x7F, 0x7F, 0x7F,
|
||||
0x00, 0x00, 0x00,
|
||||
0xFF, 0x00, 0x00,
|
||||
0xFF, 0x00, 0x00,
|
||||
0xFB, 0x00, 0x00,
|
||||
};
|
||||
|
||||
/* Initialize I/O registers */
|
||||
memcpy(io_reg, io_def, 0x10);
|
||||
|
||||
/*
|
||||
Port A : 3B pad
|
||||
Port B : Unused
|
||||
Port C : Unused
|
||||
*/
|
||||
port[0].data_w = device_3b_w;
|
||||
port[0].data_r = device_3b_r;
|
||||
port[1].data_w = NULL;
|
||||
port[1].data_r = NULL;
|
||||
port[2].data_w = NULL;
|
||||
port[2].data_r = NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* I/O chip functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void gen_io_w(int offset, int value)
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case 0x01: /* Port A Data */
|
||||
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
||||
io_reg[offset] = value;
|
||||
if(port[0].data_w) port[0].data_w(value);
|
||||
return;
|
||||
|
||||
case 0x02: /* Port B Data */
|
||||
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
||||
io_reg[offset] = value;
|
||||
if(port[1].data_w) port[1].data_w(value);
|
||||
return;
|
||||
|
||||
case 0x03: /* Port C Data */
|
||||
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
||||
io_reg[offset] = value;
|
||||
if(port[2].data_w) port[2].data_w(value);
|
||||
return;
|
||||
|
||||
case 0x04: /* Port A Ctrl */
|
||||
case 0x05: /* Port B Ctrl */
|
||||
case 0x06: /* Port C Ctrl */
|
||||
io_reg[offset] = value & 0xFF;
|
||||
break;
|
||||
|
||||
case 0x07: /* Port A TxData */
|
||||
case 0x0A: /* Port B TxData */
|
||||
case 0x0D: /* Port C TxData */
|
||||
io_reg[offset] = value;
|
||||
break;
|
||||
|
||||
case 0x09: /* Port A S-Ctrl */
|
||||
case 0x0C: /* Port B S-Ctrl */
|
||||
case 0x0F: /* Port C S-Ctrl */
|
||||
io_reg[offset] = (value & 0xF8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int gen_io_r(int offset)
|
||||
{
|
||||
uint8 temp;
|
||||
uint8 has_scd = 0x20; /* No Sega CD unit attached */
|
||||
uint8 gen_ver = 0x00; /* Version 0 hardware */
|
||||
|
||||
switch(offset)
|
||||
{
|
||||
case 0x00: /* Version */
|
||||
switch(rom_version())
|
||||
{
|
||||
case 'J':
|
||||
temp = 0x00;
|
||||
break;
|
||||
case 'U':
|
||||
temp = 0x80;
|
||||
break;
|
||||
case 'E':
|
||||
temp = 0xC0;
|
||||
break;
|
||||
case 'A':
|
||||
temp = 0xC0;
|
||||
break;
|
||||
case 'B':
|
||||
temp = 0xC0;
|
||||
break;
|
||||
case '4':
|
||||
temp = 0x80;
|
||||
break;
|
||||
default:
|
||||
temp = 0x80;
|
||||
break;
|
||||
}
|
||||
return (temp | has_scd | gen_ver);
|
||||
break;
|
||||
|
||||
case 0x01: /* Port A Data */
|
||||
if(port[0].data_r) return ((io_reg[offset] & 0x80) | port[0].data_r());
|
||||
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
||||
|
||||
case 0x02: /* Port B Data */
|
||||
if(port[1].data_r) return ((io_reg[offset] & 0x80) | port[1].data_r());
|
||||
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
||||
|
||||
case 0x03: /* Port C Data */
|
||||
if(port[2].data_r) return ((io_reg[offset] & 0x80) | port[2].data_r());
|
||||
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
||||
}
|
||||
|
||||
return (io_reg[offset]);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Input callbacks */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
uint8 pad_2b_r(void)
|
||||
{
|
||||
uint8 temp = 0x3F;
|
||||
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
||||
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
||||
if(input.pad[0] & INPUT_LEFT) temp &= ~0x04;
|
||||
if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
|
||||
if(input.pad[0] & INPUT_B) temp &= ~0x10;
|
||||
if(input.pad[0] & INPUT_C) temp &= ~0x20;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
static int th = 0;
|
||||
|
||||
uint8 device_3b_r(void)
|
||||
{
|
||||
uint8 temp = 0x3F;
|
||||
|
||||
if(th)
|
||||
{
|
||||
temp = 0x3f;
|
||||
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
||||
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
||||
if(input.pad[0] & INPUT_LEFT) temp &= ~0x04;
|
||||
if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
|
||||
if(input.pad[0] & INPUT_B) temp &= ~0x10;
|
||||
if(input.pad[0] & INPUT_C) temp &= ~0x20;
|
||||
return (temp | 0x40);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = 0x33;
|
||||
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
||||
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
||||
if(input.pad[0] & INPUT_A) temp &= ~0x10;
|
||||
if(input.pad[0] & INPUT_START) temp &= ~0x20;
|
||||
return (temp);
|
||||
}
|
||||
}
|
||||
|
||||
void device_3b_w(uint8 data)
|
||||
{
|
||||
th = (data & 0x40);
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef _IO_H_
|
||||
#define _IO_H_
|
||||
|
||||
/*
|
||||
|
||||
void io_reset(void);
|
||||
void io_set_version(int export, int pal, int fdd, int n);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*data_w)(uint8 data);
|
||||
uint8 (*data_r)(void);
|
||||
} port_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 state;
|
||||
} t_input_3b;
|
||||
|
||||
/* Global variables */
|
||||
extern port_t port[3];
|
||||
extern uint8 io_reg[0x10];
|
||||
|
||||
/* Function prototypes */
|
||||
extern void io_reset(void);
|
||||
extern void gen_io_w(int offset, int value);
|
||||
extern int gen_io_r(int offset);
|
||||
extern uint8 pad_2b_r(void);
|
||||
extern uint8 device_3b_r(void);
|
||||
extern void device_3b_w(uint8 data);
|
||||
|
||||
#endif /* _IO_H_ */
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
#ifndef keyboard_osd_h_
|
||||
#define keyboard_osd_h_
|
||||
|
||||
extern bool virtualkeyboardIsActive(void);
|
||||
extern void drawVirtualkeyboard(void);
|
||||
extern void toggleVirtualkeyboard(bool keepOn);
|
||||
extern void handleVirtualkeyboard(void);
|
||||
|
||||
extern bool callibrationActive(void);
|
||||
extern int handleCallibration(uint16_t bClick);
|
||||
|
||||
extern bool menuActive(void);
|
||||
extern char * menuSelection(void);
|
||||
extern void toggleMenu(bool on);
|
||||
extern int handleMenu(uint16_t bClick);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,339 +0,0 @@
|
|||
#ifndef M68K__HEADER
|
||||
#define M68K__HEADER
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.3
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other lisencing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
* http://kstenerud.cjb.net
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ GENERAL DEFINES =========================== */
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/* There are 7 levels of interrupt to the 68K.
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
*/
|
||||
#define M68K_IRQ_NONE 0
|
||||
#define M68K_IRQ_1 1
|
||||
#define M68K_IRQ_2 2
|
||||
#define M68K_IRQ_3 3
|
||||
#define M68K_IRQ_4 4
|
||||
#define M68K_IRQ_5 5
|
||||
#define M68K_IRQ_6 6
|
||||
#define M68K_IRQ_7 7
|
||||
|
||||
|
||||
/* Special interrupt acknowledge values.
|
||||
* Use these as special returns from the interrupt acknowledge callback
|
||||
* (specified later in this header).
|
||||
*/
|
||||
|
||||
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
|
||||
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
|
||||
* acknowledge cycle instead of DTACK.
|
||||
*/
|
||||
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
|
||||
|
||||
/* Causes the spurious interrupt vector (0x18) to be taken
|
||||
* This happens in a real 68K if BERR is asserted during the interrupt
|
||||
* acknowledge cycle (i.e. no devices responded to the acknowledge).
|
||||
*/
|
||||
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
|
||||
|
||||
|
||||
/* CPU types for use in m68k_set_cpu_type() */
|
||||
enum
|
||||
{
|
||||
M68K_CPU_TYPE_INVALID,
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020,
|
||||
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
|
||||
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
|
||||
};
|
||||
|
||||
/* Registers used by m68k_get_reg() and m68k_set_reg() */
|
||||
typedef enum
|
||||
{
|
||||
/* Real registers */
|
||||
M68K_REG_D0, /* Data registers */
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0, /* Address registers */
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC, /* Program Counter */
|
||||
M68K_REG_SR, /* Status Register */
|
||||
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||
M68K_REG_USP, /* User Stack Pointer */
|
||||
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||
M68K_REG_MSP, /* Master Stack Pointer */
|
||||
M68K_REG_SFC, /* Source Function Code */
|
||||
M68K_REG_DFC, /* Destination Function Code */
|
||||
M68K_REG_VBR, /* Vector Base Register */
|
||||
M68K_REG_CACR, /* Cache Control Register */
|
||||
M68K_REG_CAAR, /* Cache Address Register */
|
||||
|
||||
/* Assumed registers */
|
||||
/* These are cheat registers which emulate the 1-longword prefetch
|
||||
* present in the 68000 and 68010.
|
||||
*/
|
||||
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||
|
||||
/* Convenience registers */
|
||||
M68K_REG_PPC, /* Previous value in the program counter */
|
||||
M68K_REG_IR, /* Instruction register */
|
||||
M68K_REG_CPU_TYPE /* Type of CPU being run */
|
||||
} m68k_register_t;
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* You will have to implement these functions */
|
||||
|
||||
/* read/write functions called by the CPU to access memory.
|
||||
* while values used are 32 bits, only the appropriate number
|
||||
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
|
||||
* of value should be written to memory).
|
||||
*
|
||||
* NOTE: I have separated the immediate and PC-relative memory fetches
|
||||
* from the other memory fetches because some systems require
|
||||
* differentiation between PROGRAM and DATA fetches (usually
|
||||
* for security setups such as encryption).
|
||||
* This separation can either be achieved by setting
|
||||
* M68K_SEPARATE_READS in m68kconf.h and defining
|
||||
* the read functions, or by setting M68K_EMULATE_FC and
|
||||
* making a function code callback function.
|
||||
* Using the callback offers better emulation coverage
|
||||
* because you can also monitor whether the CPU is in SYSTEM or
|
||||
* USER mode, but it is also slower.
|
||||
*/
|
||||
|
||||
/* Read from anywhere */
|
||||
unsigned int m68k_read_memory_8(unsigned int address);
|
||||
unsigned int m68k_read_memory_16(unsigned int address);
|
||||
unsigned int m68k_read_memory_32(unsigned int address);
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
unsigned int m68k_read_immediate_16(unsigned int address);
|
||||
unsigned int m68k_read_immediate_32(unsigned int address);
|
||||
|
||||
/* Read data relative to the PC */
|
||||
unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||
|
||||
/* Memory access for the disassembler */
|
||||
unsigned int m68k_read_disassembler_8 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_16 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_32 (unsigned int address);
|
||||
|
||||
/* Write to anywhere */
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== CALLBACKS =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* These functions allow you to set callbacks to the host when specific events
|
||||
* occur. Note that you must enable the corresponding value in m68kconf.h
|
||||
* in order for these to do anything useful.
|
||||
* Note: I have defined default callbacks which are used if you have enabled
|
||||
* the corresponding #define in m68kconf.h but either haven't assigned a
|
||||
* callback or have assigned a callback of NULL.
|
||||
*/
|
||||
|
||||
/* Set the callback for an interrupt acknowledge.
|
||||
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
|
||||
* The CPU will call the callback with the interrupt level being acknowledged.
|
||||
* The host program must return either a vector from 0x02-0xff, or one of the
|
||||
* special interrupt acknowledge values specified earlier in this header.
|
||||
* If this is not implemented, the CPU will always assume an autovectored
|
||||
* interrupt, and will automatically clear the interrupt request when it
|
||||
* services the interrupt.
|
||||
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
|
||||
*/
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level));
|
||||
|
||||
|
||||
/* Set the callback for a breakpoint acknowledge (68010+).
|
||||
* You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
|
||||
* The CPU will call the callback with whatever was in the data field of the
|
||||
* BKPT instruction for 68020+, or 0 for 68010.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
|
||||
|
||||
|
||||
/* Set the callback for the RESET instruction.
|
||||
* You must enable M68K_EMULATE_RESET in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a RESET instruction.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void));
|
||||
|
||||
|
||||
/* Set the callback for informing of a large PC change.
|
||||
* You must enable M68K_MONITOR_PC in m68kconf.h.
|
||||
* The CPU calls this callback with the new PC value every time the PC changes
|
||||
* by a large value (currently set for changes by longwords).
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
|
||||
|
||||
|
||||
/* Set the callback for CPU function code changes.
|
||||
* You must enable M68K_EMULATE_FC in m68kconf.h.
|
||||
* The CPU calls this callback with the function code before every memory
|
||||
* access to set the CPU's function code according to what kind of memory
|
||||
* access it is (supervisor/user, program/data and such).
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||
|
||||
|
||||
/* Set a callback for the instruction cycle of the CPU.
|
||||
* You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
|
||||
* The CPU calls this callback just before fetching the opcode in the
|
||||
* instruction cycle.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Use this function to set the CPU type you want to emulate.
|
||||
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
|
||||
* M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
|
||||
*/
|
||||
void m68k_set_cpu_type(unsigned int cpu_type);
|
||||
|
||||
/* Pulse the RESET pin on the CPU.
|
||||
* You *MUST* reset the CPU at least once to initialize the emulation
|
||||
* Note: If you didn't call m68k_set_cpu_type() before resetting
|
||||
* the CPU for the first time, the CPU will be set to
|
||||
* M68K_CPU_TYPE_68000.
|
||||
*/
|
||||
void m68k_pulse_reset(void);
|
||||
|
||||
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||
int m68k_execute(int num_cycles);
|
||||
|
||||
/* These functions let you read/write/modify the number of cycles left to run
|
||||
* while m68k_execute() is running.
|
||||
* These are useful if the 68k accesses a memory-mapped port on another device
|
||||
* that requires immediate processing by another CPU.
|
||||
*/
|
||||
int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||
int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||
void m68k_end_timeslice(void); /* End timeslice now */
|
||||
|
||||
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
* Setting IRQ to 0 will clear an interrupt request.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level);
|
||||
|
||||
|
||||
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||
void m68k_pulse_halt(void);
|
||||
|
||||
|
||||
/* Context switching to allow multiple CPUs */
|
||||
|
||||
/* Get the size of the cpu context in bytes */
|
||||
unsigned int m68k_context_size(void);
|
||||
|
||||
/* Get a cpu context */
|
||||
unsigned int m68k_get_context(void* dst);
|
||||
|
||||
/* set the current cpu context */
|
||||
void m68k_set_context(void* dst);
|
||||
|
||||
/* Save the current cpu context to disk.
|
||||
* You must provide a function pointer of the form:
|
||||
* void save_value(char* identifier, unsigned int value)
|
||||
*/
|
||||
void m68k_save_context( void (*save_value)(char* identifier, unsigned int value));
|
||||
|
||||
/* Load a cpu context from disk.
|
||||
* You must provide a function pointer of the form:
|
||||
* unsigned int load_value(char* identifier)
|
||||
*/
|
||||
void m68k_load_context(unsigned int (*load_value)(char* identifier));
|
||||
|
||||
|
||||
|
||||
/* Peek at the internals of a CPU context. This can either be a context
|
||||
* retrieved using m68k_get_context() or the currently running context.
|
||||
* If context is NULL, the currently running CPU context will be used.
|
||||
*/
|
||||
unsigned int m68k_get_reg(void* context, m68k_register_t reg);
|
||||
|
||||
/* Poke values into the internals of the currently running CPU context */
|
||||
void m68k_set_reg(m68k_register_t reg, unsigned int value);
|
||||
|
||||
/* Check if an instruction is valid for the specified CPU type */
|
||||
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
|
||||
|
||||
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
|
||||
* disassembly in str_buff and returns the size of the instruction in bytes.
|
||||
*/
|
||||
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Import the configuration for this build */
|
||||
#include "m68kconf.h"
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68K__HEADER */
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.3
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other lisencing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
* http://kstenerud.cjb.net
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef M68KCONF__HEADER
|
||||
#define M68KCONF__HEADER
|
||||
|
||||
|
||||
/* Configuration switches.
|
||||
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
|
||||
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
|
||||
* or macro you specify, rather than using callback functions whose pointer
|
||||
* must be passed in using m68k_set_xxx_callback().
|
||||
*/
|
||||
#define OPT_OFF 0
|
||||
#define OPT_ON 1
|
||||
#define OPT_SPECIFY_HANDLER 2
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
|
||||
* to OPT_ON and use m68kmame.h to configure the 68k core.
|
||||
*/
|
||||
#ifndef M68K_COMPILE_FOR_MAME
|
||||
#define M68K_COMPILE_FOR_MAME OPT_OFF
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
#include "m68kmame.h"
|
||||
#else
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Turn on if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_010 OPT_ON
|
||||
#define M68K_EMULATE_EC020 OPT_ON
|
||||
#define M68K_EMULATE_020 OPT_ON
|
||||
|
||||
|
||||
/* If on, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
|
||||
|
||||
/* If on, CPU will call the interrupt acknowledge callback when it services an
|
||||
* interrupt.
|
||||
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||
* auto-clear when the interrupt is serviced.
|
||||
*/
|
||||
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
|
||||
#define M68K_INT_ACK_CALLBACK(A) vdp_int_ack_callback(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
* a breakpoint instruction and it is running a 68010+.
|
||||
*/
|
||||
#define M68K_EMULATE_BKPT_ACK OPT_OFF
|
||||
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
|
||||
|
||||
|
||||
/* If on, the CPU will monitor the trace flags and take trace exceptions
|
||||
*/
|
||||
#define M68K_EMULATE_TRACE OPT_OFF
|
||||
|
||||
|
||||
/* If on, CPU will call the output reset callback when it encounters a reset
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_EMULATE_RESET OPT_OFF
|
||||
#define M68K_RESET_CALLBACK() your_reset_handler_function()
|
||||
|
||||
|
||||
/* If on, CPU will call the set fc callback on every memory access to
|
||||
* differentiate between user/supervisor, program/data access like a real
|
||||
* 68000 would. This should be enabled and the callback should be set if you
|
||||
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||
* to read/write data from different address spaces)
|
||||
*/
|
||||
#define M68K_EMULATE_FC OPT_OFF
|
||||
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the pc changed callback when it changes the PC by a
|
||||
* large value. This allows host programs to be nicer when it comes to
|
||||
* fetching immediate data and instructions on a banked memory system.
|
||||
*/
|
||||
#define M68K_MONITOR_PC OPT_OFF
|
||||
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the instruction hook callback before every
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
||||
|
||||
|
||||
/* If on, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||
|
||||
|
||||
/* If on, the CPU will generate address error exceptions if it tries to
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: Do not enable this! It is not working!
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||
|
||||
|
||||
/* Turn on to enable logging of illegal instruction calls.
|
||||
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
|
||||
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
|
||||
*/
|
||||
#define M68K_LOG_ENABLE OPT_OFF
|
||||
#define M68K_LOG_1010_1111 OPT_OFF
|
||||
#define M68K_LOG_FILEHANDLE some_file_handle
|
||||
|
||||
|
||||
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||
|
||||
/* The following options set optimizations that violate the current ANSI
|
||||
* standard, but will be compliant under the forthcoming C9X standard.
|
||||
*/
|
||||
|
||||
|
||||
/* If on, the enulation core will use 64-bit integers to speed up some
|
||||
* operations.
|
||||
*/
|
||||
#define M68K_USE_64_BIT OPT_OFF
|
||||
|
||||
|
||||
/* Set to your compiler's static inline keyword to enable it, or
|
||||
* set it to blank to disable it.
|
||||
* If you define INLINE in the makefile, it will override this value.
|
||||
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
|
||||
*/
|
||||
#ifndef INLINE
|
||||
#define INLINE static __inline__
|
||||
#endif /* INLINE */
|
||||
|
||||
|
||||
/* If your environment requires special prefixes for system callback functions
|
||||
* such as the argument to qsort(), then set them here or in the makefile.
|
||||
*/
|
||||
#ifndef DECL_SPEC
|
||||
#define DECL_SPEC
|
||||
#endif
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68KCONF__HEADER */
|
||||
|
|
@ -1,894 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#if 0
|
||||
static const char* copyright_notice =
|
||||
"MUSASHI\n"
|
||||
"Version 3.3 (2001-01-29)\n"
|
||||
"A portable Motorola M680x0 processor emulation engine.\n"
|
||||
"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
|
||||
"\n"
|
||||
"This code may be freely used for non-commercial purpooses as long as this\n"
|
||||
"copyright notice remains unaltered in the source code and any binary files\n"
|
||||
"containing this code in compiled form.\n"
|
||||
"\n"
|
||||
"All other lisencing terms must be negotiated with the author\n"
|
||||
"(Karl Stenerud).\n"
|
||||
"\n"
|
||||
"The latest version of this code can be obtained at:\n"
|
||||
"http://kstenerud.cjb.net\n"
|
||||
;
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= NOTES ================================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#include "m68kops.h"
|
||||
#include "m68kcpu.h"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= DATA ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
int m68ki_initial_cycles;
|
||||
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||
uint m68ki_tracing = 0;
|
||||
uint m68ki_address_space;
|
||||
|
||||
#ifdef M68K_LOG_ENABLE
|
||||
char* m68ki_cpu_names[9] =
|
||||
{
|
||||
"Invalid CPU",
|
||||
"M68000",
|
||||
"M68010",
|
||||
"Invalid CPU",
|
||||
"M68EC020"
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"M68020"
|
||||
};
|
||||
#endif /* M68K_LOG_ENABLE */
|
||||
|
||||
/* The CPU core */
|
||||
m68ki_cpu_core m68ki_cpu = {0};
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
jmp_buf m68ki_address_error_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
/* Used by shift & rotate instructions */
|
||||
const uint8 m68ki_shift_8_table[65] =
|
||||
{
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
const uint16 m68ki_shift_16_table[65] =
|
||||
{
|
||||
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
|
||||
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff
|
||||
};
|
||||
const uint m68ki_shift_32_table[65] =
|
||||
{
|
||||
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
|
||||
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
||||
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
|
||||
0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
|
||||
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
|
||||
0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
|
||||
};
|
||||
|
||||
|
||||
/* Number of clock cycles to use for exception processing.
|
||||
* I used 4 for any vectors that are undocumented for processing times.
|
||||
*/
|
||||
const uint8 m68ki_exception_cycle_table[3][256] =
|
||||
{
|
||||
{ /* 000 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
50, /* 2: Bus Error (unemulated) */
|
||||
50, /* 3: Address Error (unemulated) */
|
||||
34, /* 4: Illegal Instruction */
|
||||
38, /* 5: Divide by Zero -- ASG: changed from 42 */
|
||||
40, /* 6: CHK -- ASG: chanaged from 44 */
|
||||
34, /* 7: TRAPV */
|
||||
34, /* 8: Privilege Violation */
|
||||
34, /* 9: Trace */
|
||||
4, /* 10: 1010 */
|
||||
4, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
44, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
44, /* 24: Spurious Interrupt */
|
||||
44, /* 25: Level 1 Interrupt Autovector */
|
||||
44, /* 26: Level 2 Interrupt Autovector */
|
||||
44, /* 27: Level 3 Interrupt Autovector */
|
||||
44, /* 28: Level 4 Interrupt Autovector */
|
||||
44, /* 29: Level 5 Interrupt Autovector */
|
||||
44, /* 30: Level 6 Interrupt Autovector */
|
||||
44, /* 31: Level 7 Interrupt Autovector */
|
||||
34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
|
||||
34, /* 33: TRAP #1 */
|
||||
34, /* 34: TRAP #2 */
|
||||
34, /* 35: TRAP #3 */
|
||||
34, /* 36: TRAP #4 */
|
||||
34, /* 37: TRAP #5 */
|
||||
34, /* 38: TRAP #6 */
|
||||
34, /* 39: TRAP #7 */
|
||||
34, /* 40: TRAP #8 */
|
||||
34, /* 41: TRAP #9 */
|
||||
34, /* 42: TRAP #10 */
|
||||
34, /* 43: TRAP #11 */
|
||||
34, /* 44: TRAP #12 */
|
||||
34, /* 45: TRAP #13 */
|
||||
34, /* 46: TRAP #14 */
|
||||
34, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
},
|
||||
{ /* 010 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
126, /* 2: Bus Error (unemulated) */
|
||||
126, /* 3: Address Error (unemulated) */
|
||||
38, /* 4: Illegal Instruction */
|
||||
44, /* 5: Divide by Zero */
|
||||
44, /* 6: CHK */
|
||||
34, /* 7: TRAPV */
|
||||
38, /* 8: Privilege Violation */
|
||||
38, /* 9: Trace */
|
||||
4, /* 10: 1010 */
|
||||
4, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
44, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
46, /* 24: Spurious Interrupt */
|
||||
46, /* 25: Level 1 Interrupt Autovector */
|
||||
46, /* 26: Level 2 Interrupt Autovector */
|
||||
46, /* 27: Level 3 Interrupt Autovector */
|
||||
46, /* 28: Level 4 Interrupt Autovector */
|
||||
46, /* 29: Level 5 Interrupt Autovector */
|
||||
46, /* 30: Level 6 Interrupt Autovector */
|
||||
46, /* 31: Level 7 Interrupt Autovector */
|
||||
38, /* 32: TRAP #0 */
|
||||
38, /* 33: TRAP #1 */
|
||||
38, /* 34: TRAP #2 */
|
||||
38, /* 35: TRAP #3 */
|
||||
38, /* 36: TRAP #4 */
|
||||
38, /* 37: TRAP #5 */
|
||||
38, /* 38: TRAP #6 */
|
||||
38, /* 39: TRAP #7 */
|
||||
38, /* 40: TRAP #8 */
|
||||
38, /* 41: TRAP #9 */
|
||||
38, /* 42: TRAP #10 */
|
||||
38, /* 43: TRAP #11 */
|
||||
38, /* 44: TRAP #12 */
|
||||
38, /* 45: TRAP #13 */
|
||||
38, /* 46: TRAP #14 */
|
||||
38, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
},
|
||||
{ /* 020 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
50, /* 2: Bus Error (unemulated) */
|
||||
50, /* 3: Address Error (unemulated) */
|
||||
20, /* 4: Illegal Instruction */
|
||||
38, /* 5: Divide by Zero */
|
||||
40, /* 6: CHK */
|
||||
20, /* 7: TRAPV */
|
||||
34, /* 8: Privilege Violation */
|
||||
25, /* 9: Trace */
|
||||
20, /* 10: 1010 */
|
||||
20, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
30, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
30, /* 24: Spurious Interrupt */
|
||||
30, /* 25: Level 1 Interrupt Autovector */
|
||||
30, /* 26: Level 2 Interrupt Autovector */
|
||||
30, /* 27: Level 3 Interrupt Autovector */
|
||||
30, /* 28: Level 4 Interrupt Autovector */
|
||||
30, /* 29: Level 5 Interrupt Autovector */
|
||||
30, /* 30: Level 6 Interrupt Autovector */
|
||||
30, /* 31: Level 7 Interrupt Autovector */
|
||||
20, /* 32: TRAP #0 */
|
||||
20, /* 33: TRAP #1 */
|
||||
20, /* 34: TRAP #2 */
|
||||
20, /* 35: TRAP #3 */
|
||||
20, /* 36: TRAP #4 */
|
||||
20, /* 37: TRAP #5 */
|
||||
20, /* 38: TRAP #6 */
|
||||
20, /* 39: TRAP #7 */
|
||||
20, /* 40: TRAP #8 */
|
||||
20, /* 41: TRAP #9 */
|
||||
20, /* 42: TRAP #10 */
|
||||
20, /* 43: TRAP #11 */
|
||||
20, /* 44: TRAP #12 */
|
||||
20, /* 45: TRAP #13 */
|
||||
20, /* 46: TRAP #14 */
|
||||
20, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
}
|
||||
};
|
||||
|
||||
const uint8 m68ki_ea_idx_cycle_table[64] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* ..01.000 no memory indirect, base NULL */
|
||||
5, /* ..01..01 memory indirect, base NULL, outer NULL */
|
||||
7, /* ..01..10 memory indirect, base NULL, outer 16 */
|
||||
7, /* ..01..11 memory indirect, base NULL, outer 32 */
|
||||
0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
|
||||
2, /* ..10.000 no memory indirect, base 16 */
|
||||
7, /* ..10..01 memory indirect, base 16, outer NULL */
|
||||
9, /* ..10..10 memory indirect, base 16, outer 16 */
|
||||
9, /* ..10..11 memory indirect, base 16, outer 32 */
|
||||
0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
|
||||
6, /* ..11.000 no memory indirect, base 32 */
|
||||
11, /* ..11..01 memory indirect, base 32, outer NULL */
|
||||
13, /* ..11..10 memory indirect, base 32, outer 16 */
|
||||
13, /* ..11..11 memory indirect, base 32, outer 32 */
|
||||
0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== CALLBACKS ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Default callbacks used if the callback hasn't been set yet, or if the
|
||||
* callback is set to NULL
|
||||
*/
|
||||
|
||||
/* Interrupt acknowledge */
|
||||
static int default_int_ack_callback_data;
|
||||
static int default_int_ack_callback(int int_level)
|
||||
{
|
||||
default_int_ack_callback_data = int_level;
|
||||
CPU_INT_LEVEL = 0;
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
/* Breakpoint acknowledge */
|
||||
static unsigned int default_bkpt_ack_callback_data;
|
||||
static void default_bkpt_ack_callback(unsigned int data)
|
||||
{
|
||||
default_bkpt_ack_callback_data = data;
|
||||
}
|
||||
|
||||
/* Called when a reset instruction is executed */
|
||||
static void default_reset_instr_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called when the program counter changed by a large value */
|
||||
static unsigned int default_pc_changed_callback_data;
|
||||
static void default_pc_changed_callback(unsigned int new_pc)
|
||||
{
|
||||
default_pc_changed_callback_data = new_pc;
|
||||
}
|
||||
|
||||
/* Called every time there's bus activity (read/write to/from memory */
|
||||
static unsigned int default_set_fc_callback_data;
|
||||
static void default_set_fc_callback(unsigned int new_fc)
|
||||
{
|
||||
default_set_fc_callback_data = new_fc;
|
||||
}
|
||||
|
||||
/* Called every instruction cycle prior to execution */
|
||||
static void default_instr_hook_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Access the internals of the CPU */
|
||||
unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
|
||||
{
|
||||
m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
|
||||
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: return cpu->dar[0];
|
||||
case M68K_REG_D1: return cpu->dar[1];
|
||||
case M68K_REG_D2: return cpu->dar[2];
|
||||
case M68K_REG_D3: return cpu->dar[3];
|
||||
case M68K_REG_D4: return cpu->dar[4];
|
||||
case M68K_REG_D5: return cpu->dar[5];
|
||||
case M68K_REG_D6: return cpu->dar[6];
|
||||
case M68K_REG_D7: return cpu->dar[7];
|
||||
case M68K_REG_A0: return cpu->dar[8];
|
||||
case M68K_REG_A1: return cpu->dar[9];
|
||||
case M68K_REG_A2: return cpu->dar[10];
|
||||
case M68K_REG_A3: return cpu->dar[11];
|
||||
case M68K_REG_A4: return cpu->dar[12];
|
||||
case M68K_REG_A5: return cpu->dar[13];
|
||||
case M68K_REG_A6: return cpu->dar[14];
|
||||
case M68K_REG_A7: return cpu->dar[15];
|
||||
case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
|
||||
case M68K_REG_SR: return cpu->t1_flag |
|
||||
cpu->t0_flag |
|
||||
(cpu->s_flag << 11) |
|
||||
(cpu->m_flag << 11) |
|
||||
cpu->int_mask |
|
||||
((cpu->x_flag & XFLAG_SET) >> 4) |
|
||||
((cpu->n_flag & NFLAG_SET) >> 4) |
|
||||
((!cpu->not_z_flag) << 2) |
|
||||
((cpu->v_flag & VFLAG_SET) >> 6) |
|
||||
((cpu->c_flag & CFLAG_SET) >> 8);
|
||||
case M68K_REG_SP: return cpu->dar[15];
|
||||
case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
|
||||
case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
|
||||
case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
|
||||
case M68K_REG_SFC: return cpu->sfc;
|
||||
case M68K_REG_DFC: return cpu->dfc;
|
||||
case M68K_REG_VBR: return cpu->vbr;
|
||||
case M68K_REG_CACR: return cpu->cacr;
|
||||
case M68K_REG_CAAR: return cpu->caar;
|
||||
case M68K_REG_PREF_ADDR: return cpu->pref_addr;
|
||||
case M68K_REG_PREF_DATA: return cpu->pref_data;
|
||||
case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
|
||||
case M68K_REG_IR: return cpu->ir;
|
||||
case M68K_REG_CPU_TYPE:
|
||||
switch(cpu->cpu_type)
|
||||
{
|
||||
case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
|
||||
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
|
||||
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
|
||||
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
|
||||
}
|
||||
return M68K_CPU_TYPE_INVALID;
|
||||
default: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
|
||||
{
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
|
||||
case M68K_REG_SR: m68ki_set_sr(value); return;
|
||||
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_USP: if(FLAG_S)
|
||||
REG_USP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_ISP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_MSP: if(FLAG_S && FLAG_M)
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_MSP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_SFC: REG_SFC = value & 7; return;
|
||||
case M68K_REG_DFC: REG_DFC = value & 7; return;
|
||||
case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
|
||||
case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the callbacks */
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level))
|
||||
{
|
||||
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
|
||||
}
|
||||
|
||||
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
|
||||
{
|
||||
CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
|
||||
}
|
||||
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
|
||||
{
|
||||
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
|
||||
}
|
||||
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
|
||||
{
|
||||
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
|
||||
}
|
||||
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
/* Set the CPU type. */
|
||||
void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
{
|
||||
switch(cpu_type)
|
||||
{
|
||||
case M68K_CPU_TYPE_68000:
|
||||
CPU_TYPE = CPU_TYPE_000;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[0];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 2;
|
||||
CYC_DBCC_F_NOEXP = -2;
|
||||
CYC_DBCC_F_EXP = 2;
|
||||
CYC_SCC_R_FALSE = 2;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
CYC_RESET = 132;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68010:
|
||||
CPU_TYPE = CPU_TYPE_010;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[1];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[1];
|
||||
CYC_BCC_NOTAKE_B = -4;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 6;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
CYC_RESET = 130;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68EC020:
|
||||
CPU_TYPE = CPU_TYPE_EC020;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
CYC_RESET = 518;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68020:
|
||||
CPU_TYPE = CPU_TYPE_020;
|
||||
CPU_ADDRESS_MASK = 0xffffffff;
|
||||
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
CYC_RESET = 518;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute some instructions until we use up num_cycles clock cycles */
|
||||
/* ASG: removed per-instruction interrupt checks */
|
||||
int m68k_execute(int num_cycles)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(!CPU_STOPPED)
|
||||
{
|
||||
/* Set our pool of clock cycles available */
|
||||
SET_CYCLES(num_cycles);
|
||||
m68ki_initial_cycles = num_cycles;
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* Return point if we had an address error */
|
||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Main loop. Keep going until we run out of clock cycles */
|
||||
do
|
||||
{
|
||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Set the address space for reads */
|
||||
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Call external hook to peek at CPU */
|
||||
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Record previous program counter */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* Read an instruction and call its handler */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
|
||||
/* Trace m68k_exception, if necessary */
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
} while(GET_CYCLES() > 0);
|
||||
|
||||
/* set previous PC to current PC for the next entry into the loop */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* return how many clocks we used */
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
}
|
||||
|
||||
/* We get here if the CPU is stopped or halted */
|
||||
SET_CYCLES(0);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
return num_cycles;
|
||||
}
|
||||
|
||||
|
||||
int m68k_cycles_run(void)
|
||||
{
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
}
|
||||
|
||||
int m68k_cycles_remaining(void)
|
||||
{
|
||||
return GET_CYCLES();
|
||||
}
|
||||
|
||||
/* Change the timeslice */
|
||||
void m68k_modify_timeslice(int cycles)
|
||||
{
|
||||
m68ki_initial_cycles += cycles;
|
||||
ADD_CYCLES(cycles);
|
||||
}
|
||||
|
||||
|
||||
void m68k_end_timeslice(void)
|
||||
{
|
||||
m68ki_initial_cycles = GET_CYCLES();
|
||||
SET_CYCLES(0);
|
||||
}
|
||||
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
uint old_level = CPU_INT_LEVEL;
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
|
||||
/* A transition from < 7 to 7 always interrupts (NMI) */
|
||||
/* Note: Level 7 can also level trigger like a normal IRQ */
|
||||
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
|
||||
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
|
||||
else
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
{
|
||||
static uint emulation_initialized = 0;
|
||||
|
||||
/* The first call to this function initializes the opcode handler jump table */
|
||||
if(!emulation_initialized)
|
||||
{
|
||||
m68ki_build_opcode_table();
|
||||
m68k_set_int_ack_callback(NULL);
|
||||
m68k_set_bkpt_ack_callback(NULL);
|
||||
m68k_set_reset_instr_callback(NULL);
|
||||
m68k_set_pc_changed_callback(NULL);
|
||||
m68k_set_fc_callback(NULL);
|
||||
m68k_set_instr_hook_callback(NULL);
|
||||
|
||||
emulation_initialized = 1;
|
||||
}
|
||||
|
||||
|
||||
if(CPU_TYPE == 0) /* KW 990319 */
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
|
||||
/* Clear all stop levels and eat up all remaining cycles */
|
||||
CPU_STOPPED = 0;
|
||||
SET_CYCLES(0);
|
||||
|
||||
/* Turn off tracing */
|
||||
FLAG_T1 = FLAG_T0 = 0;
|
||||
m68ki_clear_trace();
|
||||
/* Interrupt mask to level 7 */
|
||||
FLAG_INT_MASK = 0x0700;
|
||||
/* Reset VBR */
|
||||
REG_VBR = 0;
|
||||
/* Go to supervisor mode */
|
||||
m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
|
||||
|
||||
/* Invalidate the prefetch queue */
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
/* Set to arbitrary number since our first fetch is from 0 */
|
||||
CPU_PREF_ADDR = 0x1000;
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
|
||||
/* Read the initial stack pointer and program counter */
|
||||
m68ki_jump(0);
|
||||
REG_SP = m68ki_read_imm_32();
|
||||
REG_PC = m68ki_read_imm_32();
|
||||
m68ki_jump(REG_PC);
|
||||
}
|
||||
|
||||
/* Pulse the HALT line on the CPU */
|
||||
void m68k_pulse_halt(void)
|
||||
{
|
||||
CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
}
|
||||
|
||||
|
||||
/* Get and set the current CPU context */
|
||||
/* This is to allow for multiple CPUs */
|
||||
unsigned int m68k_context_size()
|
||||
{
|
||||
return sizeof(m68ki_cpu_core);
|
||||
}
|
||||
|
||||
unsigned int m68k_get_context(void* dst)
|
||||
{
|
||||
if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
|
||||
return sizeof(m68ki_cpu_core);
|
||||
}
|
||||
|
||||
void m68k_set_context(void* src)
|
||||
{
|
||||
if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
|
||||
}
|
||||
|
||||
void m68k_save_context( void (*save_value)(char*, unsigned int))
|
||||
{
|
||||
if(!save_value)
|
||||
return;
|
||||
|
||||
save_value("CPU_TYPE" , m68k_get_reg(NULL, M68K_REG_CPU_TYPE));
|
||||
save_value("D0" , REG_D[0]);
|
||||
save_value("D1" , REG_D[1]);
|
||||
save_value("D2" , REG_D[2]);
|
||||
save_value("D3" , REG_D[3]);
|
||||
save_value("D4" , REG_D[4]);
|
||||
save_value("D5" , REG_D[5]);
|
||||
save_value("D6" , REG_D[6]);
|
||||
save_value("D7" , REG_D[7]);
|
||||
save_value("A0" , REG_A[0]);
|
||||
save_value("A1" , REG_A[1]);
|
||||
save_value("A2" , REG_A[2]);
|
||||
save_value("A3" , REG_A[3]);
|
||||
save_value("A4" , REG_A[4]);
|
||||
save_value("A5" , REG_A[5]);
|
||||
save_value("A6" , REG_A[6]);
|
||||
save_value("A7" , REG_A[7]);
|
||||
save_value("PPC" , REG_PPC);
|
||||
save_value("PC" , REG_PC);
|
||||
save_value("USP" , REG_USP);
|
||||
save_value("ISP" , REG_ISP);
|
||||
save_value("MSP" , REG_MSP);
|
||||
save_value("VBR" , REG_VBR);
|
||||
save_value("SFC" , REG_SFC);
|
||||
save_value("DFC" , REG_DFC);
|
||||
save_value("CACR" , REG_CACR);
|
||||
save_value("CAAR" , REG_CAAR);
|
||||
save_value("SR" , m68ki_get_sr());
|
||||
save_value("INT_LEVEL" , CPU_INT_LEVEL);
|
||||
save_value("INT_CYCLES", CPU_INT_CYCLES);
|
||||
save_value("STOPPED" , (CPU_STOPPED & STOP_LEVEL_STOP) != 0);
|
||||
save_value("HALTED" , (CPU_STOPPED & STOP_LEVEL_HALT) != 0);
|
||||
save_value("PREF_ADDR" , CPU_PREF_ADDR);
|
||||
save_value("PREF_DATA" , CPU_PREF_DATA);
|
||||
}
|
||||
|
||||
void m68k_load_context(unsigned int (*load_value)(char*))
|
||||
{
|
||||
unsigned int temp;
|
||||
|
||||
m68k_set_cpu_type(load_value("CPU_TYPE"));
|
||||
REG_PPC = load_value("PPC");
|
||||
REG_PC = load_value("PC");
|
||||
m68ki_jump(REG_PC);
|
||||
CPU_INT_LEVEL = 0;
|
||||
m68ki_set_sr_noint(load_value("SR"));
|
||||
REG_D[0] = load_value("D0");
|
||||
REG_D[1] = load_value("D1");
|
||||
REG_D[2] = load_value("D2");
|
||||
REG_D[3] = load_value("D3");
|
||||
REG_D[4] = load_value("D4");
|
||||
REG_D[5] = load_value("D5");
|
||||
REG_D[6] = load_value("D6");
|
||||
REG_D[7] = load_value("D7");
|
||||
REG_A[0] = load_value("A0");
|
||||
REG_A[1] = load_value("A1");
|
||||
REG_A[2] = load_value("A2");
|
||||
REG_A[3] = load_value("A3");
|
||||
REG_A[4] = load_value("A4");
|
||||
REG_A[5] = load_value("A5");
|
||||
REG_A[6] = load_value("A6");
|
||||
REG_A[7] = load_value("A7");
|
||||
REG_USP = load_value("USP");
|
||||
REG_ISP = load_value("ISP");
|
||||
REG_MSP = load_value("MSP");
|
||||
REG_VBR = load_value("VBR");
|
||||
REG_SFC = load_value("SFC");
|
||||
REG_DFC = load_value("DFC");
|
||||
REG_CACR = load_value("CACR");
|
||||
REG_CAAR = load_value("CAAR");
|
||||
CPU_INT_LEVEL = load_value("INT_LEVEL");
|
||||
CPU_INT_CYCLES = load_value("INT_CYCLES");
|
||||
|
||||
CPU_STOPPED = 0;
|
||||
temp = load_value("STOPPED");
|
||||
if(temp) CPU_STOPPED |= STOP_LEVEL_STOP;
|
||||
temp = load_value("HALTED");
|
||||
if(temp) CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
|
||||
CPU_PREF_ADDR = load_value("PREF_ADDR");
|
||||
CPU_PREF_DATA = load_value("PREF_DATA");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
#ifndef _MACROS_H_
|
||||
#define _MACROS_H_
|
||||
|
||||
|
||||
#define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1]
|
||||
#define READ_WORD(BASE, ADDR) (((BASE)[(ADDR)+1]<<8) | \
|
||||
(BASE)[(ADDR)])
|
||||
#define READ_LONG(BASE, ADDR) (((BASE)[(ADDR)+1]<<24) | \
|
||||
((BASE)[(ADDR)+0]<<16) | \
|
||||
((BASE)[(ADDR)+3]<<8) | \
|
||||
(BASE)[(ADDR)+2])
|
||||
|
||||
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL)&0xff
|
||||
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[(ADDR)+1] = ((VAL)>>8) & 0xff; \
|
||||
(BASE)[ADDR] = (VAL)&0xff
|
||||
#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[(ADDR)+1] = ((VAL)>>24) & 0xff; \
|
||||
(BASE)[(ADDR)+0] = ((VAL)>>16)&0xff; \
|
||||
(BASE)[(ADDR)+3] = ((VAL)>>8)&0xff; \
|
||||
(BASE)[(ADDR)+2] = (VAL)&0xff
|
||||
|
||||
|
||||
#endif /* _MACROS_H_ */
|
||||
|
||||
|
|
@ -1,715 +0,0 @@
|
|||
|
||||
#include "shared.h"
|
||||
|
||||
unsigned int m68k_read_bus_8(unsigned int address)
|
||||
{
|
||||
uint16 temp = m68k_read_bus_16(address);
|
||||
return ((address & 1) ? (temp & 0xFF) : (temp >> 8));
|
||||
}
|
||||
|
||||
unsigned int m68k_read_bus_16(unsigned int address)
|
||||
{
|
||||
uint16 temp = 0x4e71;
|
||||
|
||||
if(address >= 0xC00000)
|
||||
{
|
||||
return (temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (temp & 0xFF00);
|
||||
}
|
||||
}
|
||||
|
||||
void m68k_unused_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
//error("Unused %08X = %08X (%08X)\n", address, value, Turbo68KReadPC());
|
||||
}
|
||||
|
||||
void m68k_unused_8_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
//error("Unused %08X = %02X (%08X)\n", address, value, Turbo68KReadPC());
|
||||
}
|
||||
|
||||
void m68k_unused_16_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
//error("Unused %08X = %04X (%08X)\n", address, value, Turbo68KReadPC());
|
||||
}
|
||||
|
||||
/*
|
||||
Functions to handle memory accesses which cause the Genesis to halt
|
||||
either temporarily (press RESET button to restart) or unrecoverably
|
||||
(cycle power to restart).
|
||||
*/
|
||||
|
||||
void m68k_lockup_w_8(unsigned int address, unsigned int value)
|
||||
{
|
||||
error("Lockup %08X = %02X (%08X)\n", address, value, m68k_get_reg(NULL, M68K_REG_PC));
|
||||
gen_running = 0;
|
||||
m68k_end_timeslice();
|
||||
}
|
||||
|
||||
void m68k_lockup_w_16(unsigned int address, unsigned int value)
|
||||
{
|
||||
error("Lockup %08X = %04X (%08X)\n", address, value, m68k_get_reg(NULL, M68K_REG_PC));
|
||||
gen_running = 0;
|
||||
m68k_end_timeslice();
|
||||
}
|
||||
|
||||
unsigned int m68k_lockup_r_8(unsigned int address)
|
||||
{
|
||||
error("Lockup %08X.b (%08X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
|
||||
gen_running = 0;
|
||||
m68k_end_timeslice();
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int m68k_lockup_r_16(unsigned int address)
|
||||
{
|
||||
error("Lockup %08X.w (%08X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
|
||||
gen_running = 0;
|
||||
m68k_end_timeslice();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 68000 memory handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
unsigned int m68k_read_memory_8(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* ROM */
|
||||
case 1:
|
||||
return readb_swap_rom(address);
|
||||
|
||||
case 7: /* RAM */
|
||||
return READ_BYTE(work_ram, address & 0xFFFF);
|
||||
|
||||
case 5: /* Z80 & I/O */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
if(zbusack == 1)
|
||||
{
|
||||
/* Z80 controls Z bus */
|
||||
return (m68k_read_bus_8(address));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read data from Z bus */
|
||||
switch(address & 0x6000)
|
||||
{
|
||||
case 0x0000: /* RAM */
|
||||
case 0x2000:
|
||||
return (zram[(address & 0x1FFF)]);
|
||||
|
||||
case 0x4000: /* YM2612 */
|
||||
return (fm_read(address & 3));
|
||||
|
||||
case 0x6000: /* Unused */
|
||||
switch(address & 0xFF00)
|
||||
{
|
||||
case 0x7F00: /* VDP */
|
||||
m68k_lockup_r_8(address);
|
||||
|
||||
default: /* Unused */
|
||||
return (0xFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x00: /* I/O CHIP */
|
||||
if(address <= 0xA1001F)
|
||||
{
|
||||
return (gen_io_r((address >> 1) & 0x0F));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (m68k_read_bus_8(address));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
if((address & 1) == 0)
|
||||
{
|
||||
return (gen_busack_r() | (m68k_read_bus_8(address) & 0xFE));
|
||||
}
|
||||
else
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 0x12: /* RESET */
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 0x13: /* TIME */
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 0x20: /* UNKNOWN */
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 0x30: /* UNKNOWN */
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
default: /* Unused */
|
||||
return (m68k_lockup_r_8(address));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* VDP */
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8);
|
||||
|
||||
case 0x01: /* DATA */
|
||||
case 0x03:
|
||||
return (vdp_data_r() & 0xFF);
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
case 0x06:
|
||||
return ((m68k_read_bus_8(address) & 0xFC) | (vdp_ctrl_r() >> 8));
|
||||
|
||||
case 0x05: /* CTRL */
|
||||
case 0x07:
|
||||
return (vdp_ctrl_r() & 0xFF);
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r() >> 8);
|
||||
|
||||
case 0x09: /* HVC */
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
return (vdp_hvc_r() & 0xFF);
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return (m68k_lockup_r_8(address));
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
return (m68k_read_bus_8(address));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unused */
|
||||
return (m68k_lockup_r_8(address));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
return (m68k_read_bus_8(address));
|
||||
|
||||
case 4: /* Unused */
|
||||
return (m68k_lockup_r_8(address));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int m68k_read_memory_16(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
|
||||
case 0: /* ROM */
|
||||
case 1:
|
||||
return readw_swap_rom(address);
|
||||
|
||||
case 7: /* RAM */
|
||||
return READ_WORD(work_ram, address & 0xFFFF);
|
||||
|
||||
case 5: /* Z80 & I/O */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
if(zbusack == 1)
|
||||
{
|
||||
return (m68k_read_bus_16(address));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 temp;
|
||||
|
||||
switch(address & 0x6000)
|
||||
{
|
||||
case 0x0000: /* RAM */
|
||||
case 0x2000:
|
||||
temp = zram[address & 0x1FFF];
|
||||
return (temp << 8 | temp);
|
||||
|
||||
case 0x4000: /* YM2612 */
|
||||
temp = fm_read(address & 3);
|
||||
return (temp << 8 | temp);
|
||||
|
||||
case 0x6000:
|
||||
switch(address & 0xFF00)
|
||||
{
|
||||
case 0x7F00: /* VDP */
|
||||
m68k_lockup_r_16(address);
|
||||
|
||||
default: /* Unused */
|
||||
return (0xFFFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(address <= 0xA1001F)
|
||||
{
|
||||
uint8 temp = gen_io_r((address >> 1) & 0x0F);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x10: /* MEMORY MODE */
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
return ((m68k_read_bus_16(address) & 0xFEFF) | (gen_busack_r() << 8));
|
||||
|
||||
case 0x12: /* RESET */
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
case 0x13: /* TIME */
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
case 0x20: /* UNKNOWN */
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
case 0x30: /* UNKNOWN */
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
default: /* Unused */
|
||||
return (m68k_lockup_r_16(address));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
case 0x02:
|
||||
return (vdp_data_r());
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
case 0x06:
|
||||
return (vdp_ctrl_r() | (m68k_read_bus_16(address) & 0xFC00));
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r());
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
return (m68k_lockup_r_16(address));
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x1A:
|
||||
case 0x1C:
|
||||
case 0x1E:
|
||||
return (m68k_read_bus_16(address));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (m68k_lockup_r_16(address));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
return (m68k_read_bus_16(address));
|
||||
|
||||
case 4:
|
||||
return (m68k_lockup_r_16(address));
|
||||
}
|
||||
|
||||
return (0xA5A5);
|
||||
}
|
||||
|
||||
|
||||
unsigned int m68k_read_memory_32(unsigned int address)
|
||||
{
|
||||
/* Split into 2 reads */
|
||||
return (m68k_read_memory_16(address + 0) << 16 | m68k_read_memory_16(address + 2));
|
||||
}
|
||||
|
||||
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 7:
|
||||
WRITE_BYTE(work_ram, address & 0xFFFF, value);
|
||||
return;
|
||||
|
||||
case 6:
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
vdp_data_w(value << 8 | value);
|
||||
return;
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
vdp_ctrl_w(value << 8 | value);
|
||||
return;
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
m68k_lockup_w_8(address, value);
|
||||
return;
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x11: /* PSG */
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(value);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k_lockup_w_8(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
case 5:
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
if(zbusack == 1)
|
||||
{
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(address & 0x6000)
|
||||
{
|
||||
case 0x0000:
|
||||
case 0x2000:
|
||||
zram[(address & 0x1FFF)] = value;
|
||||
return;
|
||||
|
||||
case 0x4000:
|
||||
fm_write(address & 3, value);
|
||||
return;
|
||||
|
||||
case 0x6000:
|
||||
switch(address & 0xFF00)
|
||||
{
|
||||
case 0x6000: /* BANK */
|
||||
gen_bank_w(value & 1);
|
||||
return;
|
||||
|
||||
case 0x7F00: /* VDP */
|
||||
m68k_lockup_w_8(address, value);
|
||||
return;
|
||||
|
||||
default: /* Unused */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(address <= 0xA1001F)
|
||||
{
|
||||
/* I/O chip only gets /LWR */
|
||||
if(address & 1)
|
||||
gen_io_w((address >> 1) & 0x0F, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bus control chip registers */
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x10: /* MEMORY MODE */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
if((address & 1) == 0)
|
||||
{
|
||||
gen_busreq_w(value & 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k_unused_8_w(address, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
gen_reset_w(value & 1);
|
||||
return;
|
||||
|
||||
case 0x13: /* TIME */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x20: /* UNKNOWN */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x30: /* UNKNOWN */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
default: /* Unused */
|
||||
m68k_lockup_w_8(address, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0: /* ROM */
|
||||
case 1: /* ROM */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
|
||||
case 4: /* Unused */
|
||||
m68k_lockup_w_8(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* ROM */
|
||||
case 1: /* ROM */
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
case 4: /* Unused */
|
||||
m68k_lockup_w_16(address, value);
|
||||
return;
|
||||
|
||||
case 5: /* Z80 area, I/O chip, miscellaneous. */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
/* Writes are ignored when the Z80 hogs the Z-bus */
|
||||
if(zbusack == 1) {
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write into Z80 address space */
|
||||
switch(address & 0x6000)
|
||||
{
|
||||
case 0x0000: /* Work RAM */
|
||||
case 0x2000: /* Work RAM */
|
||||
zram[(address & 0x1FFF)] = (value >> 8) & 0xFF;
|
||||
return;
|
||||
|
||||
case 0x4000: /* YM2612 */
|
||||
fm_write(address & 3, (value >> 8) & 0xFF);
|
||||
return;
|
||||
|
||||
case 0x6000: /* Bank register and VDP */
|
||||
switch(address & 0x7F00)
|
||||
{
|
||||
case 0x6000: /* Bank register */
|
||||
gen_bank_w((value >> 8) & 1);
|
||||
return;
|
||||
|
||||
case 0x7F00: /* VDP registers */
|
||||
m68k_lockup_w_16(address, value);
|
||||
return;
|
||||
|
||||
default: /* Unused */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* I/O chip */
|
||||
if(address <= 0xA1001F)
|
||||
{
|
||||
gen_io_w((address >> 1) & 0x0F, value & 0x00FF);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bus control chip registers */
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x10: /* MEMORY MODE */
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
gen_busreq_w((value >> 8) & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
gen_reset_w((value >> 8) & 1);
|
||||
return;
|
||||
|
||||
case 0x13: /* TIME */
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x20: /* UNKNOWN */
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
case 0x30: /* UNKNOWN */
|
||||
m68k_unused_16_w(address, value);
|
||||
return;
|
||||
|
||||
default: /* Unused */
|
||||
m68k_lockup_w_16(address, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* VDP */
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
{
|
||||
switch(address & 0x1C)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
vdp_data_w(value);
|
||||
return;
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
vdp_ctrl_w(value);
|
||||
return;
|
||||
|
||||
case 0x08: /* HV counter */
|
||||
case 0x0C: /* HV counter */
|
||||
m68k_lockup_w_16(address, value);
|
||||
return;
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14: /* PSG */
|
||||
psg_write(value & 0xFF);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x1C: /* Unused */
|
||||
m68k_unused_8_w(address, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid address */
|
||||
m68k_lockup_w_16(address, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: /* Work RAM */
|
||||
WRITE_WORD(work_ram, address & 0xFFFF, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value)
|
||||
{
|
||||
/* Split into 2 writes */
|
||||
m68k_write_memory_16(address, (value >> 16) & 0xFFFF);
|
||||
m68k_write_memory_16(address + 2, value & 0xFFFF);
|
||||
}
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
#ifndef _MEM68K_H_
|
||||
#define _MEM68K_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int m68k_read_bus_8(unsigned int address);
|
||||
unsigned int m68k_read_bus_16(unsigned int address);
|
||||
void m68k_unused_w(unsigned int address, unsigned int value);
|
||||
|
||||
void m68k_lockup_w_8(unsigned int address, unsigned int value);
|
||||
void m68k_lockup_w_16(unsigned int address, unsigned int value);
|
||||
unsigned int m68k_lockup_r_8(unsigned int address);
|
||||
unsigned int m68k_lockup_r_16(unsigned int address);
|
||||
|
||||
#endif /* _MEM68K_H_ */
|
||||
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
membnk.c --
|
||||
Memory handlers Z80 access to the banked V-bus address space.
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
void z80_write_banked_memory(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 4: /* Unused (lockup) */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 5: /* Z80, I/O chip, etc. */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if(address <= 0xA1001F)
|
||||
gen_io_w((address >> 1) & 0x0F, data);
|
||||
else
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* DRAM refresh */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* /BUSREQ */
|
||||
if(address & 1)
|
||||
z80bank_unused_w(address, data);
|
||||
else
|
||||
gen_busreq_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* /RESET (w) */
|
||||
if(address & 1)
|
||||
z80bank_unused_w(address, data);
|
||||
else
|
||||
gen_reset_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x13: /* /TIME region */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x20: /* ? */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x30: /* ? */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* Invalid */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case 6: /* VDP */
|
||||
z80bank_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
case 7: /* Work RAM */
|
||||
WRITE_BYTE(work_ram, address & 0xFFFF, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int z80_read_banked_memory(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
return readb_swap_rom(address);
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 4: /* Unused (lockup) */
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case 5: /* Z80, I/O chip, etc.*/
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if(address <= 0xA1001F)
|
||||
return gen_io_r((address >> 1) & 0x0F);
|
||||
else
|
||||
return z80bank_unused_r(address);
|
||||
break;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 0x11: /* /BUSACK from Z80 */
|
||||
/* The Z80 can't read this bit (it would be halted
|
||||
when the bit was zero) so we always return '1'. */
|
||||
return 0xFF;
|
||||
|
||||
case 0x12: /* Unused */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 0x13: /* /TIME region */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 0x20: /* Unused */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 0x30: /* Unused */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
default: /* Lockup */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* VDP */
|
||||
return z80bank_vdp_r(address);
|
||||
|
||||
case 7: /* Work RAM - can't be read on some Genesis models (!) */
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
void z80bank_vdp_w(int address, int data)
|
||||
{
|
||||
// if((address & 0xE700E0) == 0xC00000)
|
||||
if((address & 0xE700E0) == 0xC0000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* Data port */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
vdp_data_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x04: /* Control port */
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x08: /* Lockup (HVC) */
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* PSG */
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x1C: /* Test register */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid VDP address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int z80bank_vdp_r(int address)
|
||||
{
|
||||
// if((address & 0xE700E0) == 0xC00000)
|
||||
if((address & 0xE700E0) == 0xC0000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* Data */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x01: /* Data */
|
||||
case 0x03:
|
||||
return vdp_data_r() & 0xFF;
|
||||
|
||||
case 0x04: /* Control */
|
||||
case 0x06:
|
||||
return (0xFC | (vdp_ctrl_r() >> 8)) & 0xFF;
|
||||
|
||||
case 0x05: /* Control */
|
||||
case 0x07:
|
||||
return vdp_ctrl_r() & 0xFF;
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x09: /* HVC */
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
return vdp_hvc_r() & 0xFF;
|
||||
|
||||
case 0x10: /* Lockup */
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
return (z80bank_unused_r(address) | 0xFF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid VDP address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
void z80bank_unused_w(int address, int data)
|
||||
{
|
||||
error("Z80 bank unused write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
}
|
||||
|
||||
int z80bank_unused_r(int address)
|
||||
{
|
||||
error("Z80 bank unused read %06X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
return (address & 1) ? 0x00 : 0xFF;
|
||||
}
|
||||
|
||||
void z80bank_lockup_w(int address, int data)
|
||||
{
|
||||
error("Z80 bank lockup write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
}
|
||||
|
||||
int z80bank_lockup_r(int address)
|
||||
{
|
||||
error("Z80 bank lockup read %06X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
#ifndef _MEMBNK_H_
|
||||
#define _MEMBNK_H_
|
||||
|
||||
/* Function prototypes */
|
||||
void z80_write_banked_memory(unsigned int address, unsigned int data);
|
||||
int z80_read_banked_memory(unsigned int address);
|
||||
|
||||
void z80bank_vdp_w(int address, int data);
|
||||
int z80bank_vdp_r(int address);
|
||||
|
||||
void z80bank_unused_w(int address, int data);
|
||||
int z80bank_unused_r(int address);
|
||||
void z80bank_lockup_w(int address, int data);
|
||||
int z80bank_lockup_r(int address);
|
||||
|
||||
#endif /* _MEMBNK_H_ */
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#include "shared.h"
|
||||
|
||||
|
||||
//uint8 lwork_ram[WORK_RAM_SIZE]; /* 68K work RAM */
|
||||
//uint8 lzram[Z_RAM_SIZE]; /* Z80 work RAM */
|
||||
|
||||
//uint8 lvram[VRAM_SIZE];
|
||||
uint8 lbg_name_dirty[BGNAMEDIRTY_SIZE];
|
||||
uint16 lbg_name_list[BGNAME_SIZE];
|
||||
//uint8 lbg_pattern_cache[BGPATTERN_CACH_SIZE];
|
||||
|
||||
uint8 * vram;// = &lvram[0];
|
||||
uint8 * bg_name_dirty = &lbg_name_dirty[0];
|
||||
uint16 * bg_name_list = &lbg_name_list[0];
|
||||
uint8 * bg_pattern_cache; // = &lbg_pattern_cache[0];
|
||||
|
||||
|
||||
uint8 * work_ram; // = &lwork_ram[0];
|
||||
uint8 * zram; // = &lzram[0];
|
||||
|
||||
|
||||
|
||||
void mem_init(void) {
|
||||
bg_pattern_cache = emu_Malloc(BGPATTERN_CACH_SIZE);
|
||||
vram = emu_Malloc(VRAM_SIZE);
|
||||
work_ram = emu_Malloc(WORK_RAM_SIZE);
|
||||
zram = emu_Malloc(Z_RAM_SIZE);
|
||||
//bg_pattern_cache = emu_Malloc(BGPATTERN_CACH_SIZE+1)&0xFFFFFFFE;
|
||||
//vram = emu_Malloc(VRAM_SIZE+1)&0xFFFFFFFE;
|
||||
//work_ram = emu_Malloc(WORK_RAM_SIZE+1)&0xFFFFFFFE;
|
||||
//zram = emu_Malloc(Z_RAM_SIZE+1)&0xFFFFFFFE;
|
||||
}
|
||||
|
||||
|
||||
int mem_test(void) {
|
||||
// for (int i=0x40000;i<OBJ_CACHE_SIZE;i++) {
|
||||
// if (obj_pattern_cache[i] != 0) return 0;;
|
||||
// }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void memcpy_rom(int dst, int src, int size) {
|
||||
while (size > 0) {
|
||||
write_rom(dst++, read_rom(src++));
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef _MEMORY_H_
|
||||
#define _MEMORY_H_
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define WORK_RAM_SIZE 0x10000
|
||||
#define Z_RAM_SIZE 0x2000
|
||||
|
||||
#define VRAM_SIZE 0x10000
|
||||
#define BGNAMEDIRTY_SIZE 0x800
|
||||
#define BGNAME_SIZE 0x800
|
||||
#define BGPATTERN_CACH_SIZE 0x40000
|
||||
|
||||
|
||||
//extern uint8 * cart_rom;
|
||||
extern uint8 * work_ram; /* 68K work RAM */
|
||||
extern uint8 * zram; /* Z80 work RAM */
|
||||
|
||||
extern uint8 * vram;
|
||||
extern uint8 * bg_name_dirty;
|
||||
extern uint16 * bg_name_list;
|
||||
extern uint8 * bg_pattern_cache;
|
||||
|
||||
|
||||
extern void mem_init(void);
|
||||
extern int mem_test(void);
|
||||
extern uint8 rom_version(void);
|
||||
extern uint8 readb_rom(int address);
|
||||
extern uint8 readb_swap_rom(int address);
|
||||
extern uint16 readw_swap_rom(int address);
|
||||
extern void write_rom(int address, uint8 val);
|
||||
|
||||
extern void memcpy_rom(int dst, int src, int size);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
memvdp.c --
|
||||
Memory handlers for when the VDP reads the V-bus during DMA.
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
unsigned int vdp_dma_r(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
return readw_swap_rom(address);
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
return 0xFF00;
|
||||
|
||||
case 4: /* Work RAM */
|
||||
case 6:
|
||||
case 7:
|
||||
return READ_WORD(work_ram, address & 0xFFFF);
|
||||
|
||||
case 5: /* Z80 area and I/O chip */
|
||||
|
||||
/* Z80 area always returns $FFFF */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||
(e.g. Z80 isn't reset and 68000 has the bus) */
|
||||
return (zbusack == 0)
|
||||
? 0xFFFF
|
||||
: READ_WORD(work_ram, address & 0xFFFF);
|
||||
}
|
||||
else
|
||||
|
||||
/* The I/O chip and work RAM try to drive the data bus which
|
||||
results in both values being combined in random ways when read.
|
||||
We return the I/O chip values which seem to have precedence, */
|
||||
if(address <= 0xA1001F)
|
||||
{
|
||||
uint8 temp = gen_io_r((address >> 1) & 0x0F);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
else
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
return READ_WORD(work_ram, address & 0xFFFF);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
#ifndef _MEMVDP_H_
|
||||
#define _MEMVDP_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int vdp_dma_r(unsigned int address);
|
||||
|
||||
#endif /* _MEMVDP_H_ */
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
memz80.c --
|
||||
Memory handlers for Z80 memory and port access, and the Z80 to
|
||||
VDP interface.
|
||||
*/
|
||||
|
||||
#define LOG_PORT 0 /* 1= Log Z80 I/O port accesses */
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
unsigned int cpu_readmem16(unsigned int address)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
return zram[address & 0x1FFF];
|
||||
|
||||
case 2: /* YM2612 */
|
||||
return fm_read(address & 3);
|
||||
|
||||
case 3: /* VDP */
|
||||
if((address & 0xFF00) == 0x7F00)
|
||||
return z80_vdp_r(address);
|
||||
return 0xFF;
|
||||
|
||||
default: /* V-bus bank */
|
||||
return z80_read_banked_memory(zbank | (address & 0x7FFF));
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
zram[address & 0x1FFF] = data;
|
||||
return;
|
||||
|
||||
case 2: /* YM2612 */
|
||||
fm_write(address & 3, data);
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
switch(address & 0xFF00)
|
||||
{
|
||||
case 0x6000:
|
||||
gen_bank_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x7F00:
|
||||
z80_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
default:
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
default: /* V-bus bank */
|
||||
z80_write_banked_memory(zbank | (address & 0x7FFF), data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int z80_vdp_r(int address)
|
||||
{
|
||||
switch(address & 0xFF)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x01: /* VDP data port */
|
||||
case 0x03:
|
||||
return (vdp_data_r() & 0xFF);
|
||||
|
||||
case 0x04: /* VDP control port */
|
||||
case 0x06:
|
||||
return (0xFF | ((vdp_ctrl_r() >> 8) & 3));
|
||||
|
||||
case 0x05: /* VDP control port */
|
||||
case 0x07:
|
||||
return (vdp_ctrl_r() & 0xFF);
|
||||
|
||||
case 0x08: /* HV counter */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x09: /* HV counter */
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
return (vdp_hvc_r() & 0xFF);
|
||||
|
||||
case 0x10: /* Unused (PSG) */
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return z80_lockup_r(address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
return z80_unused_r(address);
|
||||
|
||||
case 0x1C: /* Unused (test register) */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
return z80_unused_r(address);
|
||||
|
||||
default: /* Invalid VDP addresses */
|
||||
return z80_lockup_r(address);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void z80_vdp_w(int address, int data)
|
||||
{
|
||||
switch(address & 0xFF)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
vdp_data_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x04: /* VDP control port */
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x08: /* Unused (HV counter) */
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
z80_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* PSG */
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
z80_unused_w(address, data);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x1C: /* Test register */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
default: /* Invalid VDP addresses */
|
||||
z80_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Port handlers. Ports are unused when not in Mark III compatability mode.
|
||||
|
||||
Games that access ports anyway:
|
||||
- Thunder Force IV reads port $BF in it's interrupt handler.
|
||||
*/
|
||||
|
||||
unsigned int cpu_readport16(unsigned int port)
|
||||
{
|
||||
#if LOG_PORT
|
||||
error("Z80 read port %04X (%04X)\n", port, z80_get_reg(Z80_PC));
|
||||
#endif
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void cpu_writeport16(unsigned int port, unsigned int data)
|
||||
{
|
||||
#if LOG_PORT
|
||||
error("Z80 write %02X to port %04X (%04X)\n", data, port, z80_get_reg(Z80_PC));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
void z80_unused_w(int address, int data)
|
||||
{
|
||||
error("Z80 unused write %04X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
}
|
||||
|
||||
int z80_unused_r(int address)
|
||||
{
|
||||
error("Z80 unused read %04X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void z80_lockup_w(int address, int data)
|
||||
{
|
||||
error("Z80 lockup write %04X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
}
|
||||
|
||||
int z80_lockup_r(int address)
|
||||
{
|
||||
error("Z80 lockup read %04X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
#ifndef _MEMZ80_H_
|
||||
#define _MEMZ80_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int cpu_readmem16(unsigned int address);
|
||||
void cpu_writemem16(unsigned int address, unsigned int data);
|
||||
unsigned int cpu_readport16(unsigned int port);
|
||||
void cpu_writeport16(unsigned int port, unsigned int data);
|
||||
void z80_unused_w(int address, int data);
|
||||
int z80_unused_r(int address);
|
||||
void z80_lockup_w(int address, int data);
|
||||
int z80_lockup_r(int address);
|
||||
int z80_vdp_r(int address);
|
||||
void z80_vdp_w(int address, int data);
|
||||
|
||||
#endif /* _MEMZ80_H_ */
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.4
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef M68K__HEADER
|
||||
#define M68K__HEADER
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Import the configuration for this build */
|
||||
#include "m68kconf.h"
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ GENERAL DEFINES =========================== */
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/* There are 7 levels of interrupt to the 68K.
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
*/
|
||||
#define M68K_IRQ_NONE 0
|
||||
#define M68K_IRQ_1 1
|
||||
#define M68K_IRQ_2 2
|
||||
#define M68K_IRQ_3 3
|
||||
#define M68K_IRQ_4 4
|
||||
#define M68K_IRQ_5 5
|
||||
#define M68K_IRQ_6 6
|
||||
#define M68K_IRQ_7 7
|
||||
|
||||
|
||||
/* Special interrupt acknowledge values.
|
||||
* Use these as special returns from the interrupt acknowledge callback
|
||||
* (specified later in this header).
|
||||
*/
|
||||
|
||||
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
|
||||
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
|
||||
* acknowledge cycle instead of DTACK.
|
||||
*/
|
||||
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
|
||||
|
||||
/* Causes the spurious interrupt vector (0x18) to be taken
|
||||
* This happens in a real 68K if BERR is asserted during the interrupt
|
||||
* acknowledge cycle (i.e. no devices responded to the acknowledge).
|
||||
*/
|
||||
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
|
||||
|
||||
|
||||
/* CPU types for use in m68k_set_cpu_type() */
|
||||
enum
|
||||
{
|
||||
M68K_CPU_TYPE_INVALID,
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020,
|
||||
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
|
||||
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
|
||||
};
|
||||
|
||||
/* Registers used by m68k_get_reg() and m68k_set_reg() */
|
||||
typedef enum
|
||||
{
|
||||
/* Real registers */
|
||||
M68K_REG_D0, /* Data registers */
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0, /* Address registers */
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC, /* Program Counter */
|
||||
M68K_REG_SR, /* Status Register */
|
||||
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||
M68K_REG_USP, /* User Stack Pointer */
|
||||
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||
M68K_REG_MSP, /* Master Stack Pointer */
|
||||
M68K_REG_SFC, /* Source Function Code */
|
||||
M68K_REG_DFC, /* Destination Function Code */
|
||||
M68K_REG_VBR, /* Vector Base Register */
|
||||
M68K_REG_CACR, /* Cache Control Register */
|
||||
M68K_REG_CAAR, /* Cache Address Register */
|
||||
|
||||
/* Assumed registers */
|
||||
/* These are cheat registers which emulate the 1-longword prefetch
|
||||
* present in the 68000 and 68010.
|
||||
*/
|
||||
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||
|
||||
/* Convenience registers */
|
||||
M68K_REG_PPC, /* Previous value in the program counter */
|
||||
M68K_REG_IR, /* Instruction register */
|
||||
M68K_REG_CPU_TYPE /* Type of CPU being run */
|
||||
} m68k_register_t;
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* You will have to implement these functions */
|
||||
|
||||
/* read/write functions called by the CPU to access memory.
|
||||
* while values used are 32 bits, only the appropriate number
|
||||
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
|
||||
* of value should be written to memory).
|
||||
*
|
||||
* NOTE: I have separated the immediate and PC-relative memory fetches
|
||||
* from the other memory fetches because some systems require
|
||||
* differentiation between PROGRAM and DATA fetches (usually
|
||||
* for security setups such as encryption).
|
||||
* This separation can either be achieved by setting
|
||||
* M68K_SEPARATE_READS in m68kconf.h and defining
|
||||
* the read functions, or by setting M68K_EMULATE_FC and
|
||||
* making a function code callback function.
|
||||
* Using the callback offers better emulation coverage
|
||||
* because you can also monitor whether the CPU is in SYSTEM or
|
||||
* USER mode, but it is also slower.
|
||||
*/
|
||||
|
||||
/* Read from anywhere */
|
||||
unsigned int m68k_read_memory_8(unsigned int address);
|
||||
unsigned int m68k_read_memory_16(unsigned int address);
|
||||
unsigned int m68k_read_memory_32(unsigned int address);
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
unsigned int m68k_read_immediate_16(unsigned int address);
|
||||
unsigned int m68k_read_immediate_32(unsigned int address);
|
||||
|
||||
/* Read data relative to the PC */
|
||||
unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||
|
||||
/* Memory access for the disassembler */
|
||||
unsigned int m68k_read_disassembler_8 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_16 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_32 (unsigned int address);
|
||||
|
||||
/* Write to anywhere */
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
/* Special call to simulate undocumented 68k behavior when move.l with a
|
||||
* predecrement destination mode is executed.
|
||||
* To simulate real 68k behavior, first write the high word to
|
||||
* [address+2], and then write the low word to [address].
|
||||
*
|
||||
* Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h.
|
||||
*/
|
||||
void m68k_write_memory_32_pd(unsigned int address, unsigned int value);
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== CALLBACKS =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* These functions allow you to set callbacks to the host when specific events
|
||||
* occur. Note that you must enable the corresponding value in m68kconf.h
|
||||
* in order for these to do anything useful.
|
||||
* Note: I have defined default callbacks which are used if you have enabled
|
||||
* the corresponding #define in m68kconf.h but either haven't assigned a
|
||||
* callback or have assigned a callback of NULL.
|
||||
*/
|
||||
|
||||
/* Set the callback for an interrupt acknowledge.
|
||||
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
|
||||
* The CPU will call the callback with the interrupt level being acknowledged.
|
||||
* The host program must return either a vector from 0x02-0xff, or one of the
|
||||
* special interrupt acknowledge values specified earlier in this header.
|
||||
* If this is not implemented, the CPU will always assume an autovectored
|
||||
* interrupt, and will automatically clear the interrupt request when it
|
||||
* services the interrupt.
|
||||
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
|
||||
*/
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level));
|
||||
|
||||
|
||||
/* Set the callback for a breakpoint acknowledge (68010+).
|
||||
* You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
|
||||
* The CPU will call the callback with whatever was in the data field of the
|
||||
* BKPT instruction for 68020+, or 0 for 68010.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
|
||||
|
||||
|
||||
/* Set the callback for the RESET instruction.
|
||||
* You must enable M68K_EMULATE_RESET in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a RESET instruction.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void));
|
||||
|
||||
|
||||
/* Set the callback for informing of a large PC change.
|
||||
* You must enable M68K_MONITOR_PC in m68kconf.h.
|
||||
* The CPU calls this callback with the new PC value every time the PC changes
|
||||
* by a large value (currently set for changes by longwords).
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
|
||||
|
||||
|
||||
/* Set the callback for CPU function code changes.
|
||||
* You must enable M68K_EMULATE_FC in m68kconf.h.
|
||||
* The CPU calls this callback with the function code before every memory
|
||||
* access to set the CPU's function code according to what kind of memory
|
||||
* access it is (supervisor/user, program/data and such).
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||
|
||||
|
||||
/* Set a callback for the instruction cycle of the CPU.
|
||||
* You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
|
||||
* The CPU calls this callback just before fetching the opcode in the
|
||||
* instruction cycle.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Use this function to set the CPU type you want to emulate.
|
||||
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
|
||||
* M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
|
||||
*/
|
||||
void m68k_set_cpu_type(unsigned int cpu_type);
|
||||
|
||||
/* Do whatever initialisations the core requires. Should be called
|
||||
* at least once at init time.
|
||||
*/
|
||||
void m68k_init(void);
|
||||
|
||||
/* Pulse the RESET pin on the CPU.
|
||||
* You *MUST* reset the CPU at least once to initialize the emulation
|
||||
* Note: If you didn't call m68k_set_cpu_type() before resetting
|
||||
* the CPU for the first time, the CPU will be set to
|
||||
* M68K_CPU_TYPE_68000.
|
||||
*/
|
||||
void m68k_pulse_reset(void);
|
||||
|
||||
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||
int m68k_execute(int num_cycles);
|
||||
|
||||
/* These functions let you read/write/modify the number of cycles left to run
|
||||
* while m68k_execute() is running.
|
||||
* These are useful if the 68k accesses a memory-mapped port on another device
|
||||
* that requires immediate processing by another CPU.
|
||||
*/
|
||||
int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||
int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||
void m68k_end_timeslice(void); /* End timeslice now */
|
||||
|
||||
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
* Setting IRQ to 0 will clear an interrupt request.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level);
|
||||
|
||||
|
||||
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||
void m68k_pulse_halt(void);
|
||||
|
||||
|
||||
/* Context switching to allow multiple CPUs */
|
||||
|
||||
/* Get the size of the cpu context in bytes */
|
||||
unsigned int m68k_context_size(void);
|
||||
|
||||
/* Get a cpu context */
|
||||
unsigned int m68k_get_context(void* dst);
|
||||
|
||||
/* set the current cpu context */
|
||||
void m68k_set_context(void* dst);
|
||||
|
||||
/* Register the CPU state information */
|
||||
void m68k_state_register(const char *type);
|
||||
|
||||
|
||||
/* Peek at the internals of a CPU context. This can either be a context
|
||||
* retrieved using m68k_get_context() or the currently running context.
|
||||
* If context is NULL, the currently running CPU context will be used.
|
||||
*/
|
||||
unsigned int m68k_get_reg(void* context, m68k_register_t reg);
|
||||
|
||||
/* Poke values into the internals of the currently running CPU context */
|
||||
void m68k_set_reg(m68k_register_t reg, unsigned int value);
|
||||
|
||||
/* Check if an instruction is valid for the specified CPU type */
|
||||
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
|
||||
|
||||
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
|
||||
* disassembly in str_buff and returns the size of the instruction in bytes.
|
||||
*/
|
||||
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
#include "m68kmame.h"
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68K__HEADER */
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.4
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef M68KCONF__HEADER
|
||||
#define M68KCONF__HEADER
|
||||
|
||||
|
||||
/* Configuration switches.
|
||||
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
|
||||
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
|
||||
* or macro you specify, rather than using callback functions whose pointer
|
||||
* must be passed in using m68k_set_xxx_callback().
|
||||
*/
|
||||
#define OPT_OFF 0
|
||||
#define OPT_ON 1
|
||||
#define OPT_SPECIFY_HANDLER 2
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
|
||||
* to OPT_ON and use m68kmame.h to configure the 68k core.
|
||||
*/
|
||||
#ifndef M68K_COMPILE_FOR_MAME
|
||||
#define M68K_COMPILE_FOR_MAME OPT_OFF
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_OFF
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Turn on if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_010 OPT_ON
|
||||
#define M68K_EMULATE_EC020 OPT_ON
|
||||
#define M68K_EMULATE_020 OPT_ON
|
||||
|
||||
|
||||
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
|
||||
* word to [address+2], and then write the low word to [address].
|
||||
*/
|
||||
#define M68K_SIMULATE_PD_WRITES OPT_OFF
|
||||
|
||||
/* If ON, CPU will call the interrupt acknowledge callback when it services an
|
||||
* interrupt.
|
||||
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||
* auto-clear when the interrupt is serviced.
|
||||
*/
|
||||
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
|
||||
#define M68K_INT_ACK_CALLBACK(A) vdp_int_ack_callback(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
* a breakpoint instruction and it is running a 68010+.
|
||||
*/
|
||||
#define M68K_EMULATE_BKPT_ACK OPT_OFF
|
||||
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
|
||||
|
||||
|
||||
/* If ON, the CPU will monitor the trace flags and take trace exceptions
|
||||
*/
|
||||
#define M68K_EMULATE_TRACE OPT_OFF
|
||||
|
||||
|
||||
/* If ON, CPU will call the output reset callback when it encounters a reset
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_EMULATE_RESET OPT_OFF
|
||||
#define M68K_RESET_CALLBACK() your_reset_handler_function()
|
||||
|
||||
|
||||
/* If ON, CPU will call the set fc callback on every memory access to
|
||||
* differentiate between user/supervisor, program/data access like a real
|
||||
* 68000 would. This should be enabled and the callback should be set if you
|
||||
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||
* to read/write data from different address spaces)
|
||||
*/
|
||||
#define M68K_EMULATE_FC OPT_OFF
|
||||
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the pc changed callback when it changes the PC by a
|
||||
* large value. This allows host programs to be nicer when it comes to
|
||||
* fetching immediate data and instructions on a banked memory system.
|
||||
*/
|
||||
#define M68K_MONITOR_PC OPT_OFF
|
||||
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the instruction hook callback before every
|
||||
* instruction.
|
||||
*/
|
||||
//#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
|
||||
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
||||
|
||||
|
||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||
|
||||
|
||||
/* If ON, the CPU will generate address error exceptions if it tries to
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||
|
||||
|
||||
/* Turn ON to enable logging of illegal instruction calls.
|
||||
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
|
||||
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
|
||||
*/
|
||||
#define M68K_LOG_ENABLE OPT_OFF
|
||||
#define M68K_LOG_1010_1111 OPT_OFF
|
||||
#define M68K_LOG_FILEHANDLE some_file_handle
|
||||
|
||||
|
||||
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||
|
||||
/* The following options set optimizations that violate the current ANSI
|
||||
* standard, but will be compliant under the forthcoming C9X standard.
|
||||
*/
|
||||
|
||||
|
||||
/* If ON, the enulation core will use 64-bit integers to speed up some
|
||||
* operations.
|
||||
*/
|
||||
#define M68K_USE_64_BIT OPT_OFF
|
||||
|
||||
|
||||
/* Set to your compiler's static inline keyword to enable it, or
|
||||
* set it to blank to disable it.
|
||||
* If you define INLINE in the makefile, it will override this value.
|
||||
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
|
||||
*/
|
||||
#ifndef INLINE
|
||||
#define INLINE static __inline__
|
||||
#endif /* INLINE */
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68KCONF__HEADER */
|
||||
|
|
@ -1,882 +0,0 @@
|
|||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.4
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= NOTES ================================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#include "m68kops.h"
|
||||
#include "m68kcpu.h"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= DATA ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
int m68ki_initial_cycles;
|
||||
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||
uint m68ki_tracing = 0;
|
||||
uint m68ki_address_space;
|
||||
|
||||
#ifdef M68K_LOG_ENABLE
|
||||
char* m68ki_cpu_names[9] =
|
||||
{
|
||||
"Invalid CPU",
|
||||
"M68000",
|
||||
"M68010",
|
||||
"Invalid CPU",
|
||||
"M68EC020"
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"M68020"
|
||||
};
|
||||
#endif /* M68K_LOG_ENABLE */
|
||||
|
||||
/* The CPU core */
|
||||
m68ki_cpu_core m68ki_cpu = {0};
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
jmp_buf m68ki_address_error_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
uint m68ki_aerr_address;
|
||||
uint m68ki_aerr_write_mode;
|
||||
uint m68ki_aerr_fc;
|
||||
|
||||
/* Used by shift & rotate instructions */
|
||||
const uint8 m68ki_shift_8_table[65] =
|
||||
{
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
const uint16 m68ki_shift_16_table[65] =
|
||||
{
|
||||
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
|
||||
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff
|
||||
};
|
||||
const uint m68ki_shift_32_table[65] =
|
||||
{
|
||||
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
|
||||
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
||||
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
|
||||
0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
|
||||
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
|
||||
0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
|
||||
};
|
||||
|
||||
|
||||
/* Number of clock cycles to use for exception processing.
|
||||
* I used 4 for any vectors that are undocumented for processing times.
|
||||
*/
|
||||
uint8 m68ki_exception_cycle_table[3][256] =
|
||||
{
|
||||
{ /* 000 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
50, /* 2: Bus Error (unemulated) */
|
||||
50, /* 3: Address Error (unemulated) */
|
||||
34, /* 4: Illegal Instruction */
|
||||
38, /* 5: Divide by Zero -- ASG: changed from 42 */
|
||||
40, /* 6: CHK -- ASG: chanaged from 44 */
|
||||
34, /* 7: TRAPV */
|
||||
34, /* 8: Privilege Violation */
|
||||
34, /* 9: Trace */
|
||||
34, /* 10: 1010 */
|
||||
34, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
44, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
44, /* 24: Spurious Interrupt */
|
||||
44, /* 25: Level 1 Interrupt Autovector */
|
||||
44, /* 26: Level 2 Interrupt Autovector */
|
||||
44, /* 27: Level 3 Interrupt Autovector */
|
||||
44, /* 28: Level 4 Interrupt Autovector */
|
||||
44, /* 29: Level 5 Interrupt Autovector */
|
||||
44, /* 30: Level 6 Interrupt Autovector */
|
||||
44, /* 31: Level 7 Interrupt Autovector */
|
||||
34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
|
||||
34, /* 33: TRAP #1 */
|
||||
34, /* 34: TRAP #2 */
|
||||
34, /* 35: TRAP #3 */
|
||||
34, /* 36: TRAP #4 */
|
||||
34, /* 37: TRAP #5 */
|
||||
34, /* 38: TRAP #6 */
|
||||
34, /* 39: TRAP #7 */
|
||||
34, /* 40: TRAP #8 */
|
||||
34, /* 41: TRAP #9 */
|
||||
34, /* 42: TRAP #10 */
|
||||
34, /* 43: TRAP #11 */
|
||||
34, /* 44: TRAP #12 */
|
||||
34, /* 45: TRAP #13 */
|
||||
34, /* 46: TRAP #14 */
|
||||
34, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
},
|
||||
{ /* 010 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
126, /* 2: Bus Error (unemulated) */
|
||||
126, /* 3: Address Error (unemulated) */
|
||||
38, /* 4: Illegal Instruction */
|
||||
44, /* 5: Divide by Zero */
|
||||
44, /* 6: CHK */
|
||||
34, /* 7: TRAPV */
|
||||
38, /* 8: Privilege Violation */
|
||||
38, /* 9: Trace */
|
||||
4, /* 10: 1010 */
|
||||
4, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
44, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
46, /* 24: Spurious Interrupt */
|
||||
46, /* 25: Level 1 Interrupt Autovector */
|
||||
46, /* 26: Level 2 Interrupt Autovector */
|
||||
46, /* 27: Level 3 Interrupt Autovector */
|
||||
46, /* 28: Level 4 Interrupt Autovector */
|
||||
46, /* 29: Level 5 Interrupt Autovector */
|
||||
46, /* 30: Level 6 Interrupt Autovector */
|
||||
46, /* 31: Level 7 Interrupt Autovector */
|
||||
38, /* 32: TRAP #0 */
|
||||
38, /* 33: TRAP #1 */
|
||||
38, /* 34: TRAP #2 */
|
||||
38, /* 35: TRAP #3 */
|
||||
38, /* 36: TRAP #4 */
|
||||
38, /* 37: TRAP #5 */
|
||||
38, /* 38: TRAP #6 */
|
||||
38, /* 39: TRAP #7 */
|
||||
38, /* 40: TRAP #8 */
|
||||
38, /* 41: TRAP #9 */
|
||||
38, /* 42: TRAP #10 */
|
||||
38, /* 43: TRAP #11 */
|
||||
38, /* 44: TRAP #12 */
|
||||
38, /* 45: TRAP #13 */
|
||||
38, /* 46: TRAP #14 */
|
||||
38, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
},
|
||||
{ /* 020 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
50, /* 2: Bus Error (unemulated) */
|
||||
50, /* 3: Address Error (unemulated) */
|
||||
20, /* 4: Illegal Instruction */
|
||||
38, /* 5: Divide by Zero */
|
||||
40, /* 6: CHK */
|
||||
20, /* 7: TRAPV */
|
||||
34, /* 8: Privilege Violation */
|
||||
25, /* 9: Trace */
|
||||
20, /* 10: 1010 */
|
||||
20, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
30, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
30, /* 24: Spurious Interrupt */
|
||||
30, /* 25: Level 1 Interrupt Autovector */
|
||||
30, /* 26: Level 2 Interrupt Autovector */
|
||||
30, /* 27: Level 3 Interrupt Autovector */
|
||||
30, /* 28: Level 4 Interrupt Autovector */
|
||||
30, /* 29: Level 5 Interrupt Autovector */
|
||||
30, /* 30: Level 6 Interrupt Autovector */
|
||||
30, /* 31: Level 7 Interrupt Autovector */
|
||||
20, /* 32: TRAP #0 */
|
||||
20, /* 33: TRAP #1 */
|
||||
20, /* 34: TRAP #2 */
|
||||
20, /* 35: TRAP #3 */
|
||||
20, /* 36: TRAP #4 */
|
||||
20, /* 37: TRAP #5 */
|
||||
20, /* 38: TRAP #6 */
|
||||
20, /* 39: TRAP #7 */
|
||||
20, /* 40: TRAP #8 */
|
||||
20, /* 41: TRAP #9 */
|
||||
20, /* 42: TRAP #10 */
|
||||
20, /* 43: TRAP #11 */
|
||||
20, /* 44: TRAP #12 */
|
||||
20, /* 45: TRAP #13 */
|
||||
20, /* 46: TRAP #14 */
|
||||
20, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
}
|
||||
};
|
||||
|
||||
uint8 m68ki_ea_idx_cycle_table[64] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* ..01.000 no memory indirect, base NULL */
|
||||
5, /* ..01..01 memory indirect, base NULL, outer NULL */
|
||||
7, /* ..01..10 memory indirect, base NULL, outer 16 */
|
||||
7, /* ..01..11 memory indirect, base NULL, outer 32 */
|
||||
0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
|
||||
2, /* ..10.000 no memory indirect, base 16 */
|
||||
7, /* ..10..01 memory indirect, base 16, outer NULL */
|
||||
9, /* ..10..10 memory indirect, base 16, outer 16 */
|
||||
9, /* ..10..11 memory indirect, base 16, outer 32 */
|
||||
0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
|
||||
6, /* ..11.000 no memory indirect, base 32 */
|
||||
11, /* ..11..01 memory indirect, base 32, outer NULL */
|
||||
13, /* ..11..10 memory indirect, base 32, outer 16 */
|
||||
13, /* ..11..11 memory indirect, base 32, outer 32 */
|
||||
0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== CALLBACKS ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Default callbacks used if the callback hasn't been set yet, or if the
|
||||
* callback is set to NULL
|
||||
*/
|
||||
|
||||
/* Interrupt acknowledge */
|
||||
static int default_int_ack_callback_data;
|
||||
static int default_int_ack_callback(int int_level)
|
||||
{
|
||||
default_int_ack_callback_data = int_level;
|
||||
CPU_INT_LEVEL = 0;
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
/* Breakpoint acknowledge */
|
||||
static unsigned int default_bkpt_ack_callback_data;
|
||||
static void default_bkpt_ack_callback(unsigned int data)
|
||||
{
|
||||
default_bkpt_ack_callback_data = data;
|
||||
}
|
||||
|
||||
/* Called when a reset instruction is executed */
|
||||
static void default_reset_instr_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called when the program counter changed by a large value */
|
||||
static unsigned int default_pc_changed_callback_data;
|
||||
static void default_pc_changed_callback(unsigned int new_pc)
|
||||
{
|
||||
default_pc_changed_callback_data = new_pc;
|
||||
}
|
||||
|
||||
/* Called every time there's bus activity (read/write to/from memory */
|
||||
static unsigned int default_set_fc_callback_data;
|
||||
static void default_set_fc_callback(unsigned int new_fc)
|
||||
{
|
||||
default_set_fc_callback_data = new_fc;
|
||||
}
|
||||
|
||||
/* Called every instruction cycle prior to execution */
|
||||
static void default_instr_hook_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
#include <setjmp.h>
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Access the internals of the CPU */
|
||||
unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
|
||||
{
|
||||
m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
|
||||
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: return cpu->dar[0];
|
||||
case M68K_REG_D1: return cpu->dar[1];
|
||||
case M68K_REG_D2: return cpu->dar[2];
|
||||
case M68K_REG_D3: return cpu->dar[3];
|
||||
case M68K_REG_D4: return cpu->dar[4];
|
||||
case M68K_REG_D5: return cpu->dar[5];
|
||||
case M68K_REG_D6: return cpu->dar[6];
|
||||
case M68K_REG_D7: return cpu->dar[7];
|
||||
case M68K_REG_A0: return cpu->dar[8];
|
||||
case M68K_REG_A1: return cpu->dar[9];
|
||||
case M68K_REG_A2: return cpu->dar[10];
|
||||
case M68K_REG_A3: return cpu->dar[11];
|
||||
case M68K_REG_A4: return cpu->dar[12];
|
||||
case M68K_REG_A5: return cpu->dar[13];
|
||||
case M68K_REG_A6: return cpu->dar[14];
|
||||
case M68K_REG_A7: return cpu->dar[15];
|
||||
case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
|
||||
case M68K_REG_SR: return cpu->t1_flag |
|
||||
cpu->t0_flag |
|
||||
(cpu->s_flag << 11) |
|
||||
(cpu->m_flag << 11) |
|
||||
cpu->int_mask |
|
||||
((cpu->x_flag & XFLAG_SET) >> 4) |
|
||||
((cpu->n_flag & NFLAG_SET) >> 4) |
|
||||
((!cpu->not_z_flag) << 2) |
|
||||
((cpu->v_flag & VFLAG_SET) >> 6) |
|
||||
((cpu->c_flag & CFLAG_SET) >> 8);
|
||||
case M68K_REG_SP: return cpu->dar[15];
|
||||
case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
|
||||
case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
|
||||
case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
|
||||
case M68K_REG_SFC: return cpu->sfc;
|
||||
case M68K_REG_DFC: return cpu->dfc;
|
||||
case M68K_REG_VBR: return cpu->vbr;
|
||||
case M68K_REG_CACR: return cpu->cacr;
|
||||
case M68K_REG_CAAR: return cpu->caar;
|
||||
case M68K_REG_PREF_ADDR: return cpu->pref_addr;
|
||||
case M68K_REG_PREF_DATA: return cpu->pref_data;
|
||||
case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
|
||||
case M68K_REG_IR: return cpu->ir;
|
||||
case M68K_REG_CPU_TYPE:
|
||||
switch(cpu->cpu_type)
|
||||
{
|
||||
case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
|
||||
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
|
||||
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
|
||||
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
|
||||
}
|
||||
return M68K_CPU_TYPE_INVALID;
|
||||
default: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
|
||||
{
|
||||
switch(regnum)
|
||||
{
|
||||
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
|
||||
case M68K_REG_SR: m68ki_set_sr(value); return;
|
||||
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_USP: if(FLAG_S)
|
||||
REG_USP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_ISP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_MSP: if(FLAG_S && FLAG_M)
|
||||
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||
else
|
||||
REG_MSP = MASK_OUT_ABOVE_32(value);
|
||||
return;
|
||||
case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_SFC: REG_SFC = value & 7; return;
|
||||
case M68K_REG_DFC: REG_DFC = value & 7; return;
|
||||
case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
|
||||
case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the callbacks */
|
||||
void m68k_set_int_ack_callback(int (*callback)(int int_level))
|
||||
{
|
||||
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
|
||||
}
|
||||
|
||||
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
|
||||
{
|
||||
CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
|
||||
}
|
||||
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
|
||||
{
|
||||
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
|
||||
}
|
||||
|
||||
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
|
||||
{
|
||||
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
|
||||
}
|
||||
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
/* Set the CPU type. */
|
||||
void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
{
|
||||
switch(cpu_type)
|
||||
{
|
||||
case M68K_CPU_TYPE_68000:
|
||||
CPU_TYPE = CPU_TYPE_000;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[0];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 2;
|
||||
CYC_DBCC_F_NOEXP = -2;
|
||||
CYC_DBCC_F_EXP = 2;
|
||||
CYC_SCC_R_TRUE = 2;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
CYC_RESET = 132;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68010:
|
||||
CPU_TYPE = CPU_TYPE_010;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[1];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[1];
|
||||
CYC_BCC_NOTAKE_B = -4;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 6;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
CYC_RESET = 130;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68EC020:
|
||||
CPU_TYPE = CPU_TYPE_EC020;
|
||||
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
CYC_RESET = 518;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68020:
|
||||
CPU_TYPE = CPU_TYPE_020;
|
||||
CPU_ADDRESS_MASK = 0xffffffff;
|
||||
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
CYC_RESET = 518;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute some instructions until we use up num_cycles clock cycles */
|
||||
/* ASG: removed per-instruction interrupt checks */
|
||||
int m68k_execute(int num_cycles)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(!CPU_STOPPED)
|
||||
{
|
||||
/* Set our pool of clock cycles available */
|
||||
SET_CYCLES(num_cycles);
|
||||
m68ki_initial_cycles = num_cycles;
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* Return point if we had an address error */
|
||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Main loop. Keep going until we run out of clock cycles */
|
||||
do
|
||||
{
|
||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Set the address space for reads */
|
||||
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Call external hook to peek at CPU */
|
||||
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Record previous program counter */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* Read an instruction and call its handler */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
|
||||
/* Trace m68k_exception, if necessary */
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
} while(GET_CYCLES() > 0);
|
||||
|
||||
/* set previous PC to current PC for the next entry into the loop */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* return how many clocks we used */
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
}
|
||||
|
||||
/* We get here if the CPU is stopped or halted */
|
||||
SET_CYCLES(0);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
return num_cycles;
|
||||
}
|
||||
|
||||
|
||||
int m68k_cycles_run(void)
|
||||
{
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
}
|
||||
|
||||
int m68k_cycles_remaining(void)
|
||||
{
|
||||
return GET_CYCLES();
|
||||
}
|
||||
|
||||
/* Change the timeslice */
|
||||
void m68k_modify_timeslice(int cycles)
|
||||
{
|
||||
m68ki_initial_cycles += cycles;
|
||||
ADD_CYCLES(cycles);
|
||||
}
|
||||
|
||||
|
||||
void m68k_end_timeslice(void)
|
||||
{
|
||||
m68ki_initial_cycles = GET_CYCLES();
|
||||
SET_CYCLES(0);
|
||||
}
|
||||
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
uint old_level = CPU_INT_LEVEL;
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
|
||||
/* A transition from < 7 to 7 always interrupts (NMI) */
|
||||
/* Note: Level 7 can also level trigger like a normal IRQ */
|
||||
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
|
||||
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
|
||||
else
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
void m68k_init(void)
|
||||
{
|
||||
static uint emulation_initialized = 0;
|
||||
|
||||
/* The first call to this function initializes the opcode handler jump table */
|
||||
if(!emulation_initialized)
|
||||
{
|
||||
m68ki_build_opcode_table();
|
||||
emulation_initialized = 1;
|
||||
}
|
||||
|
||||
m68k_set_int_ack_callback(NULL);
|
||||
m68k_set_bkpt_ack_callback(NULL);
|
||||
m68k_set_reset_instr_callback(NULL);
|
||||
m68k_set_pc_changed_callback(NULL);
|
||||
m68k_set_fc_callback(NULL);
|
||||
m68k_set_instr_hook_callback(NULL);
|
||||
}
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
{
|
||||
/* Clear all stop levels and eat up all remaining cycles */
|
||||
CPU_STOPPED = 0;
|
||||
SET_CYCLES(0);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||
CPU_INSTR_MODE = INSTRUCTION_YES;
|
||||
|
||||
/* Turn off tracing */
|
||||
FLAG_T1 = FLAG_T0 = 0;
|
||||
m68ki_clear_trace();
|
||||
/* Interrupt mask to level 7 */
|
||||
FLAG_INT_MASK = 0x0700;
|
||||
/* Reset VBR */
|
||||
REG_VBR = 0;
|
||||
/* Go to supervisor mode */
|
||||
m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
|
||||
|
||||
/* Invalidate the prefetch queue */
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
/* Set to arbitrary number since our first fetch is from 0 */
|
||||
CPU_PREF_ADDR = 0x1000;
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
|
||||
/* Read the initial stack pointer and program counter */
|
||||
m68ki_jump(0);
|
||||
REG_SP = m68ki_read_imm_32();
|
||||
REG_PC = m68ki_read_imm_32();
|
||||
m68ki_jump(REG_PC);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||
}
|
||||
|
||||
/* Pulse the HALT line on the CPU */
|
||||
void m68k_pulse_halt(void)
|
||||
{
|
||||
CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
}
|
||||
|
||||
|
||||
/* Get and set the current CPU context */
|
||||
/* This is to allow for multiple CPUs */
|
||||
unsigned int m68k_context_size()
|
||||
{
|
||||
return sizeof(m68ki_cpu_core);
|
||||
}
|
||||
|
||||
unsigned int m68k_get_context(void* dst)
|
||||
{
|
||||
if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
|
||||
return sizeof(m68ki_cpu_core);
|
||||
}
|
||||
|
||||
void m68k_set_context(void* src)
|
||||
{
|
||||
if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
|
||||
#include "state.h"
|
||||
|
||||
static struct {
|
||||
UINT16 sr;
|
||||
int stopped;
|
||||
int halted;
|
||||
} m68k_substate;
|
||||
|
||||
static void m68k_prepare_substate(void)
|
||||
{
|
||||
m68k_substate.sr = m68ki_get_sr();
|
||||
m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
|
||||
m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
|
||||
}
|
||||
|
||||
static void m68k_post_load(void)
|
||||
{
|
||||
m68ki_set_sr_noint_nosp(m68k_substate.sr);
|
||||
CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
|
||||
| m68k_substate.halted ? STOP_LEVEL_HALT : 0;
|
||||
m68ki_jump(REG_PC);
|
||||
}
|
||||
|
||||
void m68k_state_register(const char *type)
|
||||
{
|
||||
int cpu = cpu_getactivecpu();
|
||||
|
||||
state_save_register_UINT32(type, cpu, "D" , REG_D, 8);
|
||||
state_save_register_UINT32(type, cpu, "A" , REG_A, 8);
|
||||
state_save_register_UINT32(type, cpu, "PPC" , ®_PPC, 1);
|
||||
state_save_register_UINT32(type, cpu, "PC" , ®_PC, 1);
|
||||
state_save_register_UINT32(type, cpu, "USP" , ®_USP, 1);
|
||||
state_save_register_UINT32(type, cpu, "ISP" , ®_ISP, 1);
|
||||
state_save_register_UINT32(type, cpu, "MSP" , ®_MSP, 1);
|
||||
state_save_register_UINT32(type, cpu, "VBR" , ®_VBR, 1);
|
||||
state_save_register_UINT32(type, cpu, "SFC" , ®_SFC, 1);
|
||||
state_save_register_UINT32(type, cpu, "DFC" , ®_DFC, 1);
|
||||
state_save_register_UINT32(type, cpu, "CACR" , ®_CACR, 1);
|
||||
state_save_register_UINT32(type, cpu, "CAAR" , ®_CAAR, 1);
|
||||
state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1);
|
||||
state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1);
|
||||
state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1);
|
||||
state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped);
|
||||
state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted);
|
||||
state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1);
|
||||
state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1);
|
||||
state_save_register_func_presave(m68k_prepare_substate);
|
||||
state_save_register_func_postload(m68k_post_load);
|
||||
}
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue