cleanup vjaguar code

This commit is contained in:
CasualPokePlayer 2022-09-19 04:41:10 -07:00
parent 71e3dfed74
commit d50454b37a
48 changed files with 1267 additions and 17795 deletions

Binary file not shown.

View File

@ -38,10 +38,6 @@ static s16 latchL, latchR;
EXPORT bool Init(BizSettings* bizSettings, u8* boot, u8* rom, u32 sz)
{
vjs.GPUEnabled = true;
vjs.DSPEnabled = true;
vjs.usePipelinedDSP = false;
vjs.renderType = RT_NORMAL;
vjs.hardwareTypeNTSC = bizSettings->hardwareTypeNTSC;
vjs.useJaguarBIOS = bizSettings->useJaguarBIOS;
vjs.useFastBlitter = bizSettings->useFastBlitter;

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
#ifndef __BLITTER_H__
#define __BLITTER_H__
//#include "types.h"
#include "memory.h"
void BlitterInit(void);
@ -22,9 +21,4 @@ void BlitterWriteLong(uint32_t, uint32_t, uint32_t who = UNKNOWN);
uint32_t blitter_reg_read(uint32_t offset);
void blitter_reg_write(uint32_t offset, uint32_t data);
extern uint8_t blitter_working;
//For testing only...
void LogBlit(void);
#endif // __BLITTER_H__

View File

@ -11,151 +11,28 @@
// JLH 01/16/2010 Created this log ;-)
//
//
// This now uses the supposedly cross-platform libcdio to do the necessary
// low-level CD twiddling we need that libsdl can't do currently. Jury is
// still out on whether or not to make this a conditional compilation or not.
//
// Comment this out if you don't have libcdio installed
// (Actually, this is defined in the Makefile to prevent having to edit
// things too damn much. Jury is still out whether or not to make this
// change permanent.)
//#define HAVE_LIB_CDIO
#include "cdintf.h" // Every OS has to implement these
#ifdef HAVE_LIB_CDIO
#include <cdio/cdio.h> // Now using OS agnostic CD access routines!
#endif
#include "log.h"
/*
static void TestCDIO(void)
{
// See what (if anything) is installed.
CdIo_t * p_cdio = cdio_open(0, DRIVER_DEVICE);
driver_id_t driver_id;
if (p_cdio != NULL)
{
WriteLog("CDIO: The driver selected is %s.\n", cdio_get_driver_name(p_cdio));
WriteLog("CDIO: The default device for this driver is %s.\n\n", cdio_get_default_device(p_cdio));
cdio_destroy(p_cdio);
}
else
{
WriteLog("CDIO: A suitable CD-ROM driver was not found.\n\n");
}
}
*/
//
// *** OK, here's where we're going to attempt to put the platform agnostic CD interface ***
//
#ifdef HAVE_LIB_CDIO
static CdIo_t * cdioPtr = NULL;
#endif
#include "cdintf.h"
bool CDIntfInit(void)
{
#ifdef HAVE_LIB_CDIO
cdioPtr = cdio_open(NULL, DRIVER_DEVICE);
if (cdioPtr == NULL)
{
#endif
WriteLog("CDINTF: No suitable CD-ROM driver found.\n");
return false;
#ifdef HAVE_LIB_CDIO
}
WriteLog("CDINTF: Successfully opened CD-ROM interface.\n");
return true;
#endif
}
void CDIntfDone(void)
{
WriteLog("CDINTF: Shutting down CD-ROM subsystem.\n");
#ifdef HAVE_LIB_CDIO
if (cdioPtr)
cdio_destroy(cdioPtr);
#endif
}
bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
{
#warning "!!! FIX !!! CDIntfReadBlock not implemented!"
// !!! FIX !!!
WriteLog("CDINTF: ReadBlock unimplemented!\n");
return false;
}
uint32_t CDIntfGetNumSessions(void)
void CDIntfDone(void)
{
#warning "!!! FIX !!! CDIntfGetNumSessions not implemented!"
// !!! FIX !!!
// Still need relevant code here... !!! FIX !!!
return 2;
}
void CDIntfSelectDrive(uint32_t driveNum)
bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
{
#warning "!!! FIX !!! CDIntfSelectDrive not implemented!"
// !!! FIX !!!
WriteLog("CDINTF: SelectDrive unimplemented!\n");
return false;
}
uint32_t CDIntfGetCurrentDrive(void)
{
#warning "!!! FIX !!! CDIntfGetCurrentDrive not implemented!"
// !!! FIX !!!
WriteLog("CDINTF: GetCurrentDrive unimplemented!\n");
return 0;
}
const uint8_t * CDIntfGetDriveName(uint32_t driveNum)
{
#warning "!!! FIX !!! CDIntfGetDriveName driveNum is currently ignored!"
// driveNum is currently ignored... !!! FIX !!!
#ifdef HAVE_LIB_CDIO
uint8_t * driveName = (uint8_t *)cdio_get_default_device(cdioPtr);
WriteLog("CDINTF: The drive name for the current driver is %s.\n", driveName);
return driveName;
#else
return (uint8_t *)"NONE";
#endif
}
uint8_t CDIntfGetSessionInfo(uint32_t session, uint32_t offset)
{
#warning "!!! FIX !!! CDIntfGetSessionInfo not implemented!"
// !!! FIX !!!
WriteLog("CDINTF: GetSessionInfo unimplemented!\n");
return 0xFF;
}
uint8_t CDIntfGetTrackInfo(uint32_t track, uint32_t offset)
{
#warning "!!! FIX !!! CDIntfTrackInfo not implemented!"
// !!! FIX !!!
WriteLog("CDINTF: GetTrackInfo unimplemented!\n");
return 0xFF;
}

View File

@ -12,10 +12,6 @@
bool CDIntfInit(void);
void CDIntfDone(void);
bool CDIntfReadBlock(uint32_t, uint8_t *);
uint32_t CDIntfGetNumSessions(void);
void CDIntfSelectDrive(uint32_t);
uint32_t CDIntfGetCurrentDrive(void);
const uint8_t * CDIntfGetDriveName(uint32_t);
uint8_t CDIntfGetSessionInfo(uint32_t, uint32_t);
uint8_t CDIntfGetTrackInfo(uint32_t, uint32_t);

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
#ifndef __CDROM_H__
#define __CDROM_H__
//#include "types.h"
#include "memory.h"
void CDROMInit(void);

View File

@ -51,7 +51,6 @@ static unsigned long crctable[256] =
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};
int crc32_calcCheckSum(unsigned char * data, unsigned int length)
{
unsigned long crc = 0xFFFFFFFF;

View File

@ -47,14 +47,9 @@
#include "event.h"
#include "jerry.h"
#include "jaguar.h"
#include "log.h"
#include "m68000/m68kinterface.h"
//#include "memory.h"
#include "settings.h"
//#define DEBUG_DAC
#define BUFFER_SIZE 0x10000 // Make the DAC buffers 64K x 16 bits
#define DAC_AUDIO_RATE 48000 // Set the audio rate to 48 KHz
@ -67,59 +62,29 @@
#define SCLK 0xF1A150
#define SMODE 0xF1A154
// Global variables
// These are defined in memory.h/cpp
//uint16_t lrxd, rrxd; // I2S ports (into Jaguar)
// Local variables
//static uint8_t SCLKFrequencyDivider = 19; // Default is roughly 22 KHz (20774 Hz in NTSC mode)
// /*static*/ uint16_t serialMode = 0;
// Private function prototypes
void DSPSampleCallback(void);
//
// Initialize the SDL sound system
//
void DACInit(void)
{
ltxd = lrxd = 0;
sclk = 19; // Default is roughly 22 KHz
sclk = 19;
uint32_t riscClockRate = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
uint32_t cyclesPerSample = riscClockRate / DAC_AUDIO_RATE;
WriteLog("DAC: RISC clock = %u, cyclesPerSample = %u\n", riscClockRate, cyclesPerSample);
}
//
// Reset the sound buffer FIFOs
//
void DACReset(void)
{
// LeftFIFOHeadPtr = LeftFIFOTailPtr = 0, RightFIFOHeadPtr = RightFIFOTailPtr = 1;
ltxd = lrxd = 0;
}
//
// Pause/unpause the SDL audio thread
//
void DACPauseAudioThread(bool state/*= true*/)
{
}
//
// Close down the SDL sound subsystem
//
void DACDone(void)
{
WriteLog("DAC: Done.\n");
}
@ -133,15 +98,17 @@ void DACDone(void)
// If the DSP isn't running, then fill the buffer with L/RTXD and exit.
//
// SDL callback routine to fill audio buffer
// Callback routine to fill audio buffer
//
// Note: The samples are packed in the buffer in 16 bit left/16 bit right pairs.
// Also, length is the length of the buffer in BYTES
//
static uint16_t * sampleBuffer;
static int bufferIndex = 0;
static int numberOfSamples = 0;
static bool bufferDone = false;
void SoundCallback(uint16_t * buffer, int length)
{
// 1st, check to see if the DSP is running. If not, fill the buffer with L/RXTD and exit.
@ -157,37 +124,18 @@ void SoundCallback(uint16_t * buffer, int length)
return;
}
// The length of time we're dealing with here is 1/48000 s, so we multiply this
// by the number of cycles per second to get the number of cycles for one sample.
// uint32_t riscClockRate = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
// uint32_t cyclesPerSample = riscClockRate / DAC_AUDIO_RATE;
// This is the length of time
// timePerSample = (1000000.0 / (double)riscClockRate) * ();
// Now, run the DSP for that length of time for each sample we need to make
bufferIndex = 0;
sampleBuffer = buffer;
// If length is the length of the sample buffer in BYTES, then shouldn't the # of
// samples be / 4? No, because we bump the sample count by 2, so this is OK.
numberOfSamples = length / 2;
bufferDone = false;
SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY);
// These timings are tied to NTSC, need to fix that in event.cpp/h! [FIXED]
do
{
double timeToNextEvent = GetTimeToNextEvent(EVENT_JERRY);
if (vjs.DSPEnabled)
{
if (vjs.usePipelinedDSP)
DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent));
else
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
}
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
HandleNextEvent(EVENT_JERRY);
}
while (!bufferDone);
@ -209,34 +157,16 @@ void DSPSampleCallback(void)
SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY);
}
#if 0
//
// Calculate the frequency of SCLK * 32 using the divider
//
int GetCalculatedFrequency(void)
{
int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
// We divide by 32 here in order to find the frequency of 32 SCLKs in a row (transferring
// 16 bits of left data + 16 bits of right data = 32 bits, 1 SCLK = 1 bit transferred).
return systemClockFrequency / (32 * (2 * (SCLKFrequencyDivider + 1)));
}
#endif
//
// LTXD/RTXD/SCLK/SMODE ($F1A148/4C/50/54)
//
void DACWriteByte(uint32_t offset, uint8_t data, uint32_t who/*= UNKNOWN*/)
void DACWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{
WriteLog("DAC: %s writing BYTE %02X at %08X\n", whoName[who], data, offset);
if (offset == SCLK + 3)
DACWriteWord(offset - 3, (uint16_t)data);
}
void DACWriteWord(uint32_t offset, uint16_t data, uint32_t who/*= UNKNOWN*/)
void DACWriteWord(uint32_t offset, uint16_t data, uint32_t who)
{
if (offset == LTXD + 2)
{
@ -246,10 +176,8 @@ void DACWriteWord(uint32_t offset, uint16_t data, uint32_t who/*= UNKNOWN*/)
{
rtxd = data;
}
else if (offset == SCLK + 2) // Sample rate
else if (offset == SCLK + 2)
{
WriteLog("DAC: Writing %u to SCLK (by %s)...\n", data, whoName[who]);
sclk = data & 0xFF;
JERRYI2SInterruptTimer = -1;
RemoveCallback(JERRYI2SCallback);
@ -257,38 +185,20 @@ void DACWriteWord(uint32_t offset, uint16_t data, uint32_t who/*= UNKNOWN*/)
}
else if (offset == SMODE + 2)
{
// serialMode = data;
smode = data;
WriteLog("DAC: %s writing to SMODE. Bits: %s%s%s%s%s%s [68K PC=%08X]\n", whoName[who],
(data & 0x01 ? "INTERNAL " : ""), (data & 0x02 ? "MODE " : ""),
(data & 0x04 ? "WSEN " : ""), (data & 0x08 ? "RISING " : ""),
(data & 0x10 ? "FALLING " : ""), (data & 0x20 ? "EVERYWORD" : ""),
m68k_get_reg(NULL, M68K_REG_PC));
}
}
//
// LRXD/RRXD/SSTAT ($F1A148/4C/50)
//
uint8_t DACReadByte(uint32_t offset, uint32_t who/*= UNKNOWN*/)
uint8_t DACReadByte(uint32_t offset, uint32_t who)
{
// WriteLog("DAC: %s reading byte from %08X\n", whoName[who], offset);
return 0xFF;
}
//static uint16_t fakeWord = 0;
uint16_t DACReadWord(uint32_t offset, uint32_t who/*= UNKNOWN*/)
uint16_t DACReadWord(uint32_t offset, uint32_t who)
{
// WriteLog("DAC: %s reading word from %08X\n", whoName[who], offset);
// return 0xFFFF;
// WriteLog("DAC: %s reading WORD %04X from %08X\n", whoName[who], fakeWord, offset);
// return fakeWord++;
//NOTE: This only works if a bunch of things are set in BUTCH which we currently don't
// check for. !!! FIX !!!
// Partially fixed: We check for I2SCNTRL in the JERRY I2S routine...
// return GetWordFromButchSSI(offset, who);
if (offset == LRXD || offset == RRXD)
return 0x0000;
else if (offset == LRXD + 2)
@ -296,6 +206,6 @@ uint16_t DACReadWord(uint32_t offset, uint32_t who/*= UNKNOWN*/)
else if (offset == RRXD + 2)
return rrxd;
return 0xFFFF; // May need SSTAT as well... (but may be a Jaguar II only feature)
return 0xFFFF;
}

View File

@ -9,9 +9,7 @@
void DACInit(void);
void DACReset(void);
void DACPauseAudioThread(bool state = true);
void DACDone(void);
//int GetCalculatedFrequency(void);
// DAC memory access
@ -20,7 +18,6 @@ void DACWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
uint8_t DACReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t DACReadWord(uint32_t offset, uint32_t who = UNKNOWN);
// DAC defines
#define SMODE_INTERNAL 0x01

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,6 @@ void DSPReset(void);
void DSPExec(int32_t);
void DSPDone(void);
void DSPUpdateRegisterBanks(void);
void DSPHandleIRQs(void);
void DSPSetIRQLine(int irqline, int state);
uint8_t DSPReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t DSPReadWord(uint32_t offset, uint32_t who = UNKNOWN);
@ -26,14 +25,8 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN);
void DSPReleaseTimeslice(void);
bool DSPIsRunning(void);
void DSPExecP(int32_t cycles);
void DSPExecP2(int32_t cycles);
//void DSPExecP3(int32_t cycles);
void DSPExecComp(int32_t cycles);
// Exported vars
extern bool doDSPDis;
extern uint32_t dsp_reg_bank_0[], dsp_reg_bank_1[];
// DSP interrupt numbers (in $F1A100, bits 4-8 & 16)

View File

@ -16,34 +16,22 @@
#include "eeprom.h"
#include <stdlib.h>
#include <string.h> // For memset
#include <string.h>
#include "jaguar.h"
#include "log.h"
#include "settings.h"
//#define eeprom_LOG
uint16_t eeprom_ram[64];
uint16_t cdromEEPROM[64];
bool eeprom_dirty;
//
// Private function prototypes
//
static void EEPROMSave(void);
static void eeprom_set_di(uint32_t state);
static void eeprom_set_cs(uint32_t state);
static uint32_t eeprom_get_do(void);
enum { EE_STATE_START = 1, EE_STATE_OP_A, EE_STATE_OP_B, EE_STATE_0, EE_STATE_1,
EE_STATE_2, EE_STATE_3, EE_STATE_0_0, EE_READ_ADDRESS, EE_STATE_0_0_0,
EE_STATE_0_0_1, EE_STATE_0_0_2, EE_STATE_0_0_3, EE_STATE_0_0_1_0, EE_READ_DATA,
EE_STATE_BUSY, EE_STATE_1_0, EE_STATE_1_1, EE_STATE_2_0, EE_STATE_3_0 };
// Local global variables
static uint16_t jerry_ee_state = EE_STATE_START;
static uint16_t jerry_ee_op = 0;
static uint16_t jerry_ee_rstate = 0;
@ -54,47 +42,36 @@ static uint16_t jerry_ee_data_cnt = 16;
static uint16_t jerry_writes_enabled = 0;
static uint16_t jerry_ee_direct_jump = 0;
static char eeprom_filename[MAX_PATH];
static char cdromEEPROMFilename[MAX_PATH];
void EepromInit(void)
{
memset(eeprom_ram, 0xFF, 64 * sizeof(uint16_t));
memset(cdromEEPROM, 0xFF, 64 * sizeof(uint16_t));
eeprom_dirty = false;
}
void EepromReset(void)
{
}
void EepromDone(void)
{
WriteLog("EEPROM: Done.\n");
}
static void EEPROMSave(void)
{
eeprom_dirty = true;
}
uint8_t EepromReadByte(uint32_t offset)
{
switch (offset)
{
case 0xF14001:
return eeprom_get_do();
case 0xF14801:
break;
case 0xF15001:
eeprom_set_cs(1);
break;
// default: WriteLog("EEPROM: unmapped 0x%.8x\n", offset); break;
case 0xF14001:
return eeprom_get_do();
case 0xF14801:
break;
case 0xF15001:
eeprom_set_cs(1);
break;
}
return 0x00;
@ -106,231 +83,182 @@ uint16_t EepromReadWord(uint32_t offset)
return ((uint16_t)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1);
}
void EepromWriteByte(uint32_t offset, uint8_t data)
{
switch (offset)
{
case 0xF14001:
break;
case 0xF14801:
eeprom_set_di(data & 0x01);
break;
case 0xF15001:
eeprom_set_cs(1);
break;
// default: WriteLog("eeprom: unmapped 0x%.8x\n",offset); break;
case 0xF14001:
break;
case 0xF14801:
eeprom_set_di(data & 0x01);
break;
case 0xF15001:
eeprom_set_cs(1);
break;
}
}
void EepromWriteWord(uint32_t offset, uint16_t data)
{
EepromWriteByte(offset + 0, (data >> 8) & 0xFF);
EepromWriteByte(offset + 1, data & 0xFF);
}
/*
;
; Commands specific to the National Semiconductor NM93C14
;
;
; 9-bit commands..
; 876543210
eEWDS equ %100000000 ;Erase/Write disable (default)
eWRAL equ %100010000 ;Writes all registers
eERAL equ %100100000 ;Erase all registers
eEWEN equ %100110000 ;Erase/write Enable
eWRITE equ %101000000 ;Write selected register
eREAD equ %110000000 ;read from EEPROM
eERASE equ %111000000 ;Erase selected register
*/
static void eeprom_set_di(uint32_t data)
{
// WriteLog("eeprom: di=%i\n",data);
// WriteLog("eeprom: state %i\n",jerry_ee_state);
switch (jerry_ee_state)
{
case EE_STATE_START:
jerry_ee_state = EE_STATE_OP_A;
break;
case EE_STATE_OP_A:
jerry_ee_op = (data << 1);
jerry_ee_state = EE_STATE_OP_B;
break;
case EE_STATE_OP_B:
jerry_ee_op |= data;
jerry_ee_direct_jump = 0;
// WriteLog("eeprom: opcode %i\n",jerry_ee_op);
case EE_STATE_START:
jerry_ee_state = EE_STATE_OP_A;
break;
case EE_STATE_OP_A:
jerry_ee_op = (data << 1);
jerry_ee_state = EE_STATE_OP_B;
break;
case EE_STATE_OP_B:
jerry_ee_op |= data;
jerry_ee_direct_jump = 0;
switch (jerry_ee_op)
{
// Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS
case 0: jerry_ee_state = EE_STATE_0; break;
// Opcode 01: eWRITE (Write selected register)
case 1: jerry_ee_state = EE_STATE_1; break;
// Opcode 10: eREAD (Read from EEPROM)
case 2: jerry_ee_state = EE_STATE_2; break;
// Opcode 11: eERASE (Erase selected register)
case 3: jerry_ee_state = EE_STATE_3; break;
}
switch (jerry_ee_op)
{
case 0: jerry_ee_state = EE_STATE_0; break;
case 1: jerry_ee_state = EE_STATE_1; break;
case 2: jerry_ee_state = EE_STATE_2; break;
case 3: jerry_ee_state = EE_STATE_3; break;
}
eeprom_set_di(data);
break;
case EE_STATE_0:
jerry_ee_rstate = EE_STATE_0_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_direct_jump = 1;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
break;
case EE_STATE_0_0:
switch ((jerry_ee_address_data >> 4) & 0x03)
{
// Opcode 00 00: eEWDS (Erase/Write disable)
case 0: jerry_ee_state=EE_STATE_0_0_0; break;
// Opcode 00 01: eWRAL (Write all registers)
case 1: jerry_ee_state=EE_STATE_0_0_1; break;
// Opcode 00 10: eERAL (Erase all registers)
case 2: jerry_ee_state=EE_STATE_0_0_2; break;
// Opcode 00 11: eEWEN (Erase/Write enable)
case 3: jerry_ee_state=EE_STATE_0_0_3; break;
}
eeprom_set_di(data);
break;
case EE_STATE_0:
jerry_ee_rstate = EE_STATE_0_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_direct_jump = 1;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
break;
case EE_STATE_0_0:
switch ((jerry_ee_address_data >> 4) & 0x03)
{
case 0: jerry_ee_state=EE_STATE_0_0_0; break;
case 1: jerry_ee_state=EE_STATE_0_0_1; break;
case 2: jerry_ee_state=EE_STATE_0_0_2; break;
case 3: jerry_ee_state=EE_STATE_0_0_3; break;
}
eeprom_set_di(data);
break;
case EE_STATE_0_0_0:
// writes disable
// WriteLog("eeprom: read only\n");
jerry_writes_enabled = 0;
jerry_ee_state = EE_STATE_START;
break;
case EE_STATE_0_0_1:
// writes all
jerry_ee_rstate = EE_STATE_0_0_1_0;
jerry_ee_state = EE_READ_DATA;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_0_0_1_0:
// WriteLog("eeprom: filling eeprom with 0x%.4x\n",data);
if (jerry_writes_enabled)
{
for(int i=0; i<64; i++)
eeprom_ram[i] = jerry_ee_data;
eeprom_set_di(data);
break;
case EE_STATE_0_0_0:
jerry_writes_enabled = 0;
jerry_ee_state = EE_STATE_START;
break;
case EE_STATE_0_0_1:
jerry_ee_rstate = EE_STATE_0_0_1_0;
jerry_ee_state = EE_READ_DATA;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_0_0_1_0:
if (jerry_writes_enabled)
{
for(int i=0; i<64; i++)
eeprom_ram[i] = jerry_ee_data;
EEPROMSave(); // Save it NOW!
}
EEPROMSave();
}
//else
// WriteLog("eeprom: not writing because read only\n");
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_0_0_2:
// erase all
//WriteLog("eeprom: erasing eeprom\n");
if (jerry_writes_enabled)
for(int i=0; i<64; i++)
eeprom_ram[i] = 0xFFFF;
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_0_0_2:
if (jerry_writes_enabled)
for(int i=0; i<64; i++)
eeprom_ram[i] = 0xFFFF;
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_0_0_3:
// writes enable
//WriteLog("eeprom: read/write\n");
jerry_writes_enabled = 1;
jerry_ee_state = EE_STATE_START;
break;
case EE_STATE_1:
jerry_ee_rstate = EE_STATE_1_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_1_0:
jerry_ee_rstate = EE_STATE_1_1;
jerry_ee_state = EE_READ_DATA;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_1_1:
//WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data);
if (jerry_writes_enabled)
{
eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
EEPROMSave(); // Save it NOW!
}
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_0_0_3:
jerry_writes_enabled = 1;
jerry_ee_state = EE_STATE_START;
break;
case EE_STATE_1:
jerry_ee_rstate = EE_STATE_1_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_1_0:
jerry_ee_rstate = EE_STATE_1_1;
jerry_ee_state = EE_READ_DATA;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_1_1:
if (jerry_writes_enabled)
{
eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
EEPROMSave();
}
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_2:
jerry_ee_rstate = EE_STATE_2_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
break;
case EE_STATE_3:
jerry_ee_rstate = EE_STATE_3_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_3_0:
//WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data);
if (jerry_writes_enabled)
eeprom_ram[jerry_ee_address_data] = 0xFFFF;
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_STATE_2:
jerry_ee_rstate = EE_STATE_2_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_data_cnt = 16;
jerry_ee_data = 0;
break;
case EE_STATE_3:
jerry_ee_rstate = EE_STATE_3_0;
jerry_ee_state = EE_READ_ADDRESS;
jerry_ee_address_cnt = 6;
jerry_ee_address_data = 0;
jerry_ee_direct_jump = 1;
break;
case EE_STATE_3_0:
if (jerry_writes_enabled)
eeprom_ram[jerry_ee_address_data] = 0xFFFF;
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_READ_DATA:
//WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1);
jerry_ee_data <<= 1;
jerry_ee_data |= data;
jerry_ee_data_cnt--;
jerry_ee_state = EE_STATE_BUSY;
break;
case EE_READ_DATA:
jerry_ee_data <<= 1;
jerry_ee_data |= data;
jerry_ee_data_cnt--;
if (!jerry_ee_data_cnt)
{
jerry_ee_state = jerry_ee_rstate;
if (!jerry_ee_data_cnt)
{
jerry_ee_state = jerry_ee_rstate;
if (jerry_ee_direct_jump)
eeprom_set_di(data);
}
if (jerry_ee_direct_jump)
eeprom_set_di(data);
}
break;
case EE_READ_ADDRESS:
jerry_ee_address_data <<= 1;
jerry_ee_address_data |= data;
jerry_ee_address_cnt--;
// WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt);
break;
case EE_READ_ADDRESS:
jerry_ee_address_data <<= 1;
jerry_ee_address_data |= data;
jerry_ee_address_cnt--;
if (!jerry_ee_address_cnt)
{
jerry_ee_state = jerry_ee_rstate;
//WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data);
if (!jerry_ee_address_cnt)
{
jerry_ee_state = jerry_ee_rstate;
if (jerry_ee_direct_jump)
eeprom_set_di(data);
}
if (jerry_ee_direct_jump)
eeprom_set_di(data);
}
break;
default:
jerry_ee_state = EE_STATE_OP_A;
break;
default:
jerry_ee_state = EE_STATE_OP_A;
}
}
static void eeprom_set_cs(uint32_t /*state*/)
static void eeprom_set_cs(uint32_t)
{
// WriteLog("eeprom: cs=%i\n",state);
jerry_ee_state = EE_STATE_START;
jerry_ee_op = 0;
jerry_ee_rstate = 0;
@ -348,26 +276,24 @@ static uint32_t eeprom_get_do(void)
switch (jerry_ee_state)
{
case EE_STATE_START:
data = 1;
break;
case EE_STATE_BUSY:
jerry_ee_state = EE_STATE_START;
data = 0;
break;
case EE_STATE_2_0:
jerry_ee_data_cnt--;
data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01;
if (!jerry_ee_data_cnt)
{
//WriteLog("eeprom: read 0x%.4x at 0x%.2x cpu %i pc=0x%.8x\n",eeprom_ram[jerry_ee_address_data],jerry_ee_address_data,jaguar_cpu_in_exec,s68000readPC());
case EE_STATE_START:
data = 1;
break;
case EE_STATE_BUSY:
jerry_ee_state = EE_STATE_START;
}
break;
data = 0;
break;
case EE_STATE_2_0:
jerry_ee_data_cnt--;
data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01;
if (!jerry_ee_data_cnt)
{
jerry_ee_state = EE_STATE_START;
}
break;
}
// WriteLog("eeprom: do=%i\n",data);
return data;
}

View File

@ -20,13 +20,9 @@
#include "event.h"
#include <stdint.h>
#include "log.h"
//#define EVENT_LIST_SIZE 512
#define EVENT_LIST_SIZE 32
// Now, a bit of weirdness: It seems that the number of lines displayed on the screen
// makes the effective refresh rate either 30 or 25 Hz!
@ -47,14 +43,12 @@ struct Event
void (* timerCallback)(void);
};
static Event eventList[EVENT_LIST_SIZE];
static Event eventListJERRY[EVENT_LIST_SIZE];
static uint32_t nextEvent;
static uint32_t nextEventJERRY;
static uint32_t numberOfEvents;
void InitializeEventList(void)
{
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
@ -64,13 +58,9 @@ void InitializeEventList(void)
}
numberOfEvents = 0;
WriteLog("EVENT: Cleared event list.\n");
}
// Set callback time in µs. This is fairly arbitrary, but works well enough for our purposes.
//We just slap the next event into the list in the first available slot, no checking, no nada...
void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAIN*/)
void SetCallbackTime(void (* callback)(void), double time, int type)
{
if (type == EVENT_MAIN)
{
@ -78,7 +68,6 @@ void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAI
{
if (!eventList[i].valid)
{
//WriteLog("EVENT: Found callback slot #%u...\n", i);
eventList[i].timerCallback = callback;
eventList[i].eventTime = time;
eventList[i].eventType = type;
@ -88,8 +77,6 @@ void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAI
return;
}
}
WriteLog("EVENT: SetCallbackTime() failed to find an empty slot in the main list (%u events)!\n", numberOfEvents);
}
else
{
@ -97,7 +84,6 @@ void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAI
{
if (!eventListJERRY[i].valid)
{
//WriteLog("EVENT: Found callback slot #%u...\n", i);
eventListJERRY[i].timerCallback = callback;
eventListJERRY[i].eventTime = time;
eventListJERRY[i].eventType = type;
@ -107,12 +93,9 @@ void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAI
return;
}
}
WriteLog("EVENT: SetCallbackTime() failed to find an empty slot in the main list (%u events)!\n", numberOfEvents);
}
}
void RemoveCallback(void (* callback)(void))
{
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
@ -154,31 +137,12 @@ void AdjustCallbackTime(void (* callback)(void), double time)
}
}
//
// Since our list is unordered WRT time, we have to search it to find the next event
// Returns time to next event & sets nextEvent to that event
//
double GetTimeToNextEvent(int type/*= EVENT_MAIN*/)
double GetTimeToNextEvent(int type)
{
#if 0
double time = 0;
bool firstTime = true;
for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
{
if (eventList[i].valid)
{
if (firstTime)
time = eventList[i].eventTime, nextEvent = i, firstTime = false;
else
{
if (eventList[i].eventTime < time)
time = eventList[i].eventTime, nextEvent = i;
}
}
}
#else
if (type == EVENT_MAIN)
{
double time = eventList[0].eventTime;
@ -211,11 +175,9 @@ double GetTimeToNextEvent(int type/*= EVENT_MAIN*/)
return time;
}
#endif
}
void HandleNextEvent(int type/*= EVENT_MAIN*/)
void HandleNextEvent(int type)
{
if (type == EVENT_MAIN)
{
@ -224,13 +186,10 @@ void HandleNextEvent(int type/*= EVENT_MAIN*/)
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{
//We can skip the check & just subtract from everything, since the check is probably
//just as heavy as the code after and we won't use the elapsed time from an invalid event anyway.
// if (eventList[i].valid)
eventList[i].eventTime -= elapsedTime;
eventList[i].eventTime -= elapsedTime;
}
eventList[nextEvent].valid = false; // Remove event from list...
eventList[nextEvent].valid = false;
numberOfEvents--;
(*event)();
@ -242,101 +201,12 @@ void HandleNextEvent(int type/*= EVENT_MAIN*/)
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{
//We can skip the check & just subtract from everything, since the check is probably
//just as heavy as the code after and we won't use the elapsed time from an invalid event anyway.
// if (eventList[i].valid)
eventListJERRY[i].eventTime -= elapsedTime;
eventListJERRY[i].eventTime -= elapsedTime;
}
eventListJERRY[nextEventJERRY].valid = false; // Remove event from list...
eventListJERRY[nextEventJERRY].valid = false;
numberOfEvents--;
(*event)();
}
}
/*
void OPCallback(void)
{
DoFunkyOPStuffHere();
SetCallbackTime(OPCallback, HORIZ_PERIOD_IN_USEC);
}
void VICallback(void)
{
double oneFrameInUsec = 16666.66666666;
SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
}
void JaguarInit(void)
{
double oneFrameInUsec = 16666.66666666;
SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
SetCallbackTime(OPCallback, );
}
void JaguarExec(void)
{
while (true)
{
double timeToNextEvent = GetTimeToNextEvent();
m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
if (!HandleNextEvent())
break;
}
}
// NOTES: The timers count RISC cycles, and when the dividers count down to zero they can interrupt either the DSP and/or CPU.
// NEW:
// TOM Programmable Interrupt Timer handler
// NOTE: TOM's PIT is only enabled if the prescaler is != 0
// The PIT only generates an interrupt when it counts down to zero, not when loaded!
void TOMResetPIT()
{
// Need to remove previous timer from the queue, if it exists...
RemoveCallback(TOMPITCallback);
if (TOMPITPrescaler)
{
double usecs = (TOMPITPrescaler + 1) * (TOMPITDivider + 1) * RISC_CYCLE_IN_USEC;
SetCallbackTime(TOMPITCallback, usecs);
}
}
void TOMPITCallback(void)
{
INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking
if (INT1_WREG & 0x08)
m68k_set_irq(2); // Generate 68K NMI
TOMResetPIT();
}
// Small problem with this approach: If a timer interrupt is already pending,
// the pending timer needs to be replaced with the new one! (Taken care of above, BTW...)
TOMWriteWord(uint32 address, uint16 data)
{
if (address == PIT0)
{
TOMPITPrescaler = data;
TOMResetPIT();
}
else if (address == PIT1)
{
TOMPITDivider = data;
TOMResetPIT();
}
}
*/

View File

@ -20,35 +20,18 @@
#include <stdarg.h>
#include <string.h>
#include "crc32.h"
#include "filedb.h"
#include "eeprom.h"
#include "jaguar.h"
#include "log.h"
#include "memory.h"
#include "universalhdr.h"
// Private function prototypes
//static int ParseFileType(uint8_t header1, uint8_t header2, uint32_t size);
// Private variables/enums
//
// Jaguar file loading
// We do a more intelligent file analysis here instead of relying on (possible
// false) file extensions which people don't seem to give two shits about
// anyway. :-(
//
bool JaguarLoadFile(uint8_t * buffer, uint32_t size)
{
jaguarROMSize = size;
jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize);
WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32);
// TODO: Check for EEPROM file in ZIP file. If there is no EEPROM in the user's EEPROM
// directory, copy the one from the ZIP file, if it exists.
EepromInit();
jaguarRunAddress = 0x802000; // For non-BIOS runs, this is true
jaguarRunAddress = 0x802000;
int fileType = ParseFileType(buffer, jaguarROMSize);
jaguarCartInserted = false;
@ -56,31 +39,23 @@ bool JaguarLoadFile(uint8_t * buffer, uint32_t size)
{
jaguarCartInserted = true;
memcpy(jagMemSpace + 0x800000, buffer, jaguarROMSize);
// Checking something...
jaguarRunAddress = GET32(jagMemSpace, 0x800404);
WriteLog("FILE: Cartridge run address is reported as $%X...\n", jaguarRunAddress);
jaguarRunAddress = GET32(jagMemSpace, 0x800404);
return true;
}
else if (fileType == JST_ALPINE)
{
// File extension ".ROM": Alpine image that loads/runs at $802000
WriteLog("FILE: Setting up Alpine ROM... Run address: 00802000, length: %08X\n", jaguarROMSize);
memset(jagMemSpace + 0x800000, 0xFF, 0x2000);
memcpy(jagMemSpace + 0x802000, buffer, jaguarROMSize);
// Maybe instead of this, we could try requiring the STUBULATOR ROM? Just a thought...
// Try setting the vector to say, $1000 and putting an instruction there that loops forever:
// This kludge works! Yeah!
SET32(jaguarMainRAM, 0x10, 0x00001000);
SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here
SET16(jaguarMainRAM, 0x1000, 0x60FE);
return true;
}
else if (fileType == JST_ABS_TYPE1)
{
// For ABS type 1, run address == load address
uint32_t loadAddress = GET32(buffer, 0x16),
codeSize = GET32(buffer, 0x02) + GET32(buffer, 0x06);
WriteLog("FILE: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize);
memcpy(jagMemSpace + loadAddress, buffer + 0x24, codeSize);
jaguarRunAddress = loadAddress;
return true;
@ -89,134 +64,60 @@ WriteLog("FILE: Cartridge run address is reported as $%X...\n", jaguarRunAddress
{
uint32_t loadAddress = GET32(buffer, 0x28), runAddress = GET32(buffer, 0x24),
codeSize = GET32(buffer, 0x18) + GET32(buffer, 0x1C);
WriteLog("FILE: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize);
memcpy(jagMemSpace + loadAddress, buffer + 0xA8, codeSize);
jaguarRunAddress = runAddress;
return true;
}
// NB: This is *wrong*
/*
Basically, if there is no "JAG" at position $1C, then the long there is the load/start
address in LITTLE ENDIAN.
If "JAG" is present, the the next character ("R" or "L") determines the size of the
JagServer command (2 bytes vs. 4). Following that are the commands themselves;
typically it will either be 2 (load) or 3 (load & run). Command headers go like so:
2:
Load address (long)
Length (long)
payload
3:
Load address (long)
Length (long)
Run address (long)
payload
5: (Reset)
[command only]
7: (Run at address)
Run address (long)
[no payload]
9: (Clear memory)
Start address (long)
End address (long)
[no payload]
10: (Poll for commands)
[command only]
12: (Load & run user program)
filname, terminated with NULL
[no payload]
$FFFF: (Halt)
[no payload]
*/
else if (fileType == JST_JAGSERVER)
{
// This kind of shiaut should be in the detection code below...
// (and now it is! :-)
// if (buffer[0x1C] == 'J' && buffer[0x1D] == 'A' && buffer[0x1E] == 'G')
// {
// Still need to do some checking here for type 2 vs. type 3. This assumes 3
// Also, JAGR vs. JAGL (word command size vs. long command size)
uint32_t loadAddress = GET32(buffer, 0x22), runAddress = GET32(buffer, 0x2A);
WriteLog("FILE: Setting up homebrew (Jag Server)... Run address: $%X, length: $%X\n", runAddress, jaguarROMSize - 0x2E);
memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E);
jaguarRunAddress = runAddress;
uint32_t loadAddress = GET32(buffer, 0x22), runAddress = GET32(buffer, 0x2A);
memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E);
jaguarRunAddress = runAddress;
// Hmm. Is this kludge necessary?
SET32(jaguarMainRAM, 0x10, 0x00001000); // Set Exception #4 (Illegal Instruction)
SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here
SET32(jaguarMainRAM, 0x10, 0x00001000);
SET16(jaguarMainRAM, 0x1000, 0x60FE);
return true;
// }
// else // Special WTFOMGBBQ type here...
// {
// uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C];
// WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20);
// memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20);
// jaguarRunAddress = loadAddress;
// return true;
// }
return true;
}
else if (fileType == JST_WTFOMGBBQ)
{
uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C];
WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20);
memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20);
jaguarRunAddress = loadAddress;
return true;
}
// We can assume we have JST_NONE at this point. :-P
WriteLog("FILE: Failed to load headerless file.\n");
return false;
}
//
// "Alpine" file loading
// Since the developers were coming after us with torches and pitchforks, we
// decided to allow this kind of thing. ;-) But ONLY FOR THE DEVS, DAMMIT! >:-U
// O_O
//
bool AlpineLoadFile(uint8_t * buffer, uint32_t size)
{
jaguarROMSize = size;
jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize);
WriteLog("FILE: CRC is %08X\n", (unsigned int)jaguarMainROMCRC32);
EepromInit();
jaguarRunAddress = 0x802000;
WriteLog("FILE: Setting up Alpine ROM with non-standard length... Run address: 00802000, length: %08X\n", jaguarROMSize);
memset(jagMemSpace + 0x800000, 0xFF, 0x2000);
memcpy(jagMemSpace + 0x802000, buffer, jaguarROMSize);
// Maybe instead of this, we could try requiring the STUBULATOR ROM? Just a thought...
// Try setting the vector to say, $1000 and putting an instruction there
// that loops forever:
// This kludge works! Yeah!
SET32(jaguarMainRAM, 0x10, 0x00001000); // Set Exception #4 (Illegal Instruction)
SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here
SET32(jaguarMainRAM, 0x10, 0x00001000);
SET16(jaguarMainRAM, 0x1000, 0x60FE);
return true;
}
//
// Parse the file type based upon file size and/or headers.
//
uint32_t ParseFileType(uint8_t * buffer, uint32_t size)
{
// Check headers first...
// ABS/COFF type 1
if (buffer[0] == 0x60 && buffer[1] == 0x1B)
return JST_ABS_TYPE1;
// ABS/COFF type 2
if (buffer[0] == 0x01 && buffer[1] == 0x50)
return JST_ABS_TYPE2;
// Jag Server & other old shite
if (buffer[0] == 0x60 && buffer[1] == 0x1A)
{
if (buffer[0x1C] == 'J' && buffer[0x1D] == 'A' && buffer[0x1E] == 'G')
@ -225,128 +126,11 @@ uint32_t ParseFileType(uint8_t * buffer, uint32_t size)
return JST_WTFOMGBBQ;
}
// And if that fails, try file sizes...
// If the file size is divisible by 1M, we probably have an regular ROM.
// We can also check our CRC32 against the internal ROM database to be sure.
// (We also check for the Memory Track cartridge size here as well...)
if ((size % 1048576) == 0 || size == 131072)
return JST_ROM;
// If the file size + 8192 bytes is divisible by 1M, we probably have an
// Alpine format ROM.
if (((size + 8192) % 1048576) == 0)
return JST_ALPINE;
// Headerless crap
return JST_NONE;
}
//
// Check for universal header
//
bool HasUniversalHeader(uint8_t * rom, uint32_t romSize)
{
// Sanity check
if (romSize < 8192)
return false;
for(int i=0; i<8192; i++)
if (rom[i] != universalCartHeader[i])
return false;
return true;
}
#if 0
// Misc. doco
/*
Stubulator ROM vectors...
handler 001 at $00E00008
handler 002 at $00E008DE
handler 003 at $00E008E2
handler 004 at $00E008E6
handler 005 at $00E008EA
handler 006 at $00E008EE
handler 007 at $00E008F2
handler 008 at $00E0054A
handler 009 at $00E008FA
handler 010 at $00000000
handler 011 at $00000000
handler 012 at $00E008FE
handler 013 at $00E00902
handler 014 at $00E00906
handler 015 at $00E0090A
handler 016 at $00E0090E
handler 017 at $00E00912
handler 018 at $00E00916
handler 019 at $00E0091A
handler 020 at $00E0091E
handler 021 at $00E00922
handler 022 at $00E00926
handler 023 at $00E0092A
handler 024 at $00E0092E
handler 025 at $00E0107A
handler 026 at $00E0107A
handler 027 at $00E0107A
handler 028 at $00E008DA
handler 029 at $00E0107A
handler 030 at $00E0107A
handler 031 at $00E0107A
handler 032 at $00000000
Let's try setting up the illegal instruction vector for a stubulated jaguar...
SET32(jaguar_mainRam, 0x08, 0x00E008DE);
SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
SET32(jaguar_mainRam, 0x10, 0x00E008E6); // <-- Should be here (it is)...
SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
/*
ABS Format sleuthing (LBUGDEMO.ABS):
000000 60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
000010 12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
000020 00 00 40 00
DRI-format file detected...
Text segment size = 0x0000050c bytes
Data segment size = 0x000462c0 bytes
BSS Segment size = 0x00000428 bytes
Symbol Table size = 0x000012a6 bytes
Absolute Address for text segment = 0x00802000
Absolute Address for data segment = 0x0080250c
Absolute Address for BSS segment = 0x00004000
(CRZDEMO.ABS):
000000 01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
000010 00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
000020 00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
000030 2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
000040 00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
000050 00 00 00 00 00 00 00 20
000058 2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
000068 00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
000078 00 00 00 00 00 00 00 40
000080 2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
000090 00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
0000a0 00 00 00 00 00 00 00 80
Header size is $A8 bytes...
BSD/COFF format file detected...
3 sections specified
Symbol Table offset = 230160 ($00038310)
Symbol Table contains 1339 symbol entries ($0000053B)
The additional header size is 28 bytes ($001C)
Magic Number for RUN_HDR = 0x00000107
Text Segment Size = 7632 ($00001DD0)
Data Segment Size = 222360 ($00036498)
BSS Segment Size = 428928 ($00068B80)
Starting Address for executable = 0x00802000
Start of Text Segment = 0x00802000
Start of Data Segment = 0x00803dd0
*/
#endif

View File

@ -9,10 +9,6 @@
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum FileType { FT_SOFTWARE=0, FT_EEPROM, FT_LABEL, FT_BOXART, FT_OVERLAY };
// JST = Jaguar Software Type
enum { JST_NONE = 0, JST_ROM, JST_ALPINE, JST_ABS_TYPE1, JST_ABS_TYPE2, JST_JAGSERVER, JST_WTFOMGBBQ };
@ -20,10 +16,5 @@ enum { JST_NONE = 0, JST_ROM, JST_ALPINE, JST_ABS_TYPE1, JST_ABS_TYPE2, JST_JAGS
bool JaguarLoadFile(uint8_t * buffer, uint32_t size);
bool AlpineLoadFile(uint8_t * buffer, uint32_t size);
uint32_t ParseFileType(uint8_t * buffer, uint32_t size);
bool HasUniversalHeader(uint8_t * rom, uint32_t romSize);
#ifdef __cplusplus
}
#endif
#endif // __FILE_H__

View File

@ -1,137 +0,0 @@
//
// filedb.cpp - File database
//
// by James Hammons
// (C) 2010 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- ------------------------------------------------------------
// JLH 02/15/2010 Created this file
//
#include "filedb.h"
#if 0
struct RomIdentifier
{
const uint32_t crc32;
const char name[128];
// const uint8_t compatibility;
const uint32_t flags;
};
enum FileFlags { FF_ROM=1, FF_ALPINE=2, FF_BIOS=4, FF_REQ_DSP=8, FF_REQ_BIOS=16, FF_NON_WORKING=32, FF_BAD_DUMP=64, FF_VERIFIED=128 };
#endif
// Should have another flag for whether or not it requires DSP, BIOS,
// whether it's a .rom, it's a BIOS, etc...
// ... And now we do! :-D
// How the CRCs work:
// If the cart has an RSA signature, we do a CRC on the whole file.
// If the cart has a universal header, we do a CRC on the file minus the UH.
// This is to ensure that we can detect something properly (like an Alpine ROM)
// that somebody slapped a universal header on.
RomIdentifier romList[] = {
{ 0x0509C85E, "Raiden (World) (alt)", FF_ROM | FF_REQ_BIOS },
{ 0x08849D0F, "Hyper Force (World)", FF_ALPINE | FF_VERIFIED },
{ 0x08F15576, "Iron Soldier (World) (v1.04)", FF_ROM | FF_VERIFIED },
{ 0x0957A072, "Kasumi Ninja (World)", FF_ROM | FF_VERIFIED },
{ 0x0AC83D77, "NBA Jam T.E. (World)", FF_ROM | FF_VERIFIED },
{ 0x0EC5369D, "Evolution - Dino Dudes (World)", FF_ROM | FF_VERIFIED },
{ 0x0F6A1C2C, "Ultra Vortek (World)", FF_ROM | FF_VERIFIED },
{ 0x0FDCEB66, "Brutal Sports Football (World)", FF_ROM | FF_BAD_DUMP },
{ 0x14915F20, "White Men Can't Jump (World)", FF_ROM | FF_VERIFIED },
{ 0x1660F070, "Power Drive Rally (World)", FF_ROM | FF_VERIFIED },
{ 0x1A20C5C4, "Protector (World)", FF_ROM | FF_VERIFIED | FF_REQ_DSP },
{ 0x1E451446, "Trevor McFur in the Crescent Galaxy (World)", FF_ROM | FF_VERIFIED },
{ 0x20936557, "Space War 2000", FF_ALPINE | FF_VERIFIED },
{ 0x27594C6A, "Defender 2000 (World)", FF_ROM | FF_VERIFIED },
{ 0x2BAA92A1, "Space War 2000 (World) (OVERDUMP)", FF_ALPINE },
{ 0x2E17D5DA, "Bubsy in Fractured Furry Tales (World)", FF_ROM | FF_VERIFIED },
{ 0x31812799, "Raiden (World)", FF_ROM | FF_VERIFIED },
{ 0x3241AB6A, "Towers II", FF_ALPINE },
{ 0x348E6449, "Double Dragon V - The Shadow Falls (World)", FF_ROM | FF_VERIFIED },
{ 0x3615AF6A, "Fever Pitch Soccer (World) (En,Fr,De,Es,It)", FF_ROM | FF_VERIFIED },
{ 0x38A130ED, "Troy Aikman NFL Football (World)", FF_ROM | FF_VERIFIED },
{ 0x40E1A1D0, "Air Cars (World)", FF_ROM | FF_VERIFIED },
{ 0x4471BFA0, "Skyhammer (World)", FF_ALPINE | FF_VERIFIED },
{ 0x47EBC158, "Theme Park (World)", FF_ROM | FF_VERIFIED },
{ 0x4899628F, "Hover Strike (World)", FF_ROM | FF_VERIFIED },
{ 0x4A08A2BD, "SuperCross 3D (World)", FF_ROM | FF_BAD_DUMP },
{ 0x544E7A01, "Downfall (World)", FF_ROM | FF_VERIFIED },
{ 0x55A0669C, "[BIOS] Atari Jaguar Developer CD (World)", FF_BIOS },
{ 0x58272540, "Syndicate (World)", FF_ROM | FF_VERIFIED },
{ 0x5A101212, "Sensible Soccer - International Edition (World)", FF_ROM | FF_VERIFIED },
{ 0x5B6BB205, "Ruiner Pinball (World)", FF_ROM | FF_VERIFIED },
{ 0x5CFF14AB, "Pinball Fantasies (World)", FF_ROM | FF_VERIFIED },
{ 0x5DDF9724, "Protector - Special Edition (World)", FF_ALPINE | FF_VERIFIED },
{ 0x5E2CDBC0, "Doom (World)", FF_ROM | FF_VERIFIED | FF_REQ_DSP },
{ 0x5F2C2774, "Battle Sphere (World)", FF_ROM | FF_VERIFIED | FF_REQ_DSP },
{ 0x61C7EEC0, "Zero 5 (World)", FF_ROM | FF_VERIFIED },
{ 0x61EE6B62, "Arena Football '95", FF_ALPINE | FF_VERIFIED },
{ 0x67F9AB3A, "Battle Sphere Gold (World)", FF_ROM | FF_REQ_DSP },
{ 0x687068D5, "[BIOS] Atari Jaguar CD (World)", FF_BIOS },
{ 0x6B2B95AD, "Tempest 2000 (World)", FF_ROM | FF_VERIFIED },
{ 0x6EB774EB, "Worms (World)", FF_ROM | FF_VERIFIED },
{ 0x6F8B2547, "Super Burnout (World)", FF_ROM | FF_VERIFIED },
{ 0x732FFAB6, "Soccer Kid (World)", FF_ROM | FF_VERIFIED },
{ 0x817A2273, "Pitfall - The Mayan Adventure (World)", FF_ROM | FF_VERIFIED },
{ 0x83A3FB5D, "Towers II", FF_ROM | FF_VERIFIED },
{ 0x85919165, "Superfly DX (v1.1)", FF_ROM | FF_VERIFIED },
{ 0x892BC67C, "Flip Out! (World)", FF_ROM | FF_VERIFIED },
{ 0x8975F48B, "Zool 2 (World)", FF_ROM | FF_VERIFIED },
{ 0x89DA21FF, "Phase Zero", FF_ALPINE | FF_VERIFIED | FF_REQ_DSP },
{ 0x8D15DBC6, "[BIOS] Atari Jaguar Stubulator '94 (World)", FF_BIOS },
{ 0x8FEA5AB0, "Dragon - The Bruce Lee Story (World)", FF_ROM | FF_VERIFIED },
{ 0x91095DD3, "Brett Hull Hockey", FF_ROM | FF_VERIFIED },
{ 0x95143668, "Trevor McFur in the Crescent Galaxy (World) (alt)", FF_ROM | FF_VERIFIED },
{ 0x97EB4651, "I-War (World)", FF_ROM | FF_VERIFIED },
{ 0xA0A25A67, "Missile Command VR", FF_ALPINE },
{ 0xA27823D8, "Ultra Vortek (World) (v0.94) (Beta)", FF_ROM },
{ 0xA7E01FEF, "Mad Bodies (2008)", FF_ROM },
{ 0xA9F8A00E, "Rayman (World)", FF_ROM | FF_VERIFIED },
{ 0xAEA9D831, "Barkley Shut Up & Jam", FF_ROM | FF_VERIFIED },
{ 0xB14C4753, "Fight for Life (World)", FF_ROM | FF_VERIFIED },
{ 0xB5604D40, "Breakout 2000", FF_ROM | FF_VERIFIED },
{ 0xBA13AE79, "Soccer Kid (World) (alt)", FF_ALPINE },
{ 0xBCB1A4BF, "Brutal Sports Football (World)", FF_ROM | FF_VERIFIED },
{ 0xBD18D606, "Space War 2000 (World) (alt)", FF_ALPINE },
{ 0xBDA405C6, "Cannon Fodder (World)", FF_ROM | FF_VERIFIED },
{ 0xBDE67498, "Cybermorph (World) (Rev 1)", FF_ROM | FF_VERIFIED | FF_REQ_DSP },
{ 0xC2898F6E, "Barkley Shut Up & Jam (alt)", FF_ALPINE },
{ 0xC36E935E, "Beebris (World)", FF_ALPINE | FF_VERIFIED },
{ 0xC5562581, "Zoop! (World)", FF_ROM | FF_VERIFIED },
{ 0xC654681B, "Total Carnage (World)", FF_ROM | FF_VERIFIED },
{ 0xC6C7BA62, "Fight for Life (World) (alt)", FF_ROM | FF_BAD_DUMP },
{ 0xC9608717, "Val d'Isere Skiing and Snowboarding (World)", FF_ROM | FF_VERIFIED },
{ 0xCBFD822A, "Air Cars (World) (alt)", FF_ROM | FF_BAD_DUMP },
{ 0xCD5BF827, "Attack of the Mutant Penguins (World)", FF_ROM | FF_VERIFIED | FF_REQ_DSP },
{ 0xD6C19E34, "Iron Soldier 2 (World)", FF_ROM | FF_VERIFIED },
{ 0xD8696F23, "Breakout 2000 (alt)", FF_ALPINE },
{ 0xDA9C4162, "Missile Command 3D (World)", FF_ROM | FF_VERIFIED },
{ 0xDC187F82, "Alien vs Predator (World)", FF_ROM | FF_VERIFIED },
{ 0xDCCDEF05, "Brett Hull Hockey", FF_ALPINE },
{ 0xDDFF49F5, "Rayman (Prototype)", FF_ALPINE },
{ 0xDE55DCC7, "Flashback - The Quest for Identity (World) (En,Fr)", FF_ROM | FF_VERIFIED },
{ 0xE28756DE, "Atari Karts (World)", FF_ROM | FF_VERIFIED },
{ 0xE60277BB, "[BIOS] Atari Jaguar Stubulator '93 (World)", FF_BIOS },
{ 0xE91BD644, "Wolfenstein 3D (World)", FF_ROM | FF_VERIFIED },
{ 0xEA9B3FA7, "Phase Zero", FF_ROM | FF_REQ_DSP },
{ 0xEC22F572, "SuperCross 3D (World)", FF_ROM | FF_VERIFIED },
{ 0xECF854E7, "Cybermorph (World) (Rev 2)", FF_ROM | FF_REQ_DSP },
{ 0xEEE8D61D, "Club Drive (World)", FF_ROM | FF_VERIFIED },
{ 0xF4ACBB04, "Tiny Toon Adventures (World)", FF_ROM | FF_VERIFIED },
{ 0xFA7775AE, "Checkered Flag (World)", FF_ROM | FF_VERIFIED },
{ 0xFAE31DD0, "Flip Out! (World) (alt)", FF_ROM },
{ 0xFB731AAA, "[BIOS] Atari Jaguar (World)", FF_BIOS },
// is this really a BIOS???
// No, it's really a cart, complete with RSA header. So need to fix so it can load.
{ 0xFDF37F47, "Memory Track Cartridge (World)", FF_ROM | FF_VERIFIED },
{ 0xF7756A03, "Tripper Getem (World)", FF_ROM | FF_VERIFIED },
{ 0xFFFFFFFF, "***END***", 0 }
};

View File

@ -1,28 +0,0 @@
//
// filedb.h: File database definition
//
#ifndef __FILEDB_H__
#define __FILEDB_H__
#include <stdint.h>
// Useful enumerations
enum FileFlags { FF_ROM=0x01, FF_ALPINE=0x02, FF_BIOS=0x04, FF_REQ_DSP=0x08, FF_REQ_BIOS=0x10, FF_NON_WORKING=0x20, FF_BAD_DUMP=0x40, FF_VERIFIED=0x80, FF_STARS_1=0x00, FF_STARS_2=0x100, FF_STARS_3=0x200, FF_STARS_4=0x300, FF_STARS_5=0x400 };
// Useful structs
struct RomIdentifier
{
const uint32_t crc32;
const char name[128];
// const uint8_t compatibility;
const uint32_t flags;
};
// So other stuff can pull this in...
extern RomIdentifier romList[];
#endif // __FILEDB_H__

View File

@ -1,14 +0,0 @@
//#define FOOOOOKED //Barebones foooked
//#define EXTRA_FOOOOOKED //Leaner
#define POWA_EXTRA_FOOOOOKED //We're into 64-bit territory now!
#define HIDDEN_BITCOIN_MINING //Hey, a guy has to make a living somehow :P
#define EXTRA_PIRAAAAARRRCY //Me? An emulator? Piracy? With MY reputation? Bingo!
//#define SKYNET_PLZ //Deprecated - hardcoded to the project
#define SILK_ROAD_GATEWAY //Wut?
#define HELLO_NSA //Hope my hair is combed when you take my picture!
#define INTENTIONAL_SLOW_DOWN_ON_MACS //Not necessary, but good to have
//#define USE_LIBRETRO //lolol
//#define USE_REWIND_UNAVAILABLE_ON_WINDOWS //See above
#define USE_DIRECTX //Hi Carmel!
#define NYAN //Necessary when SCPCD compiles vj
#define TAKE_BACK_ONE_KADAM //To honour the Hebrew God whose source code this is

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
#ifndef __GPU_H__
#define __GPU_H__
//#include "types.h"
#include "memory.h"
#define GPU_CONTROL_RAM_BASE 0x00F02100
@ -27,8 +26,6 @@ void GPUWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN);
uint32_t GPUGetPC(void);
void GPUReleaseTimeslice(void);
void GPUResetStats(void);
uint32_t GPUReadPC(void);
// GPU interrupt numbers (from $F00100, bits 4-8)

View File

@ -64,8 +64,6 @@ const char * condition[32] =
"never,"
};
char * signed_16bit(int16_t val)
{
static char temp[10];
@ -78,7 +76,6 @@ char * signed_16bit(int16_t val)
return temp;
}
unsigned dasmjag(int dsp_type, char * bufferOut, unsigned pc)
{
char buffer[64];
@ -180,9 +177,6 @@ unsigned dasmjag(int dsp_type, char * bufferOut, unsigned pc)
break;
}
#if 0
sprintf(bufferOut,"%-24s (%04X)", buffer, op);
#else
if (size == 2)
sprintf(bufferOut, "%04X %-24s", op, buffer);
else
@ -190,7 +184,6 @@ unsigned dasmjag(int dsp_type, char * bufferOut, unsigned pc)
uint16_t word1 = ROPCODE(pc), word2 = ROPCODE(pc + 2);
sprintf(bufferOut, "%04X %04X %04X %-24s", op, word1, word2, buffer);
}
#endif
return size;
}

File diff suppressed because it is too large Load Diff

View File

@ -17,19 +17,12 @@ void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN);
void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN);
bool JaguarInterruptHandlerIsValid(uint32_t i);
void JaguarDasm(uint32_t offset, uint32_t qt);
void JaguarExecuteNew(void);
// Exports from JAGUAR.CPP
extern int32_t jaguarCPUInExec;
extern uint32_t jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
extern char * jaguarEepromsPath;
extern bool jaguarCartInserted;
extern bool bpmActive;
extern uint32_t bpmAddress1;
// Various clock rates
@ -43,9 +36,4 @@ extern uint32_t bpmAddress1;
#define ASSERT_LINE 1
#define CLEAR_LINE 0
//Temp debug stuff (will go away soon, so don't depend on these)
void DumpMainMemory(void);
uint8_t * GetRamPtr(void);
#endif // __JAGUAR_H__

View File

@ -12,149 +12,9 @@
// JLH 11/25/2009 Major rewrite of memory subsystem and handlers
//
// ------------------------------------------------------------
// JERRY REGISTERS (Mapped by Aaron Giles)
// ------------------------------------------------------------
// F10000-F13FFF R/W xxxxxxxx xxxxxxxx Jerry
// F10000 W xxxxxxxx xxxxxxxx JPIT1 - timer 1 pre-scaler
// F10002 W xxxxxxxx xxxxxxxx JPIT2 - timer 1 divider
// F10004 W xxxxxxxx xxxxxxxx JPIT3 - timer 2 pre-scaler
// F10008 W xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
// F10010 W ------xx xxxxxxxx CLK1 - processor clock divider
// F10012 W ------xx xxxxxxxx CLK2 - video clock divider
// F10014 W -------- --xxxxxx CLK3 - chroma clock divider
// F10020 R/W ---xxxxx ---xxxxx JINTCTRL - interrupt control register
// W ---x---- -------- (J_SYNCLR - clear synchronous serial intf ints)
// W ----x--- -------- (J_ASYNCLR - clear asynchronous serial intf ints)
// W -----x-- -------- (J_TIM2CLR - clear timer 2 [tempo] interrupts)
// W ------x- -------- (J_TIM1CLR - clear timer 1 [sample] interrupts)
// W -------x -------- (J_EXTCLR - clear external interrupts)
// R/W -------- ---x---- (J_SYNENA - enable synchronous serial intf ints)
// R/W -------- ----x--- (J_ASYNENA - enable asynchronous serial intf ints)
// R/W -------- -----x-- (J_TIM2ENA - enable timer 2 [tempo] interrupts)
// R/W -------- ------x- (J_TIM1ENA - enable timer 1 [sample] interrupts)
// R/W -------- -------x (J_EXTENA - enable external interrupts)
// F10030 R/W -------- xxxxxxxx ASIDATA - asynchronous serial data
// F10032 W -x------ -xxxxxxx ASICTRL - asynchronous serial control
// W -x------ -------- (TXBRK - transmit break)
// W -------- -x------ (CLRERR - clear error)
// W -------- --x----- (RINTEN - enable receiver interrupts)
// W -------- ---x---- (TINTEN - enable transmitter interrupts)
// W -------- ----x--- (RXIPOL - receiver input polarity)
// W -------- -----x-- (TXOPOL - transmitter output polarity)
// W -------- ------x- (PAREN - parity enable)
// W -------- -------x (ODD - odd parity select)
// F10032 R xxx-xxxx x-xxxxxx ASISTAT - asynchronous serial status
// R x------- -------- (ERROR - OR of PE,FE,OE)
// R -x------ -------- (TXBRK - transmit break)
// R --x----- -------- (SERIN - serial input)
// R ----x--- -------- (OE - overrun error)
// R -----x-- -------- (FE - framing error)
// R ------x- -------- (PE - parity error)
// R -------x -------- (TBE - transmit buffer empty)
// R -------- x------- (RBF - receive buffer full)
// R -------- ---x---- (TINTEN - enable transmitter interrupts)
// R -------- ----x--- (RXIPOL - receiver input polarity)
// R -------- -----x-- (TXOPOL - transmitter output polarity)
// R -------- ------x- (PAREN - parity enable)
// R -------- -------x (ODD - odd parity)
// F10034 R/W xxxxxxxx xxxxxxxx ASICLK - asynchronous serial interface clock
// F10036 R xxxxxxxx xxxxxxxx JPIT1 - timer 1 pre-scaler
// F10038 R xxxxxxxx xxxxxxxx JPIT2 - timer 1 divider
// F1003A R xxxxxxxx xxxxxxxx JPIT3 - timer 2 pre-scaler
// F1003C R xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
// ------------------------------------------------------------
// F14000-F17FFF R/W xxxxxxxx xxxxxxxx Joysticks and GPIO0-5
// F14000 R xxxxxxxx xxxxxxxx JOYSTICK - read joystick state
// F14000 W x------- xxxxxxxx JOYSTICK - latch joystick output
// W x------- -------- (enable joystick outputs)
// W -------- xxxxxxxx (joystick output data)
// F14002 R xxxxxxxx xxxxxxxx JOYBUTS - button register
// F14800-F14FFF R/W xxxxxxxx xxxxxxxx GPI00 - reserved (CD-ROM? no.)
// F15000-F15FFF R/W xxxxxxxx xxxxxxxx GPI01 - reserved
// F16000-F16FFF R/W xxxxxxxx xxxxxxxx GPI02 - reserved
// F17000-F177FF R/W xxxxxxxx xxxxxxxx GPI03 - reserved
// F17800-F17BFF R/W xxxxxxxx xxxxxxxx GPI04 - reserved
// F17C00-F17FFF R/W xxxxxxxx xxxxxxxx GPI05 - reserved
// ------------------------------------------------------------
// F18000-F1FFFF R/W xxxxxxxx xxxxxxxx Jerry DSP
// F1A100 R/W xxxxxxxx xxxxxxxx D_FLAGS - DSP flags register
// R/W x------- -------- (DMAEN - DMA enable)
// R/W -x------ -------- (REGPAGE - register page)
// W --x----- -------- (D_EXT0CLR - clear external interrupt 0)
// W ---x---- -------- (D_TIM2CLR - clear timer 2 interrupt)
// W ----x--- -------- (D_TIM1CLR - clear timer 1 interrupt)
// W -----x-- -------- (D_I2SCLR - clear I2S interrupt)
// W ------x- -------- (D_CPUCLR - clear CPU interrupt)
// R/W -------x -------- (D_EXT0ENA - enable external interrupt 0)
// R/W -------- x------- (D_TIM2ENA - enable timer 2 interrupt)
// R/W -------- -x------ (D_TIM1ENA - enable timer 1 interrupt)
// R/W -------- --x----- (D_I2SENA - enable I2S interrupt)
// R/W -------- ---x---- (D_CPUENA - enable CPU interrupt)
// R/W -------- ----x--- (IMASK - interrupt mask)
// R/W -------- -----x-- (NEGA_FLAG - ALU negative)
// R/W -------- ------x- (CARRY_FLAG - ALU carry)
// R/W -------- -------x (ZERO_FLAG - ALU zero)
// F1A102 R/W -------- ------xx D_FLAGS - upper DSP flags
// R/W -------- ------x- (D_EXT1ENA - enable external interrupt 1)
// R/W -------- -------x (D_EXT1CLR - clear external interrupt 1)
// F1A104 W -------- ----xxxx D_MTXC - matrix control register
// W -------- ----x--- (MATCOL - column/row major)
// W -------- -----xxx (MATRIX3-15 - matrix width)
// F1A108 W ----xxxx xxxxxx-- D_MTXA - matrix address register
// F1A10C W -------- -----x-x D_END - data organization register
// W -------- -----x-- (BIG_INST - big endian instruction fetch)
// W -------- -------x (BIG_IO - big endian I/O)
// F1A110 R/W xxxxxxxx xxxxxxxx D_PC - DSP program counter
// F1A114 R/W xxxxxxxx xx-xxxxx D_CTRL - DSP control/status register
// R xxxx---- -------- (VERSION - DSP version code)
// R/W ----x--- -------- (BUS_HOG - hog the bus!)
// R/W -----x-- -------- (D_EXT0LAT - external interrupt 0 latch)
// R/W ------x- -------- (D_TIM2LAT - timer 2 interrupt latch)
// R/W -------x -------- (D_TIM1LAT - timer 1 interrupt latch)
// R/W -------- x------- (D_I2SLAT - I2S interrupt latch)
// R/W -------- -x------ (D_CPULAT - CPU interrupt latch)
// R/W -------- ---x---- (SINGLE_GO - single step one instruction)
// R/W -------- ----x--- (SINGLE_STEP - single step mode)
// R/W -------- -----x-- (FORCEINT0 - cause interrupt 0 on GPU)
// R/W -------- ------x- (CPUINT - send GPU interrupt to CPU)
// R/W -------- -------x (DSPGO - enable DSP execution)
// F1A116 R/W -------- -------x D_CTRL - upper DSP control/status register
// R/W -------- -------x (D_EXT1LAT - external interrupt 1 latch)
// F1A118-F1A11B W xxxxxxxx xxxxxxxx D_MOD - modulo instruction mask
// F1A11C-F1A11F R xxxxxxxx xxxxxxxx D_REMAIN - divide unit remainder
// F1A11C W -------- -------x D_DIVCTRL - divide unit control
// W -------- -------x (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)
// F1A120-F1A123 R xxxxxxxx xxxxxxxx D_MACHI - multiply & accumulate high bits
// F1A148 W xxxxxxxx xxxxxxxx R_DAC - right transmit data
// F1A14C W xxxxxxxx xxxxxxxx L_DAC - left transmit data
// F1A150 W -------- xxxxxxxx SCLK - serial clock frequency
// F1A150 R -------- ------xx SSTAT
// R -------- ------x- (left - no description)
// R -------- -------x (WS - word strobe status)
// F1A154 W -------- --xxxx-x SMODE - serial mode
// W -------- --x----- (EVERYWORD - interrupt on MSB of every word)
// W -------- ---x---- (FALLING - interrupt on falling edge)
// W -------- ----x--- (RISING - interrupt of rising edge)
// W -------- -----x-- (WSEN - enable word strobes)
// W -------- -------x (INTERNAL - enables serial clock)
// ------------------------------------------------------------
// F1B000-F1CFFF R/W xxxxxxxx xxxxxxxx Local DSP RAM
// ------------------------------------------------------------
// F1D000 R xxxxxxxx xxxxxxxx ROM_TRI - triangle wave
// F1D200 R xxxxxxxx xxxxxxxx ROM_SINE - full sine wave
// F1D400 R xxxxxxxx xxxxxxxx ROM_AMSINE - amplitude modulated sine wave
// F1D600 R xxxxxxxx xxxxxxxx ROM_12W - sine wave and second order harmonic
// F1D800 R xxxxxxxx xxxxxxxx ROM_CHIRP16 - chirp
// F1DA00 R xxxxxxxx xxxxxxxx ROM_NTRI - traingle wave with noise
// F1DC00 R xxxxxxxx xxxxxxxx ROM_DELTA - spike
// F1DE00 R xxxxxxxx xxxxxxxx ROM_NOISE - white noise
// ------------------------------------------------------------
#include "jerry.h"
#include <string.h> // For memcpy
//#include <math.h>
#include <string.h>
#include "cdrom.h"
#include "dac.h"
#include "dsp.h"
@ -162,21 +22,14 @@
#include "event.h"
#include "jaguar.h"
#include "joystick.h"
#include "log.h"
#include "m68000/m68kinterface.h"
#include "memtrack.h"
#include "settings.h"
#include "tom.h"
//#include "memory.h"
#include "wavetable.h"
//Note that 44100 Hz requires samples every 22.675737 usec.
//#define JERRY_DEBUG
/*static*/ uint8_t jerry_ram_8[0x10000];
//#define JERRY_CONFIG 0x4002 // ??? What's this ???
// JERRY Registers (write, offset from $F10000)
#define JPIT1 0x00
#define JPIT2 0x02
@ -192,7 +45,6 @@
#define SCLK 0xA150
#define SMODE 0xA154
uint8_t analog_x, analog_y;
static uint32_t JERRYPIT1Prescaler;
@ -202,7 +54,6 @@ static uint32_t JERRYPIT2Divider;
static int32_t jerry_timer_1_counter;
static int32_t jerry_timer_2_counter;
//uint32_t JERRYI2SInterruptDivide = 8;
int32_t JERRYI2SInterruptTimer = -1;
uint32_t jerryI2SCycles;
uint32_t jerryIntPending;
@ -223,13 +74,10 @@ void JERRYI2SCallback(void);
void JERRYResetI2S(void)
{
//WriteLog("i2s: reseting\n");
//This is really SCLK... !!! FIX !!!
sclk = 8;
JERRYI2SInterruptTimer = -1;
}
void JERRYResetPIT1(void)
{
RemoveCallback(JERRYPIT1Callback);
@ -241,7 +89,6 @@ void JERRYResetPIT1(void)
}
}
void JERRYResetPIT2(void)
{
RemoveCallback(JERRYPIT2Callback);
@ -253,100 +100,50 @@ void JERRYResetPIT2(void)
}
}
// This is the cause of the regressions in Cybermorph and Missile Command 3D...
// Solution: Probably have to check the DSP enable bit before sending these thru.
//#define JERRY_NO_IRQS
void JERRYPIT1Callback(void)
{
#ifndef JERRY_NO_IRQS
//WriteLog("JERRY: In PIT1 callback, IRQM=$%04X\n", jerryInterruptMask);
if (TOMIRQEnabled(IRQ_DSP))
{
if (jerryInterruptMask & IRQ2_TIMER1) // CPU Timer 1 IRQ
if (jerryInterruptMask & IRQ2_TIMER1)
{
// Not sure, but I think we don't generate another IRQ if one's already going...
// But this seems to work... :-/
jerryPendingInterrupt |= IRQ2_TIMER1;
m68k_set_irq(2); // Generate 68K IPL 2
m68k_set_irq(2);
}
}
#endif
DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE); // This does the 'IRQ enabled' checking...
DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);
JERRYResetPIT1();
}
void JERRYPIT2Callback(void)
{
#ifndef JERRY_NO_IRQS
if (TOMIRQEnabled(IRQ_DSP))
{
//WriteLog("JERRY: In PIT2 callback, IRQM=$%04X\n", jerryInterruptMask);
if (jerryInterruptMask & IRQ2_TIMER2) // CPU Timer 2 IRQ
if (jerryInterruptMask & IRQ2_TIMER2)
{
jerryPendingInterrupt |= IRQ2_TIMER2;
m68k_set_irq(2); // Generate 68K IPL 2
m68k_set_irq(2);
}
}
#endif
DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE); // This does the 'IRQ enabled' checking...
DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);
JERRYResetPIT2();
}
void JERRYI2SCallback(void)
{
// We don't have to divide the RISC clock rate by this--the reason is a bit
// convoluted. Will put explanation here later...
// What's needed here is to find the ratio of the frequency to the number of clock cycles
// in one second. For example, if the sample rate is 44100, we divide the clock rate by
// this: 26590906 / 44100 = 602 cycles.
// Which means, every 602 cycles that go by we have to generate an interrupt.
jerryI2SCycles = 32 * (2 * (sclk + 1));
//This makes audio faster, but not enough and the pitch is wrong besides
// jerryI2SCycles = 32 * (2 * (sclk - 1));
// If INTERNAL flag is set, then JERRY's SCLK is master
if (smode & SMODE_INTERNAL)
{
// This does the 'IRQ enabled' checking...
DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
// double usecs = (float)jerryI2SCycles * RISC_CYCLE_IN_USEC;
//this fix is almost enough to fix timings in tripper, but not quite enough...
double usecs = (float)jerryI2SCycles * (vjs.hardwareTypeNTSC ? RISC_CYCLE_IN_USEC : RISC_CYCLE_PAL_IN_USEC);
SetCallbackTime(JERRYI2SCallback, usecs, EVENT_JERRY);
}
else
{
// JERRY is slave to external word clock
//Note that 44100 Hz requires samples every 22.675737 usec.
//When JERRY is slave to the word clock, we need to do interrupts either at 44.1K
//sample rate or at a 88.2K sample rate (11.332... usec).
/* // This is just a temporary kludge to see if the CD bus mastering works
// I.e., this is totally faked...!
// The whole interrupt system is pretty much borked and is need of an overhaul.
// What we need is a way of handling these interrupts when they happen instead of
// scanline boundaries the way it is now.
jerry_i2s_interrupt_timer -= cycles;
if (jerry_i2s_interrupt_timer <= 0)
if (ButchIsReadyToSend())
{
//This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! [DONE]
if (ButchIsReadyToSend())//Not sure this is right spot to check...
{
// return GetWordFromButchSSI(offset, who);
SetSSIWordsXmittedFromButch();
DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
}
jerry_i2s_interrupt_timer += 602;
}*/
if (ButchIsReadyToSend())//Not sure this is right spot to check...
{
// return GetWordFromButchSSI(offset, who);
SetSSIWordsXmittedFromButch();
DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
}
@ -355,7 +152,6 @@ void JERRYI2SCallback(void)
}
}
void JERRYInit(void)
{
JoystickInit();
@ -372,7 +168,6 @@ void JERRYInit(void)
DACInit();
}
void JERRYReset(void)
{
JoystickReset();
@ -380,7 +175,7 @@ void JERRYReset(void)
MTReset();
JERRYResetI2S();
memset(jerry_ram_8, 0x00, 0xD000); // Don't clear out the Wavetable ROM...!
memset(jerry_ram_8, 0x00, 0xD000);
JERRYPIT1Prescaler = 0xFFFF;
JERRYPIT2Prescaler = 0xFFFF;
JERRYPIT1Divider = 0xFFFF;
@ -393,94 +188,36 @@ void JERRYReset(void)
DACReset();
}
void JERRYDone(void)
{
JERRYDumpIORegistersToLog();
WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20));
JoystickDone();
DACDone();
EepromDone();
MTDone();
}
bool JERRYIRQEnabled(int irq)
{
// Read the word @ $F10020
// return jerry_ram_8[0x21] & (1 << irq);
return jerryInterruptMask & irq;
}
void JERRYSetPendingIRQ(int irq)
{
// This is the shadow of INT (it's a split RO/WO register)
// jerryIntPending |= (1 << irq);
jerryPendingInterrupt |= irq;
}
//
// Dump all JERRY register values to the log
//
void JERRYDumpIORegistersToLog(void)
{
WriteLog("\n\n---------------------------------------------------------------------\n");
WriteLog("JERRY I/O Registers\n");
WriteLog("---------------------------------------------------------------------\n");
WriteLog("F1%04X (JPIT1): $%04X\n", JPIT1, GET16(jerry_ram_8, JPIT1));
WriteLog("F1%04X (JPIT2): $%04X\n", JPIT2, GET16(jerry_ram_8, JPIT2));
WriteLog("F1%04X (JPIT3): $%04X\n", JPIT3, GET16(jerry_ram_8, JPIT3));
WriteLog("F1%04X (JPIT4): $%04X\n", JPIT4, GET16(jerry_ram_8, JPIT4));
WriteLog("F1%04X (CLK1): $%04X\n", CLK1, GET16(jerry_ram_8, CLK1));
WriteLog("F1%04X (CLK2): $%04X\n", CLK2, GET16(jerry_ram_8, CLK2));
WriteLog("F1%04X (CLK3): $%04X\n", CLK3, GET16(jerry_ram_8, CLK3));
WriteLog("F1%04X (JINTCTRL): $%04X\n", JINTCTRL, GET16(jerry_ram_8, JINTCTRL));
WriteLog("F1%04X (ASIDATA): $%04X\n", ASIDATA, GET16(jerry_ram_8, ASIDATA));
WriteLog("F1%04X (ASICTRL): $%04X\n", ASICTRL, GET16(jerry_ram_8, ASICTRL));
WriteLog("F1%04X (ASICLK): $%04X\n", ASICLK, GET16(jerry_ram_8, ASICLK));
WriteLog("F1%04X (SCLK): $%04X\n", SCLK, GET16(jerry_ram_8, SCLK));
WriteLog("F1%04X (SMODE): $%04X\n", SMODE, GET16(jerry_ram_8, SMODE));
WriteLog("---------------------------------------------------------------------\n\n\n");
}
//
// JERRY byte access (read)
//
uint8_t JERRYReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
uint8_t JERRYReadByte(uint32_t offset, uint32_t who)
{
#ifdef JERRY_DEBUG
WriteLog("JERRY: Reading byte at %06X\n", offset);
#endif
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
return DSPReadByte(offset, who);
else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
return DSPReadByte(offset, who);
// LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
else if (offset >= 0xF1A148 && offset <= 0xF1A153)
return DACReadByte(offset, who);
// F10036 R xxxxxxxx xxxxxxxx JPIT1 - timer 1 pre-scaler
// F10038 R xxxxxxxx xxxxxxxx JPIT2 - timer 1 divider
// F1003A R xxxxxxxx xxxxxxxx JPIT3 - timer 2 pre-scaler
// F1003C R xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
//This is WRONG!
// else if (offset >= 0xF10000 && offset <= 0xF10007)
//This is still wrong. What needs to be returned here are the values being counted down
//in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
//This is probably the problem with the new timer code... This is invalid
//under the new system... !!! FIX !!!
else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
{
WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
}
// else if (offset >= 0xF10010 && offset <= 0xF10015)
// return clock_byte_read(offset);
// else if (offset >= 0xF17C00 && offset <= 0xF17C01)
// return anajoy_byte_read(offset);
else if (offset >= 0xF14000 && offset <= 0xF14003)
// return JoystickReadByte(offset) | EepromReadByte(offset);
{
uint16_t value = JoystickReadWord(offset & 0xFE);
@ -489,7 +226,6 @@ WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
else
value >>= 8;
// This is wrong, should only have the lowest bit from $F14001
return value | EepromReadByte(offset);
}
else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
@ -498,42 +234,19 @@ WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
return jerry_ram_8[offset & 0xFFFF];
}
//
// JERRY word access (read)
//
uint16_t JERRYReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
uint16_t JERRYReadWord(uint32_t offset, uint32_t who)
{
#ifdef JERRY_DEBUG
WriteLog("JERRY: Reading word at %06X\n", offset);
#endif
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
return DSPReadWord(offset, who);
else if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
return DSPReadWord(offset, who);
// LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
else if (offset >= 0xF1A148 && offset <= 0xF1A153)
return DACReadWord(offset, who);
// F10036 R xxxxxxxx xxxxxxxx JPIT1 - timer 1 pre-scaler
// F10038 R xxxxxxxx xxxxxxxx JPIT2 - timer 1 divider
// F1003A R xxxxxxxx xxxxxxxx JPIT3 - timer 2 pre-scaler
// F1003C R xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
//This is WRONG!
// else if ((offset >= 0xF10000) && (offset <= 0xF10007))
//This is still wrong. What needs to be returned here are the values being counted down
//in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
{
WriteLog("JERRY: Unhandled timer read (WORD) at %08X...\n", offset);
}
// else if ((offset >= 0xF10010) && (offset <= 0xF10015))
// return clock_word_read(offset);
else if (offset == 0xF10020)
// return jerryIntPending;
return jerryPendingInterrupt;
// else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
// return anajoy_word_read(offset);
else if (offset == 0xF14000)
return (JoystickReadWord(offset) & 0xFFFE) | EepromReadWord(offset);
else if ((offset >= 0xF14002) && (offset < 0xF14003))
@ -541,251 +254,114 @@ WriteLog("JERRY: Unhandled timer read (WORD) at %08X...\n", offset);
else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
return EepromReadWord(offset);
/*if (offset >= 0xF1D000)
WriteLog("JERRY: Reading word at %08X [%04X]...\n", offset, ((uint16_t)jerry_ram_8[(offset+0)&0xFFFF] << 8) | jerry_ram_8[(offset+1)&0xFFFF]);//*/
offset &= 0xFFFF; // Prevent crashing...!
offset &= 0xFFFF;
return ((uint16_t)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1];
}
//
// JERRY byte access (write)
//
void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{
// Moved here tentatively, so we can see everything written to JERRY.
jerry_ram_8[offset & 0xFFFF] = data;
#ifdef JERRY_DEBUG
WriteLog("jerry: writing byte %.2x at 0x%.6x\n",data,offset);
#endif
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20))
{
DSPWriteByte(offset, data, who);
return;
}
else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE + 0x2000))
{
DSPWriteByte(offset, data, who);
return;
}
// SCLK ($F1A150--8 bits wide)
//NOTE: This should be taken care of in DAC...
#if 0
else if ((offset >= 0xF1A152) && (offset <= 0xF1A153))
{
#if 0
// WriteLog("JERRY: Writing %02X to SCLK...\n", data);
if ((offset & 0x03) == 2)
sclk = (sclk & 0x00FF) | ((uint32_t)data << 8);
else
sclk = (sclk & 0xFF00) | (uint32_t)data;
#else
sclk = data;
#endif
#warning "!!! SCLK should be handled in dac.cpp !!!"
JERRYI2SInterruptTimer = -1;
RemoveCallback(JERRYI2SCallback);
JERRYI2SCallback();
// return;
}
#endif
// LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
else if (offset >= 0xF1A148 && offset <= 0xF1A157)
{
DACWriteByte(offset, data, who);
return;
}
else if (offset >= 0xF10000 && offset <= 0xF10007)
{
WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset);
return;
}
/* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
{
clock_byte_write(offset, data);
return;
}//*/
// JERRY -> 68K interrupt enables/latches (need to be handled!)
else if (offset >= 0xF10020 && offset <= 0xF10021)//WAS:23)
else if (offset >= 0xF10020 && offset <= 0xF10021)
{
if (offset == 0xF10020)
{
// Clear pending interrupts...
jerryPendingInterrupt &= ~data;
}
else if (offset == 0xF10021)
jerryInterruptMask = data;
//WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", data, offset);
//WriteLog("JERRY: (Previous is partially handled... IRQMask=$%04X)\n", jerryInterruptMask);
}
/* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
{
anajoy_byte_write(offset, data);
return;
}*/
else if ((offset >= 0xF14000) && (offset <= 0xF14003))
{
WriteLog("JERRYWriteByte: Unhandled byte write to JOYSTICK by %s.\n", whoName[who]);
// JoystickWriteByte(offset, data);
JoystickWriteWord(offset & 0xFE, (uint16_t)data);
// This is wrong, EEPROM is never written here
EepromWriteByte(offset, data);
return;
}
else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
{
EepromWriteByte(offset, data);
return;
}
//Need to protect write attempts to Wavetable ROM (F1D000-FFF)
if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
return;
// jerry_ram_8[offset & 0xFFFF] = data;
}
//
// JERRY word access (write)
//
void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who)
{
// Moved here tentatively, so we can see everything written to JERRY.
jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
#ifdef JERRY_DEBUG
WriteLog( "JERRY: Writing word %04X at %06X\n", data, offset);
#endif
#if 1
if (offset == 0xF10000)
WriteLog("JERRY: JPIT1 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10002)
WriteLog("JERRY: JPIT2 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10004)
WriteLog("JERRY: JPIT3 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10006)
WriteLog("JERRY: JPIT4 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10010)
WriteLog("JERRY: CLK1 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10012)
WriteLog("JERRY: CLK2 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10014)
WriteLog("JERRY: CLK3 word written by %s: %u\n", whoName[who], data);
//else if (offset == 0xF1A100)
// WriteLog("JERRY: D_FLAGS word written by %s: %u\n", whoName[who], data);
//else if (offset == 0xF1A102)
// WriteLog("JERRY: D_FLAGS+2 word written by %s: %u\n", whoName[who], data);
else if (offset == 0xF10020)
WriteLog("JERRY: JINTCTRL word written by %s: $%04X (%s%s%s%s%s%s)\n", whoName[who], data,
(data & 0x01 ? "Extrnl " : ""), (data & 0x02 ? "DSP " : ""),
(data & 0x04 ? "Timer0 " : ""), (data & 0x08 ? "Timer1 " : ""),
(data & 0x10 ? "ASI " : ""), (data & 0x20 ? "I2S " : ""));
#endif
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20))
{
DSPWriteWord(offset, data, who);
return;
}
else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE + 0x2000))
{
DSPWriteWord(offset, data, who);
return;
}
//NOTE: This should be taken care of in DAC...
#if 0
else if (offset == 0xF1A152) // Bottom half of SCLK ($F1A150)
{
#warning "!!! SCLK should be handled in dac.cpp !!!"
WriteLog("JERRY: Writing $%X to SCLK (by %s)...\n", data, whoName[who]);
//This should *only* be enabled when SMODE has its INTERNAL bit set! !!! FIX !!!
#if 0
sclk = (uint8_t)data;
#else
sclk = data & 0xFF;
#endif
JERRYI2SInterruptTimer = -1;
RemoveCallback(JERRYI2SCallback);
JERRYI2SCallback();
DACWriteWord(offset, data, who);
return;
}
#endif
// LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
else if (offset >= 0xF1A148 && offset <= 0xF1A156)
{
DACWriteWord(offset, data, who);
return;
}
else if (offset >= 0xF10000 && offset <= 0xF10007)
{
switch(offset & 0x07)
{
case 0:
JERRYPIT1Prescaler = data;
JERRYResetPIT1();
break;
case 2:
JERRYPIT1Divider = data;
JERRYResetPIT1();
break;
case 4:
JERRYPIT2Prescaler = data;
JERRYResetPIT2();
break;
case 6:
JERRYPIT2Divider = data;
JERRYResetPIT2();
case 0:
JERRYPIT1Prescaler = data;
JERRYResetPIT1();
break;
case 2:
JERRYPIT1Divider = data;
JERRYResetPIT1();
break;
case 4:
JERRYPIT2Prescaler = data;
JERRYResetPIT2();
break;
case 6:
JERRYPIT2Divider = data;
JERRYResetPIT2();
}
// Need to handle (unaligned) cases???
return;
}
// JERRY -> 68K interrupt enables/latches (need to be handled!)
else if (offset >= 0xF10020 && offset <= 0xF10022)
{
jerryInterruptMask = data & 0xFF;
jerryPendingInterrupt &= ~(data >> 8);
//WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%04X to $%08X!\n", data, offset);
//WriteLog("JERRY: (Previous is partially handled... IRQMask=$%04X)\n", jerryInterruptMask);
return;
}
else if (offset >= 0xF14000 && offset < 0xF14003)
{
JoystickWriteWord(offset, data);
EepromWriteWord(offset, data);
return;
}
else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
{
EepromWriteWord(offset, data);
return;
}
//Need to protect write attempts to Wavetable ROM (F1D000-FFF)
if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
return;
// jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
// jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
}
int JERRYGetPIT1Frequency(void)
{
int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
return systemClockFrequency / ((JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1));
}
int JERRYGetPIT2Frequency(void)
{
int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
return systemClockFrequency / ((JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1));
}

View File

@ -5,13 +5,11 @@
#ifndef __JERRY_H__
#define __JERRY_H__
//#include "types.h"
#include "memory.h"
void JERRYInit(void);
void JERRYReset(void);
void JERRYDone(void);
void JERRYDumpIORegistersToLog(void);
uint8_t JERRYReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t JERRYReadWord(uint32_t offset, uint32_t who = UNKNOWN);
@ -26,7 +24,6 @@ int JERRYGetPIT2Frequency(void);
// 68000 Interrupt bit positions (enabled at $F10020)
//enum { IRQ2_EXTERNAL = 0, IRQ2_DSP, IRQ2_TIMER1, IRQ2_TIMER2, IRQ2_ASI, IRQ2_SSI };
enum { IRQ2_EXTERNAL=0x01, IRQ2_DSP=0x02, IRQ2_TIMER1=0x04, IRQ2_TIMER2=0x08, IRQ2_ASI=0x10, IRQ2_SSI=0x20 };
bool JERRYIRQEnabled(int irq);
@ -38,7 +35,6 @@ void JERRYI2SCallback(void);
// External variables
//extern uint32_t JERRYI2SInterruptDivide;
extern int32_t JERRYI2SInterruptTimer;
#endif

View File

@ -14,10 +14,9 @@
//
#include "joystick.h"
#include <string.h> // For memset()
#include <string.h>
#include "gpu.h"
#include "jaguar.h"
#include "log.h"
#include "settings.h"
// Global vars
@ -25,68 +24,38 @@
static uint8_t joystick_ram[4];
uint8_t joypad0Buttons[21];
uint8_t joypad1Buttons[21];
bool audioEnabled = false;
bool joysticksEnabled = false;
bool GUIKeyHeld = false;
extern int start_logging;
int gpu_start_log = 0;
int op_start_log = 0;
int blit_start_log = 0;
int effect_start = 0;
int effect_start2 = 0, effect_start3 = 0, effect_start4 = 0, effect_start5 = 0, effect_start6 = 0;
bool interactiveMode = false;
bool iLeft, iRight, iToggle = false;
bool keyHeld1 = false, keyHeld2 = false, keyHeld3 = false;
int objectPtr = 0;
bool startMemLog = false;
extern bool doDSPDis, doGPUDis;
bool blitterSingleStep = false;
bool bssGo = false;
bool bssHeld = false;
static bool joysticksEnabled;
extern bool lagged;
extern void (*inputcb)();
void JoystickInit(void)
{
JoystickReset();
}
void JoystickExec(void)
{
gpu_start_log = 0; // Only log while key down!
effect_start = 0;
effect_start2 = effect_start3 = effect_start4 = effect_start5 = effect_start6 = 0;
blit_start_log = 0;
iLeft = iRight = false;
}
void JoystickReset(void)
{
memset(joystick_ram, 0x00, 4);
memset(joypad0Buttons, 0, 21);
memset(joypad1Buttons, 0, 21);
joysticksEnabled = false;
}
void JoystickDone(void)
{
}
uint16_t JoystickReadWord(uint32_t offset)
{
lagged = false;
if (__builtin_expect(!!inputcb, false))
inputcb();
// E, D, B, 7
uint8_t joypad0Offset[16] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0x04, 0x00, 0xFF
};
@ -94,7 +63,6 @@ uint16_t JoystickReadWord(uint32_t offset)
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x0C, 0xFF
};
#warning "No bounds checking done in JoystickReadByte!"
offset &= 0x03;
if (offset == 0)
@ -102,8 +70,6 @@ uint16_t JoystickReadWord(uint32_t offset)
if (!joysticksEnabled)
return 0xFFFF;
// Joystick data returns active low for buttons pressed, high for non-
// pressed.
uint16_t data = 0xFFFF;
uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
@ -134,21 +100,17 @@ uint16_t JoystickReadWord(uint32_t offset)
}
else if (offset == 2)
{
// Hardware ID returns NTSC/PAL identification bit here
// N.B.: On real H/W, bit 7 is *always* zero...!
uint16_t data = 0xFF6F | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
if (!joysticksEnabled)
return data;
// Joystick data returns active low for buttons pressed, high for non-
// pressed.
uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
if (offset0 != 0xFF)
{
offset0 /= 4; // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
offset0 /= 4;
uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
@ -158,7 +120,7 @@ uint16_t JoystickReadWord(uint32_t offset)
if (offset1 != 0xFF)
{
offset1 /= 4; // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
offset1 /= 4;
uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
@ -172,18 +134,14 @@ uint16_t JoystickReadWord(uint32_t offset)
return 0xFFFF;
}
void JoystickWriteWord(uint32_t offset, uint16_t data)
{
#warning "No bounds checking done for JoystickWriteWord!"
offset &= 0x03;
joystick_ram[offset + 0] = (data >> 8) & 0xFF;
joystick_ram[offset + 1] = data & 0xFF;
if (offset == 0)
{
audioEnabled = (data & 0x0100 ? true : false);
joysticksEnabled = (data & 0x8000 ? true : false);
}
}

View File

@ -34,16 +34,11 @@ BUTTON_PAUSE = 20, BUTTON_LAST = 20 };
void JoystickInit(void);
void JoystickReset(void);
void JoystickDone(void);
//void JoystickWriteByte(uint32_t, uint8_t);
void JoystickWriteWord(uint32_t, uint16_t);
//uint8_t JoystickReadByte(uint32_t);
uint16_t JoystickReadWord(uint32_t);
void JoystickExec(void);
extern uint8_t joypad0Buttons[];
extern uint8_t joypad1Buttons[];
extern bool audioEnabled;
extern bool joysticksEnabled;
#endif // __JOYSTICK_H__

View File

@ -1,80 +0,0 @@
//
// Log handler
//
// Originally by David Raingeard (Cal2)
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
// Cleanups/new stuff by James Hammons
// (C) 2010 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
// JLH 07/11/2011 Instead of dumping out on max log file size being reached, we
// now just silently ignore any more output. 10 megs ought to be
// enough for anybody. ;-) Except when it isn't. :-P
//
#include "log.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
//#define MAX_LOG_SIZE 10000000 // Maximum size of log file (10 MB)
#define MAX_LOG_SIZE 100000000 // Maximum size of log file (100 MB)
static FILE * log_stream = NULL;
static uint32_t logSize = 0;
int LogInit(const char * path)
{
log_stream = fopen(path, "w");
if (log_stream == NULL)
return 0;
return 1;
}
FILE * LogGet(void)
{
return log_stream;
}
void LogDone(void)
{
if (log_stream != NULL)
fclose(log_stream);
}
//
// This logger is used mainly to ensure that text gets written to the log file
// even if the program crashes. The performance hit is acceptable in this case!
//
void WriteLog(const char * text, ...)
{
va_list arg;
va_start(arg, text);
if (log_stream == NULL)
{
va_end(arg);
return;
}
logSize += vfprintf(log_stream, text, arg);
if (logSize > MAX_LOG_SIZE)
{
// Instead of dumping out, we just close the file and ignore any more output.
fflush(log_stream);
fclose(log_stream);
log_stream = NULL;
}
va_end(arg);
fflush(log_stream); // Make sure that text is written!
}

View File

@ -1,27 +0,0 @@
//
// log.h: Logfile support
//
#ifndef __LOG_H__
#define __LOG_H__
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
int LogInit(const char *);
FILE * LogGet(void);
void LogDone(void);
void WriteLog(const char * text, ...);
#ifdef __cplusplus
}
#endif
// Some useful defines... :-)
//#define GPU_DEBUG
//#define LOG_BLITS
#endif // __LOG_H__

View File

@ -10,26 +10,9 @@
// JLH 12/10/2009 Repurposed this file. :-)
//
/*
$FFFFFF => 16,777,215
$A00000 => 10,485,760
Really, just six megabytes short of using the entire address space...
Why not? We could just allocate the entire space and then use the MMU code to do
things like call functions and whatnot...
In other words, read/write would just tuck the value into the host RAM space and
the I/O function would take care of any weird stuff...
Actually: writes would tuck in the value, but reads would have to be handled
correctly since some registers do not fall on the same address as far as reading
goes... Still completely doable though. :-)
N.B.: Jaguar RAM is only 2 megs. ROM is 6 megs max, IO is 128K
*/
#include "memory.h"
uint8_t jagMemSpace[0xF20000]; // The entire memory space of the Jaguar...!
uint8_t jagMemSpace[0xF20000];
uint8_t * jaguarMainRAM = &jagMemSpace[0x000000];
uint8_t * jaguarMainROM = &jagMemSpace[0x800000];
@ -37,85 +20,6 @@ uint8_t * cdRAM = &jagMemSpace[0xDFFF00];
uint8_t * gpuRAM = &jagMemSpace[0xF03000];
uint8_t * dspRAM = &jagMemSpace[0xF1B000];
#if 0
union Word
{
uint16_t word;
struct {
// This changes depending on endianness...
#ifdef __BIG_ENDIAN__
uint8_t hi, lo; // Big endian
#else
uint8_t lo, hi; // Little endian
#endif
};
};
#endif
#if 0
union DWord
{
uint32_t dword;
struct
{
#ifdef __BIG_ENDIAN__
uint16_t hiw, low;
#else
uint16_t low, hiw;
#endif
};
};
#endif
#if 0
static void test(void)
{
Word reg;
reg.word = 0x1234;
reg.lo = 0xFF;
reg.hi = 0xEE;
DWord reg2;
reg2.hiw = 0xFFFE;
reg2.low = 0x3322;
reg2.low.lo = 0x11;
}
#endif
// OR, we could do like so:
#if 0
#ifdef __BIG_ENDIAN__
#define DWORD_BYTE_HWORD_H 1
#define DWORD_BYTE_HWORD_L 2
#define DWORD_BYTE_LWORD_H 3
#define DWORD_BYTE_LWORD_L 4
#else
#define DWORD_BYTE_HWORD_H 4
#define DWORD_BYTE_HWORD_L 3
#define DWORD_BYTE_LWORD_H 2
#define DWORD_BYTE_LWORD_L 1
#endif
// But this starts to get cumbersome after a while... Is union really better?
//More union stuff...
unsigned long ByteSwap1 (unsigned long nLongNumber)
{
union u {unsigned long vi; unsigned char c[sizeof(unsigned long)];};
union v {unsigned long ni; unsigned char d[sizeof(unsigned long)];};
union u un;
union v vn;
un.vi = nLongNumber;
vn.d[0]=un.c[3];
vn.d[1]=un.c[2];
vn.d[2]=un.c[1];
vn.d[3]=un.c[0];
return (vn.ni);
}
#endif
//Not sure if this is a good approach yet...
//should be if we use proper aliasing, and htonl and friends...
#if 1
uint32_t & butch = *((uint32_t *)&jagMemSpace[0xDFFF00]); // base of Butch == interrupt control register, R/W
uint32_t & dscntrl = *((uint32_t *)&jagMemSpace[0xDFFF04]); // DSA control register, R/W
uint16_t & ds_data = *((uint16_t *)&jagMemSpace[0xDFFF0A]); // DSA TX/RX data, R/W
@ -127,29 +31,6 @@ uint32_t & sb_time = *((uint32_t *)&jagMemSpace[0xDFFF20]); // Subcode time an
uint32_t & fifo_data = *((uint32_t *)&jagMemSpace[0xDFFF24]); // i2s FIFO data
uint32_t & i2sdat2 = *((uint32_t *)&jagMemSpace[0xDFFF28]); // i2s FIFO data (old)
uint32_t & unknown = *((uint32_t *)&jagMemSpace[0xDFFF2C]); // Seems to be some sort of I2S interface
#else
uint32_t butch, dscntrl, ds_data, i2cntrl, sbcntrl, subdata, subdatb, sb_time, fifo_data, i2sdat2, unknown;
#endif
//#warning "Need to separate out this stuff (or do we???)"
//if we use a contiguous memory space, we don't need this shit...
//err, maybe we do, let's not be so hasty now... :-)
//#define ENDIANSAFE(x) htonl(x)
// The nice thing about doing it this way is that on big endian machines, htons/l
// compile to nothing and on Intel machines, it compiles down to a single bswap instruction.
// So endianness issues go away nicely without a lot of drama. :-D
#define BSWAP16(x) (htons(x))
#define BSWAP32(x) (htonl(x))
//this isn't endian safe...
#define BSWAP64(x) ((htonl(x & 0xFFFFFFFF) << 32) | htonl(x >> 32))
// Actually, we use ESAFExx() macros instead of this, and we use GCC to check the endianness...
// Actually, considering that "byteswap.h" doesn't exist elsewhere, the above
// is probably our best bet here. Just need to rename them to ESAFExx().
// Look at <endian.h> and see if that header is portable or not.
uint16_t & memcon1 = *((uint16_t *)&jagMemSpace[0xF00000]);
uint16_t & memcon2 = *((uint16_t *)&jagMemSpace[0xF00002]);
@ -196,7 +77,7 @@ uint32_t & g_pc = *((uint32_t *)&jagMemSpace[0xF02110]);
uint32_t & g_ctrl = *((uint32_t *)&jagMemSpace[0xF02114]);
uint32_t & g_hidata = *((uint32_t *)&jagMemSpace[0xF02118]);
uint32_t & g_divctrl = *((uint32_t *)&jagMemSpace[0xF0211C]);
uint32_t g_remain; // Dual register with $F0211C
uint32_t g_remain;
uint32_t & a1_base = *((uint32_t *)&jagMemSpace[0xF02200]);
uint32_t & a1_flags = *((uint32_t *)&jagMemSpace[0xF02204]);
uint32_t & a1_clip = *((uint32_t *)&jagMemSpace[0xF02208]);
@ -240,7 +121,7 @@ uint16_t & clk3 = *((uint16_t *)&jagMemSpace[0xF10014]);
uint16_t & j_int = *((uint16_t *)&jagMemSpace[0xF10020]);
uint16_t & asidata = *((uint16_t *)&jagMemSpace[0xF10030]);
uint16_t & asictrl = *((uint16_t *)&jagMemSpace[0xF10032]);
uint16_t asistat; // Dual register with $F10032
uint16_t asistat;
uint16_t & asiclk = *((uint16_t *)&jagMemSpace[0xF10034]);
uint16_t & joystick = *((uint16_t *)&jagMemSpace[0xF14000]);
uint16_t & joybuts = *((uint16_t *)&jagMemSpace[0xF14002]);
@ -252,17 +133,12 @@ uint32_t & d_pc = *((uint32_t *)&jagMemSpace[0xF1A110]);
uint32_t & d_ctrl = *((uint32_t *)&jagMemSpace[0xF1A114]);
uint32_t & d_mod = *((uint32_t *)&jagMemSpace[0xF1A118]);
uint32_t & d_divctrl = *((uint32_t *)&jagMemSpace[0xF1A11C]);
uint32_t d_remain; // Dual register with $F0211C
uint32_t d_remain;
uint32_t & d_machi = *((uint32_t *)&jagMemSpace[0xF1A120]);
uint16_t & ltxd = *((uint16_t *)&jagMemSpace[0xF1A148]);
uint16_t lrxd; // Dual register with $F1A148
uint16_t lrxd;
uint16_t & rtxd = *((uint16_t *)&jagMemSpace[0xF1A14C]);
uint16_t rrxd; // Dual register with $F1A14C
uint16_t rrxd;
uint8_t & sclk = *((uint8_t *) &jagMemSpace[0xF1A150]);
uint8_t sstat; // Dual register with $F1A150
uint8_t sstat;
uint32_t & smode = *((uint32_t *)&jagMemSpace[0xF1A154]);
// Memory debugging identifiers
const char * whoName[10] =
{ "Unknown", "Jaguar", "DSP", "GPU", "TOM", "JERRY", "M68K", "Blitter", "OP", "Debugger" };

View File

@ -16,13 +16,9 @@ extern uint8_t * jaguarMainROM;
extern uint8_t * gpuRAM;
extern uint8_t * dspRAM;
#if 1
extern uint32_t & butch, & dscntrl;
extern uint16_t & ds_data;
extern uint32_t & i2cntrl, & sbcntrl, & subdata, & subdatb, & sb_time, & fifo_data, & i2sdat2, & unknown;
#else
extern uint32_t butch, dscntrl, ds_data, i2cntrl, sbcntrl, subdata, subdatb, sb_time, fifo_data, i2sdat2, unknown;
#endif
extern uint16_t & memcon1, & memcon2, & hc, & vc, & lph, & lpv;
extern uint64_t & obData;
@ -53,156 +49,17 @@ extern uint32_t & d_machi;
extern uint16_t & ltxd, lrxd, & rtxd, rrxd;
extern uint8_t & sclk, sstat;
extern uint32_t & smode;
/*
uint16_t & ltxd = *((uint16_t *)&jagMemSpace[0xF1A148]);
uint16_t lrxd; // Dual register with $F1A148
uint16_t & rtxd = *((uint16_t *)&jagMemSpace[0xF1A14C]);
uint16_t rrxd; // Dual register with $F1A14C
uint8_t & sclk = *((uint8_t *) &jagMemSpace[0xF1A150]);
uint8_t sstat; // Dual register with $F1A150
uint32_t & smode = *((uint32_t *)&jagMemSpace[0xF1A154]);
*/
// Read/write tracing enumeration
enum { UNKNOWN, JAGUAR, DSP, GPU, TOM, JERRY, M68K, BLITTER, OP, DEBUG };
extern const char * whoName[10];
// BIOS identification enum
//enum { BIOS_NORMAL=0x01, BIOS_CD=0x02, BIOS_STUB1=0x04, BIOS_STUB2=0x08, BIOS_DEV_CD=0x10 };
//extern int biosAvailable;
// Some handy macros to help converting native endian to big endian (jaguar native)
// Some handy macros to help converting little endian to big endian (jaguar native)
// & vice versa
#define SET64(r, a, v) r[(a)] = ((v) & 0xFF00000000000000) >> 56, r[(a)+1] = ((v) & 0x00FF000000000000) >> 48, \
r[(a)+2] = ((v) & 0x0000FF0000000000) >> 40, r[(a)+3] = ((v) & 0x000000FF00000000) >> 32, \
r[(a)+4] = ((v) & 0xFF000000) >> 24, r[(a)+5] = ((v) & 0x00FF0000) >> 16, \
r[(a)+6] = ((v) & 0x0000FF00) >> 8, r[(a)+7] = (v) & 0x000000FF
#define GET64(r, a) (((uint64_t)r[(a)] << 56) | ((uint64_t)r[(a)+1] << 48) | \
((uint64_t)r[(a)+2] << 40) | ((uint64_t)r[(a)+3] << 32) | \
((uint64_t)r[(a)+4] << 24) | ((uint64_t)r[(a)+5] << 16) | \
((uint64_t)r[(a)+6] << 8) | (uint64_t)r[(a)+7])
#define SET32(r, a, v) r[(a)] = ((v) & 0xFF000000) >> 24, r[(a)+1] = ((v) & 0x00FF0000) >> 16, \
r[(a)+2] = ((v) & 0x0000FF00) >> 8, r[(a)+3] = (v) & 0x000000FF
#define GET32(r, a) ((r[(a)] << 24) | (r[(a)+1] << 16) | (r[(a)+2] << 8) | r[(a)+3])
#define SET16(r, a, v) r[(a)] = ((v) & 0xFF00) >> 8, r[(a)+1] = (v) & 0xFF
#define GET16(r, a) ((r[(a)] << 8) | r[(a)+1])
//This doesn't seem to work on OSX. So have to figure something else out. :-(
//byteswap.h doesn't exist on OSX.
#if 0
// This is GCC specific, but we can fix that if we need to...
// Big plus of this approach is that these compile down to single instructions on little
// endian machines while one big endian machines we don't have any overhead. :-)
#include <byteswap.h>
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ESAFE16(x) bswap_16(x)
#define ESAFE32(x) bswap_32(x)
#define ESAFE64(x) bswap_64(x)
#else
#define ESAFE16(x) (x)
#define ESAFE32(x) (x)
#define ESAFE64(x) (x)
#endif
#endif
#if 0
Stuff ripped out of Hatari, that may be useful:
/* Can the actual CPU access unaligned memory? */
#ifndef CPU_CAN_ACCESS_UNALIGNED
# if defined(__i386__) || defined(powerpc) || defined(__mc68020__)
# define CPU_CAN_ACCESS_UNALIGNED 1
# else
# define CPU_CAN_ACCESS_UNALIGNED 0
# endif
#endif
/* If the CPU can access unaligned memory, use these accelerated functions: */
#if CPU_CAN_ACCESS_UNALIGNED
#include <SDL_endian.h>
static inline uae_u32 do_get_mem_long(void *a)
{
return SDL_SwapBE32(*(uae_u32 *)a);
}
static inline uae_u16 do_get_mem_word(void *a)
{
return SDL_SwapBE16(*(uae_u16 *)a);
}
static inline void do_put_mem_long(void *a, uae_u32 v)
{
*(uae_u32 *)a = SDL_SwapBE32(v);
}
static inline void do_put_mem_word(void *a, uae_u16 v)
{
*(uae_u16 *)a = SDL_SwapBE16(v);
}
#else /* Cpu can not access unaligned memory: */
static inline uae_u32 do_get_mem_long(void *a)
{
uae_u8 *b = (uae_u8 *)a;
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
}
static inline uae_u16 do_get_mem_word(void *a)
{
uae_u8 *b = (uae_u8 *)a;
return (b[0] << 8) | b[1];
}
static inline void do_put_mem_long(void *a, uae_u32 v)
{
uae_u8 *b = (uae_u8 *)a;
b[0] = v >> 24;
b[1] = v >> 16;
b[2] = v >> 8;
b[3] = v;
}
static inline void do_put_mem_word(void *a, uae_u16 v)
{
uae_u8 *b = (uae_u8 *)a;
b[0] = v >> 8;
b[1] = v;
}
#endif /* CPU_CAN_ACCESS_UNALIGNED */
/* These are same for all architectures: */
static inline uae_u8 do_get_mem_byte(uae_u8 *a)
{
return *a;
}
static inline void do_put_mem_byte(uae_u8 *a, uae_u8 v)
{
*a = v;
}
#endif
#define SET64(r, a, v) *(uint64_t*)&r[(a)] = __builtin_bswap64((v))
#define GET64(r, a) (__builtin_bswap64(*(uint64_t*)&r[(a)]))
#define SET32(r, a, v) *(uint32_t*)&r[(a)] = __builtin_bswap32((v))
#define GET32(r, a) (__builtin_bswap32(*(uint32_t*)&r[(a)]))
#define SET16(r, a, v) *(uint16_t*)&r[(a)] = __builtin_bswap16((v))
#define GET16(r, a) (__builtin_bswap16(*(uint16_t*)&r[(a)]))
#endif // __MEMORY_H__

View File

@ -25,12 +25,6 @@
#include <stdlib.h>
#include <string.h>
#include <log.h>
#include <settings.h>
#define MEMTRACK_FILENAME "memtrack.eeprom"
//#define DEBUG_MEMTRACK
enum { MT_NONE, MT_PROD_ID, MT_RESET, MT_WRITE_ENABLE };
enum { MT_IDLE, MT_PHASE1, MT_PHASE2 };
@ -38,66 +32,22 @@ enum { MT_IDLE, MT_PHASE1, MT_PHASE2 };
uint8_t mtMem[0x20000];
uint8_t mtCommand = MT_NONE;
uint8_t mtState = MT_IDLE;
bool haveMT = false;
char mtFilename[MAX_PATH];
// Private function prototypes
void MTWriteFile(void);
void MTStateMachine(uint8_t reg, uint16_t data);
void MTInit(void)
{
sprintf(mtFilename, "%s%s", vjs.EEPROMPath, MEMTRACK_FILENAME);
FILE * fp = fopen(mtFilename, "rb");
if (fp)
{
size_t ignored = fread(mtMem, 1, 0x20000, fp);
fclose(fp);
WriteLog("MT: Loaded NVRAM from %s\n", mtFilename);
haveMT = true;
}
else
WriteLog("MT: Could not open file \"%s\"!\n", mtFilename);
memset(mtMem, 0xFF, 0x20000);
}
void MTReset(void)
{
if (!haveMT)
memset(mtMem, 0xFF, 0x20000);
}
void MTDone(void)
{
MTWriteFile();
WriteLog("MT: Done.\n");
}
void MTWriteFile(void)
{
if (!haveMT)
return;
FILE * fp = fopen(mtFilename, "wb");
if (fp)
{
fwrite(mtMem, 1, 0x20000, fp);
fclose(fp);
}
else
WriteLog("MT: Could not create file \"%s\"!", mtFilename);
}
//
// This is crappy, there doesn't seem to be a word interface to the NVRAM. But
// we'll keep this as a placeholder for now.
//
uint16_t MTReadWord(uint32_t addr)
{
uint32_t value = MTReadLong(addr);
@ -107,14 +57,9 @@ uint16_t MTReadWord(uint32_t addr)
else if ((addr & 0x03) == 2)
value &= 0xFFFF;
#ifdef DEBUG_MEMTRACK
WriteLog("MT: Reading word @ $%06X: $%04X\n", addr, value);
#endif
return (uint16_t)value;
}
uint32_t MTReadLong(uint32_t addr)
{
uint32_t value = 0;
@ -131,30 +76,17 @@ uint32_t MTReadLong(uint32_t addr)
value = (uint32_t)mtMem[(addr & 0x7FFFC) >> 2];
}
// We do this because we're not sure how the real thing behaves; but it
// seems reasonable on its face to do it this way. :-P So we turn off write
// mode when reading the NVRAM.
if (mtCommand == MT_WRITE_ENABLE)
mtCommand = MT_NONE;
#ifdef DEBUG_MEMTRACK
WriteLog("MT: Reading long @ $%06X: $%08X\n", addr, value << 16);
#endif
return value << 16;
}
void MTWriteWord(uint32_t addr, uint16_t data)
{
// We don't care about writes to long offsets + 2
if ((addr & 0x3) == 2)
return;
#ifdef DEBUG_MEMTRACK
WriteLog("MT: Writing word @ $%06X: $%04X (Writing is %sabled)\n", addr, data, (mtCommand == MT_WRITE_ENABLE ? "en" : "dis"));
#endif
// Write to the NVRAM if it's enabled...
if (mtCommand == MT_WRITE_ENABLE)
{
mtMem[(addr & 0x7FFFC) >> 2] = (uint8_t)(data & 0xFF);
@ -163,63 +95,53 @@ WriteLog("MT: Writing word @ $%06X: $%04X (Writing is %sabled)\n", addr, data, (
switch (addr)
{
case (0x800000 + (4 * 0x5555)): // $815554
MTStateMachine(0, data);
break;
case (0x800000 + (4 * 0x2AAA)): // $80AAA8
MTStateMachine(1, data);
break;
case (0x800000 + (4 * 0x5555)):
MTStateMachine(0, data);
break;
case (0x800000 + (4 * 0x2AAA)):
MTStateMachine(1, data);
break;
}
}
void MTWriteLong(uint32_t addr, uint32_t data)
{
// Strip off lower 3 bits of the passed in address
addr &= 0xFFFFFC;
MTWriteWord(addr + 0, data & 0xFFFF);
MTWriteWord(addr + 2, data >> 16);
}
void MTStateMachine(uint8_t reg, uint16_t data)
{
#ifdef DEBUG_MEMTRACK
WriteLog("MTStateMachine: reg = %u, data = $%02X, current state = %u\n", reg, data, mtState);
#endif
switch (mtState)
{
case MT_IDLE:
if ((reg == 0) && (data == 0xAA))
mtState = MT_PHASE1;
case MT_IDLE:
if ((reg == 0) && (data == 0xAA))
mtState = MT_PHASE1;
break;
case MT_PHASE1:
if ((reg == 1) && (data == 0x55))
mtState = MT_PHASE2;
else
mtState = MT_IDLE;
break;
case MT_PHASE2:
if (reg == 0)
{
if (data == 0x90) // Product ID
mtCommand = MT_PROD_ID;
else if (data == 0xF0) // Reset
mtCommand = MT_NONE;
else if (data == 0xA0) // Write enagle
mtCommand = MT_WRITE_ENABLE;
break;
case MT_PHASE1:
if ((reg == 1) && (data == 0x55))
mtState = MT_PHASE2;
else
mtCommand = MT_NONE;
}
mtState = MT_IDLE;
mtState = MT_IDLE;
break;
break;
case MT_PHASE2:
if (reg == 0)
{
if (data == 0x90)
mtCommand = MT_PROD_ID;
else if (data == 0xF0)
mtCommand = MT_NONE;
else if (data == 0xA0)
mtCommand = MT_WRITE_ENABLE;
else
mtCommand = MT_NONE;
}
mtState = MT_IDLE;
break;
}
#ifdef DEBUG_MEMTRACK
WriteLog(" state = %u, cmd = %u\n", mtState, mtCommand);
#endif
}

View File

@ -12,4 +12,3 @@ uint16_t MTReadWord(uint32_t addr);
uint32_t MTReadLong(uint32_t addr);
void MTWriteWord(uint32_t addr, uint16_t data);
void MTWriteLong(uint32_t addr, uint32_t data);

View File

@ -1,608 +0,0 @@
//
// mmu.cpp
//
// Jaguar Memory Manager Unit
//
// by James Hammons
//
// JLH = James Hammons <jlhamm@acm.org>
//
// WHO WHEN WHAT
// --- ---------- -----------------------------------------------------------
// JLH 11/25/2009 Created this file. :-)
//
#include "mmu.h"
#include <stdlib.h> // For NULL definition
#include "dac.h"
//#include "jaguar.h"
//#include "memory.h"
//#include "jagbios.h"
#include "wavetable.h"
/*
Addresses to be handled:
SYSTEM SETUP REGISTERS
*MEMCON1 Memory Control Register 1 F00000 RW
*MEMCON2 Memory Control Register 2 F00002 RW
HC Horizontal Count F00004 RW
VC Vertical Count F00006 RW
LPH Light Pen Horizontal F00008 RO
LPV Light Pen Vertical F0000A RO
OB[0-3] Object Data Field F00010-16 RO
OLP Object List Pointer F00020-23 WO
OBF Object Flag F00026 WO
VMODE Video Mode F00028 WO
BORD1 Border Colour (Red & Green) F0002A WO
BORD2 Border Colour (Blue) F0002C WO
*HP Horizontal Period F0002E WO
*HBB Horizontal Blank Begin F00030 WO
*HBE Horizontal Blank End F00032 WO
*HS Horizontal Sync F00034 WO
*HVS Horizontal Vertical Sync F00036 WO
HDB1 Horizontal Display Begin 1 F00038 WO
HDB2 Horizontal Display Begin 2 F0003A WO
HDE Horizontal Display End F0003C WO
*VP Vertical Period F0003E WO
*VBB Vertical Blank Begin F00040 WO
*VBE Vertical Blank End F00042 WO
*VS Vertical Sync F00044 WO
VDB Vertical Display Begin F00046 WO
VDE Vertical Display End F00048 WO
*VEB Vertical Equalization Begin F0004A WO
*VEE Vertical Equalization End F0004C WO
VI Vertical Interrupt F0004E WO
PIT[0-1] Programmable Interrupt Timer F00050-52 WO
*HEQ Horizontal Equalization End F00054 WO
BG Background Colour F00058 WO
INT1 CPU Interrupt Control Register F000E0 RW
INT2 CPU Interrupt Resume Register F000E2 WO
CLUT Colour Look-Up Table F00400-7FE RW
LBUF Line Buffer F00800-1D9E RW
GPU REGISTERS
G_FLAGS GPU Flags Register F02100 RW
G_MTXC Matrix Control Register F02104 WO
G_MTXA Matrix Address Register F02108 WO
G_END Data Organization Register F0210C WO
G_PC GPU Program Counter F02110 RW
G_CTRL GPU Control/Status Register F02114 RW
G_HIDATA High Data Register F02118 RW
G_REMAIN Divide Unit Remainder F0211C RO
G_DIVCTRL Divide Unit Control F0211C WO
BLITTER REGISTERS
A1_BASE A1 Base Register F02200 WO
A1_FLAGS Flags Register F02204 WO
A1_CLIP A1 Clipping Size F02208 WO
A1_PIXEL A1 Pixel Pointer F0220C WO
F02204 RO
A1_STEP A1 Step Value F02210 WO
A1_FSTEP A1 Step Fraction Value F02214 WO
A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
A1_INC A1 Increment F0221C WO
A1_FINC A1 Increment Fraction F02220 WO
A2_BASE A2 Base Register F02224 WO
A2_FLAGS A2 Flags Register F02228 WO
A2_MASK A2 Window Mask F0222C WO
A2_PIXEL A2 Pixel Pointer F02230 WO
F0222C RO
A2_STEP A2 Step Value F02234 WO
B_CMD Command/Status Register F02238 RW
B_COUNT Counters Register F0223C WO
B_SRCD Source Data Register F02240 WO
B_DSTD Destination Data Register F02248 WO
B_DSTZ Destination Z Register F02250 WO
B_SRCZ1 Source Z Register 1 F02258 WO
B_SRCZ2 Source Z Register 2 F02260 WO
B_PATD Pattern Data Register F02268 WO
B_IINC Intensity Increment F02270 WO
B_ZINC Z Increment F02274 WO
B_STOP Collision Control F02278 WO
B_I3 Intensity 3 F0227C WO
B_I2 Intensity 2 F02280 WO
B_I1 Intensity 1 F02284 WO
B_I0 Intensity 0 F02288 WO
B_Z3 Z 3 F0228C WO
B_Z2 Z 2 F02290 WO
B_Z1 Z 1 F02294 WO
B_Z0 Z 0 F02298 WO
JERRY REGISTERS
*CLK1 Processor Clock Divider F10010 WO
*CLK2 Video Clock Divider F10012 WO
*CLK3 Chroma Clock Divider F10014 WO
JPIT1 Timer 1 Pre-scaler F10000 WO
JPIT3 Timer 2 Pre-scaler F10004 WO
JPIT2 Timer 1 Divider F10002 WO
JPIT4 Timer 2 Divider F10006 WO
J_INT Interrup Control Register F10020 RW
SCLK Serial Clock Frequency F1A150 WO
SMODE Serial Mode F1A154 WO
LTXD Left Transmit Data F1A148 WO
RTXD Right Transmit Data F1A14C WO
LRXD Left Receive Data F1A148 RO
RRXD Right Receive Data F1A14C RO
L_I2S Left I2S Serial Interface F1A148 RW
R_I2S Right I2S Serial Interface F1A14C RW
SSTAT Serial Status F1A150 RO
ASICLK Asynchronous Serial Interface Clock F10034 RW
ASICTRL Asynchronous Serial Control F10032 WO
ASISTAT Asynchronous Serial Status F10032 RO
ASIDATA Asynchronous Serial Data F10030 RW
JOYSTICK REGISTERS
JOYSTICK Joystick Register F14000 RW
JOYBUTS Button Register F14002 RW
DSP REGISTERS
D_FLAGS DSP Flags Register F1A100 RW
D_MTXC DSP Matrix Control Register F1A104 WO
D_MTXA DSP Matrix Address Register F1A108 WO
D_END DSP Data Organization Register F1A10C WO
D_PC DSP Program Counter F1A110 RW
D_CTRL DSP Control/Status Register F1A114 RW
D_MOD Modulo Instruction Mask F1A118 WO
D_REMAIN Divide Unit Remainder F1A11C RO
D_DIVCTRL Divide Unit Control F1A11C WO
D_MACHI MAC High Result Bits F1A120 RO
*/
/*
The approach here is to have a list of addresses and who handles them. Could be
a one-to-one memory location up to a range for each function. Will look
something like this:
{ 0xF14000, 0xF14001, MM_IO, JoystickReadHandler, JoystickWriteHandler },
Would be nice to have a way of either calling a handler function or reading/writing
directly to/from a variable or array...
*/
enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
/*
Would be nice to have different structs tailored to different memory access types,
but if we don't do that, we can encode things as follows:
MM_NOP: readFunc = writeFunc = NULL
MM_RAM: readFunc = byte array pointer, writeFunc = NULL
MM_ROM: readFunc = byte array pointer, writeFunc = NULL
MM_IO_R: readFunc = function pointer to read function, writeFunc = NULL
MM_IO_W: readFunc = NULL, writeFunc = function pointer to write function
MM_IO: readFunc = function pointer to read function, writeFunc = function pointer to write function
There may be a need to have readFunc do both read & write functions (makes sense? perhaps)
Should we have a read mask as well, for the purposes of reading?
*/
struct MemDesc {
uint32_t startAddr;
uint32_t endAddr;
MemType type;
// (void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
void * readFunc; // This is read & write with MM_IO
void * writeFunc;
uint32_t mask;
};
MemDesc memoryMap[] = {
{ 0x000000, 0x1FFFFF, MM_RAM, jaguarMainRAM },
{ 0x200000, 0x3FFFFF, MM_RAM, jaguarMainRAM }, // Mirror of 1st 2 megs
{ 0x400000, 0x5FFFFF, MM_RAM, jaguarMainRAM }, // " "
{ 0x600000, 0x7FFFFF, MM_RAM, jaguarMainRAM }, // " "
{ 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
{ 0xDFFF00, 0xDFFF03, MM_IO, &butch }, // base of Butch == interrupt control register, R/W
{ 0xDFFF04, 0xDFFF07, MM_IO, &dscntrl }, // DSA control register, R/W
{ 0xDFFF0A, 0xDFFF0B, MM_IO, &ds_data }, // DSA TX/RX data, R/W
{ 0xDFFF10, 0xDFFF13, MM_IO, &i2cntrl }, // i2s bus control register, R/W
{ 0xDFFF14, 0xDFFF17, MM_IO, &sbcntrl }, // CD subcode control register, R/W
{ 0xDFFF18, 0xDFFF1B, MM_IO, &subdata }, // Subcode data register A
{ 0xDFFF1C, 0xDFFF1F, MM_IO, &subdatb }, // Subcode data register B
{ 0xDFFF20, 0xDFFF23, MM_IO, &sb_time }, // Subcode time and compare enable (D24)
{ 0xDFFF24, 0xDFFF27, MM_IO, &fifo_data }, // i2s FIFO data
{ 0xDFFF28, 0xDFFF2B, MM_IO, &i2sdat2 }, // i2s FIFO data (old)
{ 0xDFFF2C, 0xDFFF2F, MM_IO, &unknown }, // Seems to be some sort of I2S interface
//{ 0xE00000, 0xE1FFFF, MM_ROM, jaguarBootROM },
// TOM REGISTERS
{ 0xF00000, 0xF00001, MM_IO, &memcon1 }, // *MEMCON1 Memory Control Register 1 F00000 RW
{ 0xF00002, 0xF00003, MM_IO, &memcon2 }, // *MEMCON2 Memory Control Register 2 F00002 RW
{ 0xF00004, 0xF00005, MM_IO, &hc }, // HC Horizontal Count F00004 RW
{ 0xF00006, 0xF00007, MM_IO, &vc }, // VC Vertical Count F00006 RW
{ 0xF00008, 0xF00009, MM_IO_R, &lph }, // LPH Light Pen Horizontal F00008 RO
{ 0xF0000A, 0xF0000B, MM_IO_R, &lpv }, // LPV Light Pen Vertical F0000A RO
{ 0xF00010, 0xF00017, MM_IO_R, &obData }, // OB[0-3] Object Data Field F00010-16 RO
{ 0xF00020, 0xF00023, MM_IO_W, &olp }, // OLP Object List Pointer F00020-23 WO
{ 0xF00026, 0xF00027, MM_IO_W, &obf }, // OBF Object Flag F00026 WO
{ 0xF00028, 0xF00029, MM_IO_W, &vmode }, // VMODE Video Mode F00028 WO
{ 0xF0002A, 0xF0002B, MM_IO_W, &bord1 }, // BORD1 Border Colour (Red & Green) F0002A WO
{ 0xF0002C, 0xF0002D, MM_IO_W, &bord2 }, // BORD2 Border Colour (Blue) F0002C WO
{ 0xF0002E, 0xF0002F, MM_IO_W, &hp }, // *HP Horizontal Period F0002E WO
{ 0xF00030, 0xF00031, MM_IO_W, &hbb }, // *HBB Horizontal Blank Begin F00030 WO
{ 0xF00032, 0xF00033, MM_IO_W, &hbe }, // *HBE Horizontal Blank End F00032 WO
{ 0xF00034, 0xF00035, MM_IO_W, &hs }, // *HS Horizontal Sync F00034 WO
{ 0xF00036, 0xF00037, MM_IO_W, &hvs }, // *HVS Horizontal Vertical Sync F00036 WO
{ 0xF00038, 0xF00039, MM_IO_W, &hdb1 }, // HDB1 Horizontal Display Begin 1 F00038 WO
{ 0xF0003A, 0xF0003B, MM_IO_W, &hdb2 }, // HDB2 Horizontal Display Begin 2 F0003A WO
{ 0xF0003C, 0xF0003D, MM_IO_W, &hde }, // HDE Horizontal Display End F0003C WO
{ 0xF0003E, 0xF0003F, MM_IO_W, &vp }, // *VP Vertical Period F0003E WO
{ 0xF00040, 0xF00041, MM_IO_W, &vbb }, // *VBB Vertical Blank Begin F00040 WO
{ 0xF00042, 0xF00043, MM_IO_W, &vbe }, // *VBE Vertical Blank End F00042 WO
{ 0xF00044, 0xF00045, MM_IO_W, &vs }, // *VS Vertical Sync F00044 WO
{ 0xF00046, 0xF00047, MM_IO_W, &vdb }, // VDB Vertical Display Begin F00046 WO
{ 0xF00048, 0xF00049, MM_IO_W, &vde }, // VDE Vertical Display End F00048 WO
{ 0xF0004A, 0xF0004B, MM_IO_W, &veb }, // *VEB Vertical Equalization Begin F0004A WO
{ 0xF0004C, 0xF0004D, MM_IO_W, &vee }, // *VEE Vertical Equalization End F0004C WO
{ 0xF0004E, 0xF0004F, MM_IO_W, &vi }, // VI Vertical Interrupt F0004E WO
{ 0xF00050, 0xF00051, MM_IO_W, &pit0 }, // PIT[0-1] Programmable Interrupt Timer F00050-52 WO
{ 0xF00052, 0xF00053, MM_IO_W, &pit1 },
{ 0xF00054, 0xF00055, MM_IO_W, &heq }, // *HEQ Horizontal Equalization End F00054 WO
{ 0xF00058, 0xF0005B, MM_IO_W, &bg }, // BG Background Colour F00058 WO
{ 0xF000E0, 0xF000E1, MM_IO, &int1 }, // INT1 CPU Interrupt Control Register F000E0 RW
{ 0xF000E2, 0xF000E3, MM_IO_W, &int2 }, // INT2 CPU Interrupt Resume Register F000E2 WO
//Some of these RAM spaces may be 16- or 32-bit only... in which case, we need
//to cast appropriately (in memory.cpp, that is)...
{ 0xF00400, 0xF005FF, MM_RAM, clut }, // CLUT Colour Look-Up Table F00400-7FE RW
{ 0xF00600, 0xF007FF, MM_RAM, clut },
{ 0xF00800, 0xF01D9F, MM_RAM, lbuf }, // LBUF Line Buffer F00800-1D9E RW
//Need high speed RAM interface for GPU & DSP (we have it now...)
// GPU REGISTERS
{ 0xF02100, 0xF02103, MM_IO, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
{ 0xF02104, 0xF02107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
{ 0xF02108, 0xF0210B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
{ 0xF0210C, 0xF0210F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
{ 0xF02110, 0xF02113, MM_IO, &g_pc }, // G_PC GPU Program Counter F02110 RW
{ 0xF02114, 0xF02117, MM_IO, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
{ 0xF02118, 0xF0211B, MM_IO, &g_hidata }, // G_HIDATA High Data Register F02118 RW
{ 0xF0211C, 0xF0211F, MM_IO, &g_remain, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
// G_DIVCTRL Divide Unit Control F0211C WO
{ 0xF03000, 0xF03FFF, MM_RAM, gpuRAM },
// BLITTER REGISTERS
{ 0xF02200, 0xF02203, MM_IO_W, &a1_base }, // A1_BASE A1 Base Register F02200 WO
{ 0xF02204, 0xF02207, MM_IO, &a1_pixel, &a1_flags }, // A1_FLAGS Flags Register F02204 WO
{ 0xF02208, 0xF0220B, MM_IO_W, &a1_clip }, // A1_CLIP A1 Clipping Size F02208 WO
{ 0xF0220C, 0xF0220F, MM_IO_W, &a1_pixel }, // A1_PIXEL A1 Pixel Pointer F0220C WO
// F02204 RO
{ 0xF02210, 0xF02213, MM_IO_W, &a1_step }, // A1_STEP A1 Step Value F02210 WO
{ 0xF02214, 0xF02217, MM_IO_W, &a1_fstep }, // A1_FSTEP A1 Step Fraction Value F02214 WO
{ 0xF02218, 0xF0221B, MM_IO, &a1_fpixel }, // A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
{ 0xF0221C, 0xF0221F, MM_IO_W, &a1_inc }, // A1_INC A1 Increment F0221C WO
{ 0xF02220, 0xF02223, MM_IO_W, &a1_finc }, // A1_FINC A1 Increment Fraction F02220 WO
{ 0xF02224, 0xF02227, MM_IO_W, &a2_base }, // A2_BASE A2 Base Register F02224 WO
{ 0xF02228, 0xF0222B, MM_IO_W, &a2_flags }, // A2_FLAGS A2 Flags Register F02228 WO
{ 0xF0222C, 0xF0222F, MM_IO, &a2_pixel, &a2_mask }, // A2_MASK A2 Window Mask F0222C WO
{ 0xF02230, 0xF02233, MM_IO_W, &a2_pixel }, // A2_PIXEL A2 Pixel Pointer F02230 WO
// F0222C RO
{ 0xF02234, 0xF02237, MM_IO_W, &a2_step }, // A2_STEP A2 Step Value F02234 WO
{ 0xF02238, 0xF0223B, MM_IO, &b_cmd }, // B_CMD Command/Status Register F02238 RW
{ 0xF0223C, 0xF0223F, MM_IO_W, &b_count }, // B_COUNT Counters Register F0223C WO
{ 0xF02240, 0xF02247, MM_IO_W, &b_srcd }, // B_SRCD Source Data Register F02240 WO
{ 0xF02248, 0xF0224F, MM_IO_W, &b_dstd }, // B_DSTD Destination Data Register F02248 WO
{ 0xF02250, 0xF02258, MM_IO_W, &b_dstz }, // B_DSTZ Destination Z Register F02250 WO
{ 0xF02258, 0xF0225F, MM_IO_W, &b_srcz1 }, // B_SRCZ1 Source Z Register 1 F02258 WO
{ 0xF02260, 0xF02267, MM_IO_W, &b_srcz2 }, // B_SRCZ2 Source Z Register 2 F02260 WO
{ 0xF02268, 0xF0226F, MM_IO_W, &b_patd }, // B_PATD Pattern Data Register F02268 WO
{ 0xF02270, 0xF02273, MM_IO_W, &b_iinc }, // B_IINC Intensity Increment F02270 WO
{ 0xF02274, 0xF02277, MM_IO_W, &b_zinc }, // B_ZINC Z Increment F02274 WO
{ 0xF02278, 0xF0227B, MM_IO_W, &b_stop }, // B_STOP Collision Control F02278 WO
{ 0xF0227C, 0xF0227F, MM_IO_W, &b_i3 }, // B_I3 Intensity 3 F0227C WO
{ 0xF02280, 0xF02283, MM_IO_W, &b_i2 }, // B_I2 Intensity 2 F02280 WO
{ 0xF02284, 0xF02287, MM_IO_W, &b_i1 }, // B_I1 Intensity 1 F02284 WO
{ 0xF02288, 0xF0228B, MM_IO_W, &b_i0 }, // B_I0 Intensity 0 F02288 WO
{ 0xF0228C, 0xF0228F, MM_IO_W, &b_z3 }, // B_Z3 Z 3 F0228C WO
{ 0xF02290, 0xF02293, MM_IO_W, &b_z2 }, // B_Z2 Z 2 F02290 WO
{ 0xF02294, 0xF02297, MM_IO_W, &b_z1 }, // B_Z1 Z 1 F02294 WO
{ 0xF02298, 0xF0229B, MM_IO_W, &b_z0 }, // B_Z0 Z 0 F02298 WO
// JTRM sez ALL GPU address space is accessible from $8000 offset as "fast" 32-bit WO access
// Dunno if anything actually USED it tho... :-P
{ 0xF0A100, 0xF0A103, MM_IO_W, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
{ 0xF0A104, 0xF0A107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
{ 0xF0A108, 0xF0A10B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
{ 0xF0A10C, 0xF0A10F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
{ 0xF0A110, 0xF0A113, MM_IO_W, &g_pc }, // G_PC GPU Program Counter F02110 RW
{ 0xF0A114, 0xF0A117, MM_IO_W, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
{ 0xF0A118, 0xF0A11B, MM_IO_W, &g_hidata }, // G_HIDATA High Data Register F02118 RW
{ 0xF0A11C, 0xF0A11F, MM_IO_W, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
{ 0xF0B000, 0xF0BFFF, MM_IO_W, gpuRAM }, // "Fast" interface to GPU RAM
// JERRY REGISTERS
{ 0xF10000, 0xF10001, MM_IO_W, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10000 WO
{ 0xF10002, 0xF10003, MM_IO_W, &jpit2 }, // JPIT2 Timer 1 Divider F10002 WO
{ 0xF10004, 0xF10005, MM_IO_W, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F10004 WO
{ 0xF10006, 0xF10007, MM_IO_W, &jpit4 }, // JPIT4 Timer 2 Divider F10006 WO
{ 0xF10010, 0xF10011, MM_IO_W, &clk1 }, // *CLK1 Processor Clock Divider F10010 WO
{ 0xF10012, 0xF10013, MM_IO_W, &clk2 }, // *CLK2 Video Clock Divider F10012 WO
{ 0xF10014, 0xF10015, MM_IO_W, &clk3 }, // *CLK3 Chroma Clock Divider F10014 WO
{ 0xF10020, 0xF10021, MM_IO, &j_int }, // J_INT Interrup Control Register F10020 RW
{ 0xF10030, 0xF10031, MM_IO, &asidata }, // ASIDATA Asynchronous Serial Data F10030 RW
{ 0xF10032, 0xF10033, MM_IO, &asistat, &asictrl }, // ASICTRL Asynchronous Serial Control F10032 WO
// ASISTAT Asynchronous Serial Status F10032 RO
{ 0xF10034, 0xF10035, MM_IO, &asiclk }, // ASICLK Asynchronous Serial Interface Clock F10034 RW
{ 0xF10036, 0xF10037, MM_IO_R, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10036 RO
{ 0xF10038, 0xF10039, MM_IO_R, &jpit2 }, // JPIT2 Timer 1 Divider F10038 RO
{ 0xF1003A, 0xF1003B, MM_IO_R, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F1003A RO
{ 0xF1003C, 0xF1003D, MM_IO_R, &jpit4 }, // JPIT4 Timer 2 Divider F1003C RO
{ 0xF14000, 0xF14001, MM_IO, &joystick }, // JOYSTICK Joystick Register F14000 RW
{ 0xF14002, 0xF14003, MM_IO, &joybuts }, // JOYBUTS Button Register F14002 RW
// DSP REGISTERS
{ 0xF1A100, 0xF1A103, MM_IO, &d_flags }, // D_FLAGS DSP Flags Register F1A100 RW
{ 0xF1A104, 0xF1A107, MM_IO_W, &d_mtxc }, // D_MTXC DSP Matrix Control Register F1A104 WO
{ 0xF1A108, 0xF1A10B, MM_IO_W, &d_mtxa }, // D_MTXA DSP Matrix Address Register F1A108 WO
{ 0xF1A10C, 0xF1A10F, MM_IO_W, &d_end }, // D_END DSP Data Organization Register F1A10C WO
{ 0xF1A110, 0xF1A113, MM_IO, &d_pc }, // D_PC DSP Program Counter F1A110 RW
{ 0xF1A114, 0xF1A117, MM_IO, &d_ctrl }, // D_CTRL DSP Control/Status Register F1A114 RW
{ 0xF1A118, 0xF1A11B, MM_IO_W, &d_mod }, // D_MOD Modulo Instruction Mask F1A118 WO
{ 0xF1A11C, 0xF1A11F, MM_IO_W, &d_remain, &d_divctrl }, // D_REMAIN Divide Unit Remainder F1A11C RO
// D_DIVCTRL Divide Unit Control F1A11C WO
{ 0xF1A120, 0xF1A123, MM_IO_R, &d_machi }, // D_MACHI MAC High Result Bits F1A120 RO
{ 0xF1A148, 0xF1A149, MM_IO, &lrxd, &ltxd }, // LTXD Left Transmit Data F1A148 WO
// LRXD Left Receive Data F1A148 RO
// L_I2S Left I2S Serial Interface F1A148 RW
{ 0xF1A14C, 0xF1A14D, MM_IO, &rrxd, &rtxd }, // RTXD Right Transmit Data F1A14C WO
// RRXD Right Receive Data F1A14C RO
// R_I2S Right I2S Serial Interface F1A14C RW
{ 0xF1A150, 0xF1A150, MM_IO, &sstat, &sclk }, // SCLK Serial Clock Frequency F1A150 WO
// SSTAT Serial Status F1A150 RO
{ 0xF1A154, 0xF1A157, MM_IO_W, &smode }, // SMODE Serial Mode F1A154 WO
{ 0xF1B000, 0xF1CFFF, MM_RAM, dspRAM }, // F1B000-F1CFFF R/W xxxxxxxx xxxxxxxx Local DSP RAM
{ 0xF1D000, 0xF1DFFF, MM_ROM, waveTableROM },
// hi-speed interface for DSP??? Ain't no such thang...
{ 0xFFFFFF, 0xFFFFFF, MM_NOP } // End of memory address sentinel
};
#if 0
// Jaguar Memory map/handlers
uint32_t memoryMap[] = {
{ 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
{ 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
// Note that this is really memory mapped I/O region...
// { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
{ 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
{ 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
{ 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
{ 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
{ 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
{ 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
{ 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
{ 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
{ 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
{ 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
{ 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
{ 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
// { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
{ 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
{ 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
{ 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
{ 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
//What about LBUF writes???
{ 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
{ 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
{ 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
{ 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
/*
EEPROM:
{ 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
{ 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
{ 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
JOYSTICK:
{ 0xF14000, 0xF14003, MM_IO, joystickFoo }
0 = pad0/1 button values (4 bits each), RO(?)
1 = pad0/1 index value (4 bits each), WO
2 = unused, RO
3 = NTSC/PAL, certain button states, RO
JOYSTICK $F14000 Read/Write
15.....8 7......0
Read fedcba98 7654321q f-1 Signals J15 to J1
q Cartridge EEPROM output data
Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
0 = disable J7-J0 outputs
x don't care
m Audio mute
0 = Audio muted (reset state)
1 = Audio enabled
7-4 J7-J4 outputs (port 2)
3-0 J3-J0 outputs (port 1)
JOYBUTS $F14002 Read Only
15.....8 7......0
Read xxxxxxxx rrdv3210 x don't care
r Reserved
d Reserved
v 1 = NTSC Video hardware
0 = PAL Video hardware
3-2 Button inputs B3 & B2 (port 2)
1-0 Button inputs B1 & B0 (port 1)
J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1 Row 3 C3 Option # 9 6 3
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1 Row 2 C2 C 0 8 5 2
1 1 0 0
1 1 0 1 Row 1 C1 B * 7 4 1
1 1 1 0 Row 0 Pause A Up Down Left Right
1 1 1 1
0 bit read in any position means that button is pressed.
C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
*/
};
#endif
void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
{
}
void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
{
}
void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
{
}
void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
{
}
uint8_t MMURead8(uint32_t address, uint32_t who/*= UNKNOWN*/)
{
// Search for address in the memory map
// NOTE: This assumes that all entries are linear and sorted in ascending order!
MemDesc memory;
uint8_t byte = 0xFE;
uint32_t i = 0;
while (true)
{
if (address <= memoryMap[i].endAddr)
{
if (address >= memoryMap[i].startAddr)
{
memory = memoryMap[i];
break;
}
else
return 0xFF; // Wasn't found...
}
i++;
if (memoryMap[i].startAddr == 0xFFFFFF)
return 0xFF; // Exhausted the list, so bail!
}
uint32_t offset = address - memory.startAddr;
uint32_t size = memory.endAddr - memory.startAddr + 1;
uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
if (memory.type == MM_RAM || memory.type == MM_ROM)
{
byte = ((uint8_t *)memory.readFunc)[offset];
}
else if (memory.type == MM_IO_R || memory.type == MM_IO)
{
// Problem here: We don't know yet how wide the function is, so we don't know
// how to properly cast it. We COULD ignore the problem by passing in/receiving
// 64-bits of data and letting the function make heads or tails of it, but we
// still have the problem of, say, taking a byte from a 32-bit value.
/*
We can do like so:
uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
size = memory.endAddr - memory.startAddr + 1;
byte = (returnValFromFunc >> byteShift[offset]) & 0xFF;
Let's see, will this work depending on the endianess?
uint32_t dword
accessing it like so:
((uint8_t *)dword &)[0] --> should give us high byte
but if we assign it directly...
dword = 0x12345678 --> becomes 78 56 34 12 in memory, ptr[0] will be 78 in LE!
dword = 0x12345678 --> becomes 12 34 56 78 in memory, ptr[0] will be 12 in BE!
So we're in danger if we use the variables directly! We'd need something like
#define ENDIAN_SAFE_16(x) swap lo & hi bytes on LE systems
#define ENDIAN_SAFE_16(x) do nothing on BE systems
Then, if we want to use a jaguar variable, we need to cast it like so:
uint16_t my_vbb = ENDIAN_SAFE_16(vbb);
We have something like this already in jaguar.h, since we treat I/O spaces like
contiguous memory anyway... For reference:
// Some handy macros to help converting native endian to big endian (jaguar native)
// & vice versa
#define SET64(r, a, v) r[(a)] = ((v) & 0xFF00000000000000) >> 56, r[(a)+1] = ((v) & 0x00FF000000000000) >> 48, \
r[(a)+2] = ((v) & 0x0000FF0000000000) >> 40, r[(a)+3] = ((v) & 0x000000FF00000000) >> 32, \
r[(a)+4] = ((v) & 0xFF000000) >> 24, r[(a)+5] = ((v) & 0x00FF0000) >> 16, \
r[(a)+6] = ((v) & 0x0000FF00) >> 8, r[(a)+7] = (v) & 0x000000FF
#define GET64(r, a) (((uint64)r[(a)] << 56) | ((uint64)r[(a)+1] << 48) | \
((uint64)r[(a)+2] << 40) | ((uint64)r[(a)+3] << 32) | \
((uint64)r[(a)+4] << 24) | ((uint64)r[(a)+5] << 16) | \
((uint64)r[(a)+6] << 8) | (uint64)r[(a)+7])
#define SET32(r, a, v) r[(a)] = ((v) & 0xFF000000) >> 24, r[(a)+1] = ((v) & 0x00FF0000) >> 16, \
r[(a)+2] = ((v) & 0x0000FF00) >> 8, r[(a)+3] = (v) & 0x000000FF
#define GET32(r, a) ((r[(a)] << 24) | (r[(a)+1] << 16) | (r[(a)+2] << 8) | r[(a)+3])
#define SET16(r, a, v) r[(a)] = ((v) & 0xFF00) >> 8, r[(a)+1] = (v) & 0xFF
#define GET16(r, a) ((r[(a)] << 8) | r[(a)+1])
*/
// Confused? Let me enlighten... What we're doing here is casting
// data1 as a pointer to a function which returns a Window pointer and
// which takes no parameters (the "(Window *(*)(void))" part), then
// derefencing it (the "*" in front of that) in order to call the
// function that it points to. Clear as mud? Yeah, I hate function
// pointers too, but what else are you gonna do?
// mainWindow = (*(Window *(*)(void))event.user.data1)();
// uint32_t retVal = (*(uint32(*)(uint32))memory.readFunc)(offset);
//#define FUNC_CAST(x) (*(uint32(*)(uint32))x)
// uint32_t retVal = FUNC_CAST(memory.readFunc)(offset);
#define FUNC_CAST(retVal, function, params) (*(retVal(*)(params))function)
uint64_t retVal = FUNC_CAST(uint64_t, memory.readFunc, uint32_t)(offset);
byte = (retVal >> byteShift[offset]) & 0xFF;
}
else if (memory.type == MM_IO_W)
{
byte = 0xFF; // Write only, what do we return? A fixed value?
}
return byte;
}
uint16_t MMURead16(uint32_t address, uint32_t who/*= UNKNOWN*/)
{
return 0;
}
uint32_t MMURead32(uint32_t address, uint32_t who/*= UNKNOWN*/)
{
return 0;
}
uint64_t MMURead64(uint32_t address, uint32_t who/*= UNKNOWN*/)
{
return 0;
}

View File

@ -1,24 +0,0 @@
//
// mmu.h
//
// Jaguar Memory Manager Unit
//
// by James L. Hammons
//
#ifndef __MMU_H__
#define __MMU_H__
//#include "types.h"
#include "memory.h"
void MMUWrite8(uint32_t address, uint8_t data, uint32_t who = UNKNOWN);
void MMUWrite16(uint32_t address, uint16_t data, uint32_t who = UNKNOWN);
void MMUWrite32(uint32_t address, uint32_t data, uint32_t who = UNKNOWN);
void MMUWrite64(uint32_t address, uint64_t data, uint32_t who = UNKNOWN);
uint8_t MMURead8(uint32_t address, uint32_t who = UNKNOWN);
uint16_t MMURead16(uint32_t address, uint32_t who = UNKNOWN);
uint32_t MMURead32(uint32_t address, uint32_t who = UNKNOWN);
uint64_t MMURead64(uint32_t address, uint32_t who = UNKNOWN);
#endif // __MMU_H__

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,4 @@
#include "settings.h"
// Global variables
VJSettings vjs;

View File

@ -5,66 +5,18 @@
#ifndef __SETTINGS_H__
#define __SETTINGS_H__
#define MAX_PATH 69
// MAX_PATH isn't defined in stdlib.h on *nix, so we do it here...
#ifdef __GCCUNIX__
#include <limits.h>
#define MAX_PATH _POSIX_PATH_MAX
#else
#include <stdlib.h> // for MAX_PATH on MinGW/Darwin
// Kludge for Win64
#ifndef MAX_PATH
#define MAX_PATH _MAX_PATH // Urgh.
#endif
#endif
#include <stdint.h>
// Settings struct
struct VJSettings
{
bool useJoystick;
int32_t joyport; // Joystick port
bool hardwareTypeNTSC; // Set to false for PAL
bool hardwareTypeNTSC;
bool useJaguarBIOS;
bool GPUEnabled;
bool DSPEnabled;
bool usePipelinedDSP;
bool fullscreen;
bool useOpenGL;
uint32_t glFilter;
bool hardwareTypeAlpine;
bool audioEnabled;
uint32_t frameSkip;
uint32_t renderType;
bool allowWritesToROM;
uint32_t biosType;
bool useFastBlitter;
// Keybindings in order of U, D, L, R, C, B, A, Op, Pa, 0-9, #, *
uint32_t p1KeyBindings[21];
uint32_t p2KeyBindings[21];
// Paths
char ROMPath[MAX_PATH];
char jagBootPath[MAX_PATH];
char CDBootPath[MAX_PATH];
char EEPROMPath[MAX_PATH];
char alpineROMPath[MAX_PATH];
char absROMPath[MAX_PATH];
};
// Render types
enum { RT_NORMAL = 0, RT_TV = 1 };
// BIOS types
enum { BT_K_SERIES, BT_M_SERIES, BT_STUBULATOR_1, BT_STUBULATOR_2 };
// Exported variables
extern VJSettings vjs;

View File

@ -1,25 +0,0 @@
//
// state.cpp: VJ machine state save/load support
//
// by James Hammons
// (C) 2010 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
//
#include "state.h"
bool SaveState(void)
{
return false;
}
bool LoadState(void)
{
return false;
}

View File

@ -1,13 +0,0 @@
//
// state.h: Machine state save/load support
//
// by James L. Hammons
//
#ifndef __STATE_H__
#define __STATE_H__
bool SaveState(void);
bool LoadState(void);
#endif // __STATE_H__

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,6 @@
#define VIDEO_MODE_16BPP_DIRECT 2
#define VIDEO_MODE_16BPP_RGB 3
// Virtual screen size stuff
// NB: This virtual width is for PWIDTH = 4
//#define VIRTUAL_SCREEN_WIDTH 320
//was:340, 330
#define VIRTUAL_SCREEN_WIDTH 326
#define VIRTUAL_SCREEN_HEIGHT_NTSC 240
#define VIRTUAL_SCREEN_HEIGHT_PAL 256

View File

@ -1,274 +0,0 @@
//
// Universal Header for Jaguar carts
//
// (C) 2011 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 06/28/2011 Created this file ;-)
//
//
// This file was automagically generated by bin2c (by James Hammons)
//
unsigned char universalCartHeader[0x2000] = {
0xF6, 0x42, 0x23, 0x3C, 0x0D, 0xAC, 0x1D, 0x8D, 0xB0, 0x23, 0x71, 0x53, 0xBE, 0x87, 0x11, 0x17, 0x98, 0x27, 0x04, 0x26, 0x22, 0xC1, 0xBE, 0x1F, 0x79, 0x30, 0xDB, 0x90, 0xC6, 0xC8, 0x13, 0xF8,
0x09, 0x41, 0x99, 0x78, 0x51, 0xCB, 0xFF, 0x8C, 0xF9, 0x7F, 0x75, 0xF0, 0x6B, 0x0E, 0xFE, 0x13, 0x2D, 0x84, 0xD8, 0x21, 0xE5, 0x91, 0xD4, 0x01, 0x3F, 0x23, 0x5E, 0x13, 0xAE, 0xF2, 0x2F, 0xEF,
0x6C, 0x09, 0xD8, 0x06, 0x9F, 0x39, 0x27, 0x8F, 0x6D, 0x4F, 0x03, 0xD3, 0xD9, 0x84, 0x3D, 0xEA, 0xAB, 0xB7, 0x48, 0xF1, 0xE6, 0x98, 0x51, 0x27, 0xF0, 0x6E, 0x94, 0x0E, 0x90, 0x92, 0xC8, 0xF4,
0x50, 0x3B, 0x46, 0x58, 0x08, 0x23, 0xE0, 0x4B, 0xD2, 0x3C, 0x1C, 0xC5, 0x30, 0x6B, 0x11, 0x24, 0xFA, 0xC6, 0x78, 0x29, 0xD1, 0x53, 0x5A, 0x64, 0xE0, 0x91, 0x5A, 0x16, 0xEC, 0xD9, 0x87, 0xC4,
0xD8, 0x2D, 0x16, 0x98, 0x6A, 0x85, 0x29, 0x01, 0xF7, 0x25, 0xFB, 0xF6, 0xF9, 0xC1, 0x0F, 0x38, 0xA7, 0xB3, 0x9B, 0x1E, 0xC6, 0x19, 0x69, 0x1E, 0x6B, 0x05, 0x01, 0x77, 0xD0, 0xCD, 0x09, 0xF0,
0xA7, 0x0F, 0xAA, 0x76, 0x24, 0x92, 0x26, 0x28, 0xEF, 0x72, 0xE4, 0x86, 0x41, 0x3B, 0x83, 0x22, 0x3C, 0x07, 0x4F, 0x67, 0x0B, 0xB6, 0x27, 0x5F, 0x7C, 0xD7, 0xEC, 0x52, 0xF6, 0xBF, 0x44, 0xEE,
0x9C, 0x6B, 0x33, 0x0A, 0x36, 0xBE, 0x4C, 0xEB, 0x3E, 0x34, 0xE4, 0x3A, 0xFD, 0xF6, 0x75, 0x87, 0xB1, 0xED, 0xF6, 0x51, 0x72, 0x06, 0x99, 0x28, 0x10, 0x71, 0xD7, 0x44, 0x7E, 0xDE, 0x0F, 0x96,
0xF3, 0x84, 0x01, 0xFF, 0x59, 0x71, 0x33, 0xB2, 0x18, 0x55, 0x4E, 0x56, 0x43, 0x4C, 0xA6, 0xE9, 0x72, 0xE2, 0x4A, 0x9F, 0x04, 0x9A, 0x87, 0xF1, 0x73, 0x92, 0x86, 0x3E, 0x80, 0x07, 0x55, 0x1C,
0xCE, 0x57, 0x76, 0xD3, 0x1C, 0xC9, 0x43, 0x82, 0x7D, 0xCF, 0x19, 0x49, 0x6E, 0xFB, 0x19, 0x60, 0x74, 0x72, 0xD6, 0x90, 0x37, 0x81, 0x78, 0xFB, 0x10, 0x01, 0x7E, 0xE5, 0x5C, 0xB7, 0x81, 0x88,
0xE2, 0xEB, 0x07, 0xA2, 0x75, 0x10, 0x35, 0x11, 0xCB, 0xE9, 0x2E, 0x75, 0x39, 0x79, 0x3E, 0x76, 0xB8, 0xF8, 0x5A, 0x88, 0xFF, 0x6C, 0x77, 0x07, 0xBD, 0xCE, 0x05, 0xF6, 0xD2, 0x29, 0x03, 0x5F,
0xBE, 0x04, 0x51, 0xD8, 0xF7, 0x15, 0x07, 0xF9, 0xBE, 0xD9, 0x12, 0x27, 0x3D, 0xE0, 0xF2, 0xC0, 0x20, 0x2F, 0xBF, 0xA6, 0xBA, 0x76, 0x6B, 0x69, 0x8F, 0x05, 0x41, 0x01, 0x4D, 0x9E, 0xF0, 0x79,
0x87, 0xAF, 0x8C, 0xDB, 0xFB, 0x30, 0xE3, 0xC9, 0x51, 0x29, 0x2A, 0x3E, 0x91, 0x3A, 0xE0, 0x52, 0xEE, 0x45, 0xE6, 0x79, 0x5A, 0x3D, 0x92, 0x12, 0x12, 0x1F, 0x6C, 0x62, 0xA2, 0x9B, 0x99, 0xAC,
0xD8, 0x32, 0xF3, 0xF4, 0xCF, 0x4A, 0x09, 0x56, 0x5A, 0x0D, 0x76, 0x84, 0xE1, 0x5A, 0xFF, 0x23, 0x69, 0xD2, 0x03, 0xE6, 0x2E, 0x47, 0xC6, 0x54, 0x09, 0xA3, 0x47, 0x6E, 0x5B, 0x5A, 0xA1, 0xE8,
0x25, 0xC5, 0xA5, 0x61, 0x64, 0xB8, 0x82, 0xC8, 0x17, 0x1A, 0x8A, 0xC8, 0x1D, 0xEC, 0x49, 0x94, 0x1E, 0x00, 0xA0, 0x23, 0x39, 0x35, 0xF3, 0xB2, 0xA7, 0x54, 0x47, 0x90, 0xCB, 0x52, 0x40, 0x78,
0xA3, 0x33, 0x88, 0xEB, 0x23, 0x0A, 0x29, 0x1B, 0xC7, 0xB7, 0xE2, 0x10, 0x75, 0x9F, 0x27, 0x5B, 0xE3, 0x00, 0x63, 0x6F, 0x12, 0x55, 0x20, 0x0B, 0x44, 0xB2, 0x67, 0xEF, 0x74, 0x15, 0x17, 0xBB,
0x7B, 0xB7, 0x95, 0x78, 0xC0, 0xFE, 0x2C, 0x99, 0xDD, 0xFF, 0xDC, 0xFC, 0x43, 0xAF, 0x42, 0xC2, 0x27, 0x8A, 0x53, 0x9E, 0x62, 0x0B, 0x12, 0x8E, 0xD3, 0x5E, 0x76, 0x0F, 0x2B, 0x9D, 0x6D, 0x8D,
0x28, 0x44, 0xA0, 0xB4, 0xB1, 0x22, 0xA8, 0x9D, 0x2C, 0x01, 0x90, 0x04, 0xAB, 0x0D, 0x60, 0x29, 0x60, 0xD7, 0x49, 0x02, 0x24, 0x9E, 0x10, 0x1D, 0xE6, 0x1C, 0x58, 0xC9, 0xFC, 0x14, 0x97, 0x92,
0x23, 0x1E, 0x74, 0xDE, 0x23, 0xAF, 0xA7, 0xB6, 0xDB, 0x52, 0x78, 0xDA, 0x5E, 0x6C, 0x16, 0x6B, 0x36, 0x17, 0xBC, 0x01, 0x7F, 0x6A, 0x55, 0xA7, 0x7D, 0xC0, 0x60, 0xFD, 0x50, 0x72, 0x78, 0x62,
0x14, 0xFD, 0x06, 0xF7, 0x0F, 0x1E, 0x82, 0xCC, 0xFB, 0x0B, 0x62, 0x06, 0x78, 0x1D, 0x80, 0x0B, 0x55, 0xAE, 0xC9, 0x25, 0x61, 0x65, 0x88, 0xDB, 0x23, 0x0E, 0x0D, 0xFB, 0xD9, 0x3B, 0x41, 0x33,
0x85, 0xC8, 0x9F, 0x61, 0xBC, 0xC9, 0x17, 0x22, 0x29, 0x4E, 0x41, 0xCA, 0xA5, 0x4F, 0xDF, 0x7B, 0xF0, 0xB7, 0xC3, 0xA4, 0x93, 0xB2, 0xF2, 0xE7, 0x4D, 0x3B, 0x46, 0x21, 0x22, 0xD9, 0x50, 0x9F,
0x2E, 0x7F, 0x2B, 0xA3, 0xD2, 0xA1, 0x24, 0x68, 0xE4, 0xBF, 0x28, 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, 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, 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, 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, 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, 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, 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,
0x04, 0x04, 0x04, 0x04, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
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, 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, 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, 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, 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, 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, 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, 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, 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, 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
};

View File

@ -1,10 +0,0 @@
//
// Universal Header for Jaguar carts
//
#ifndef __UNIVERSALHDR_H__
#define __UNIVERSALHDR_H__
extern unsigned char universalCartHeader[];
#endif // __UNIVERSALHDR_H__

View File

@ -10,6 +10,8 @@
// JLH 01/16/2010 Created this log ;-)
//
#include "wavetable.h"
//
// In a real Jaguar, these are 16-bit values that are sign-extended to 32 bits.
// Each entry has 128 values (e.g., SINE goes from F1D200-F1D3FF)
@ -17,7 +19,7 @@
// NOTE: This can probably be converted to 32-bit table, since I don't think
// that unaligned access is allowed...
/*const*/ unsigned char waveTableROM[4096] =
const uint8_t waveTableROM[4096] =
{
0xFF, 0xFF, 0xC2, 0x01, 0xFF, 0xFF, 0xC4, 0x01, 0xFF, 0xFF, 0xC6, 0x01, 0xFF, 0xFF, 0xC8, 0x01,
0xFF, 0xFF, 0xCA, 0x01, 0xFF, 0xFF, 0xCC, 0x01, 0xFF, 0xFF, 0xCE, 0x01, 0xFF, 0xFF, 0xD0, 0x01,

View File

@ -11,7 +11,8 @@
#ifndef __WAVETABLE_H__
#define __WAVETABLE_H__
// How to preserve const-ness of this stuff without introducing tons of hairiness?
extern /*const*/ unsigned char waveTableROM[];
#include <stdint.h>
extern const uint8_t waveTableROM[];
#endif // __WAVETABLE_H__