more virtualjaguar cleanup, fix various bugs, have the DSP run more in sync with the CPU/GPU (makes Zoop boot, Doom is much less laggy, various missing sound issues are no longer present)

This commit is contained in:
CasualPokePlayer 2022-10-02 06:48:14 -07:00
parent 2e5c62f632
commit 71f2676ad8
43 changed files with 881 additions and 1952 deletions

Binary file not shown.

View File

@ -1,15 +1,14 @@
#include "jaguar.h" #include "jaguar.h"
#include "file.h" #include "rom.h"
#include "settings.h" #include "settings.h"
#include "memory.h" #include "memory.h"
#include "tom.h" #include "tom.h"
#include "gpu.h" #include "gpu.h"
#include "dsp.h" #include "dsp.h"
#include "dac.h"
#include "joystick.h" #include "joystick.h"
#include "m68000/m68kinterface.h" #include "m68000/m68kinterface.h"
#include "blip_buf.h"
#include <emulibc.h> #include <emulibc.h>
#include <waterboxcore.h> #include <waterboxcore.h>
@ -34,22 +33,11 @@ struct BizSettings
u8 useFastBlitter; u8 useFastBlitter;
}; };
void SoundCallback(u16 * buffer, int length);
static u16* soundBuf;
static blip_t* blipL;
static blip_t* blipR;
static s16 latchL, latchR;
static void InitCommon(BizSettings* bizSettings) static void InitCommon(BizSettings* bizSettings)
{ {
vjs.hardwareTypeNTSC = bizSettings->hardwareTypeNTSC; vjs.hardwareTypeNTSC = bizSettings->hardwareTypeNTSC;
vjs.useJaguarBIOS = bizSettings->useJaguarBIOS; vjs.useJaguarBIOS = bizSettings->useJaguarBIOS;
vjs.useFastBlitter = bizSettings->useFastBlitter; vjs.useFastBlitter = bizSettings->useFastBlitter;
soundBuf = alloc_invisible<u16>(2048);
blipL = blip_new(1024);
blipR = blip_new(1024);
blip_set_rates(blipL, 48000, 44100);
blip_set_rates(blipR, 48000, 44100);
JaguarInit(); JaguarInit();
} }
@ -57,9 +45,9 @@ EXPORT bool Init(BizSettings* bizSettings, u8* boot, u8* rom, u32 sz)
{ {
InitCommon(bizSettings); InitCommon(bizSettings);
if (!JaguarLoadFile(rom, sz)) if (!JaguarLoadROM(rom, sz))
{ {
if (!AlpineLoadFile(rom, sz)) if (!AlpineLoadROM(rom, sz))
{ {
return false; return false;
} }
@ -68,7 +56,7 @@ EXPORT bool Init(BizSettings* bizSettings, u8* boot, u8* rom, u32 sz)
} }
else else
{ {
vjs.hardwareTypeAlpine = ParseFileType(rom, sz) == JST_ALPINE; vjs.hardwareTypeAlpine = ParseROMType(rom, sz) == JST_ALPINE;
} }
SET32(jaguarMainRAM, 0, 0x00200000); SET32(jaguarMainRAM, 0, 0x00200000);
@ -93,7 +81,7 @@ EXPORT void InitWithCd(BizSettings* bizSettings, u8* boot, u8* memtrack)
InitCommon(bizSettings); InitCommon(bizSettings);
if (memtrack) if (memtrack)
{ {
JaguarLoadFile(memtrack, 0x20000); JaguarLoadROM(memtrack, 0x20000);
} }
vjs.hardwareTypeAlpine = false; vjs.hardwareTypeAlpine = false;
@ -153,6 +141,7 @@ extern u8 gpu_ram_8[0x1000];
extern u8 dsp_ram_8[0x2000]; extern u8 dsp_ram_8[0x2000];
extern u8 cdRam[0x100]; extern u8 cdRam[0x100];
extern u8 blitter_ram[0x100]; extern u8 blitter_ram[0x100];
extern u8 tomRam8[0x4000];
extern u8 jerry_ram_8[0x10000]; extern u8 jerry_ram_8[0x10000];
static u8 unmapped; static u8 unmapped;
@ -166,11 +155,11 @@ static inline u8* GetSysBusPtr(u64 address)
case 0x800000 ... 0xDFFEFF: return &jaguarMainROM[address - 0x800000]; case 0x800000 ... 0xDFFEFF: return &jaguarMainROM[address - 0x800000];
case 0xDFFF00 ... 0xDFFFFF: return &cdRam[address & 0xFF]; case 0xDFFF00 ... 0xDFFFFF: return &cdRam[address & 0xFF];
case 0xE00000 ... 0xE3FFFF: return &jagMemSpace[address]; case 0xE00000 ... 0xE3FFFF: return &jagMemSpace[address];
case 0xF00000 ... 0xF021FF: return &TOMGetRamPointer()[address & 0x3FFF]; case 0xF00000 ... 0xF021FF: return &tomRam8[address & 0x3FFF];
case 0xF02200 ... 0xF0229F: return &blitter_ram[address & 0xFF]; case 0xF02200 ... 0xF0229F: return &blitter_ram[address & 0xFF];
case 0xF022A0 ... 0xF02FFF: return &TOMGetRamPointer()[address & 0x3FFF]; case 0xF022A0 ... 0xF02FFF: return &tomRam8[address & 0x3FFF];
case 0xF03000 ... 0xF03FFF: return &gpu_ram_8[address & 0xFFF]; case 0xF03000 ... 0xF03FFF: return &gpu_ram_8[address & 0xFFF];
case 0xF04000 ... 0xF0FFFF: return &TOMGetRamPointer()[address & 0x3FFF]; case 0xF04000 ... 0xF0FFFF: return &tomRam8[address & 0x3FFF];
case 0xF10000 ... 0xF1AFFF: return &jerry_ram_8[address & 0xFFFF]; case 0xF10000 ... 0xF1AFFF: return &jerry_ram_8[address & 0xFFFF];
case 0xF1B000 ... 0xF1CFFF: return &dsp_ram_8[address - 0xF1B000]; case 0xF1B000 ... 0xF1CFFF: return &dsp_ram_8[address - 0xF1B000];
case 0xF1D000 ... 0xF1FFFF: return &jerry_ram_8[address & 0xFFFF]; case 0xF1D000 ... 0xF1FFFF: return &jerry_ram_8[address & 0xFFFF];
@ -228,9 +217,9 @@ EXPORT void GetMemoryAreas(MemoryArea* m)
m[3].Size = sizeof(dsp_ram_8); m[3].Size = sizeof(dsp_ram_8);
m[3].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN; m[3].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN;
m[4].Data = TOMGetRamPointer(); m[4].Data = tomRam8;
m[4].Name = "TOM RAM"; m[4].Name = "TOM RAM";
m[4].Size = 0x4000; m[4].Size = sizeof(tomRam8);
m[4].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN; m[4].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN;
m[5].Data = jerry_ram_8; m[5].Data = jerry_ram_8;
@ -261,56 +250,32 @@ EXPORT void GetMemoryAreas(MemoryArea* m)
struct MyFrameInfo : public FrameInfo struct MyFrameInfo : public FrameInfo
{ {
u32 player1, player2; u32 Player1, Player2;
bool reset; bool Reset;
}; };
bool lagged; bool lagged;
EXPORT void FrameAdvance(MyFrameInfo* f) EXPORT void FrameAdvance(MyFrameInfo* f)
{ {
if (f->reset) if (f->Reset)
{ {
JaguarReset(); JaguarReset();
} }
for (u32 i = 0; i < 21; i++) for (u32 i = 0; i < 21; i++)
{ {
joypad0Buttons[i] = (f->player1 >> i) & 1; joypad0Buttons[i] = (f->Player1 >> i) & 1;
joypad1Buttons[i] = (f->player2 >> i) & 1; joypad1Buttons[i] = (f->Player2 >> i) & 1;
} }
lagged = true; lagged = true;
JaguarExecuteNew(); DACResetBuffer(f->SoundBuffer);
JaguarAdvance();
TOMBlit(f->VideoBuffer, f->Width, f->Height); TOMBlit(f->VideoBuffer, f->Width, f->Height);
f->Samples = DACResetBuffer(NULL);
u32 samples = 48000 / (vjs.hardwareTypeNTSC ? 60 : 50);
SoundCallback(soundBuf, samples * 4);
s16* sb = reinterpret_cast<s16*>(soundBuf);
for (u32 i = 0; i < samples; i++)
{
s16 l = *sb++;
if (latchL != l)
{
blip_add_delta(blipL, i, latchL - l);
latchL = l;
}
s16 r = *sb++;
if (latchR != r)
{
blip_add_delta(blipR, i, latchR - r);
latchR = r;
}
}
blip_end_frame(blipL, samples);
blip_end_frame(blipR, samples);
f->Samples = blip_samples_avail(blipL);
blip_read_samples(blipL, f->SoundBuffer + 0, f->Samples, 1);
blip_read_samples(blipR, f->SoundBuffer + 1, f->Samples, 1);
f->Lagged = lagged; f->Lagged = lagged;
} }

View File

@ -1,344 +0,0 @@
/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
#include "blip_buf.h"
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
/* Library Copyright (C) 2003-2009 Shay Green. This library is free software;
you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#if defined (BLARGG_TEST) && BLARGG_TEST
#include "blargg_test.h"
#endif
/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000.
Avoids constants that don't fit in 32 bits. */
#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF
typedef unsigned long fixed_t;
enum { pre_shift = 32 };
#elif defined(ULLONG_MAX)
typedef unsigned long long fixed_t;
enum { pre_shift = 32 };
#else
typedef unsigned fixed_t;
enum { pre_shift = 0 };
#endif
enum { time_bits = pre_shift + 20 };
static fixed_t const time_unit = (fixed_t) 1 << time_bits;
enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */
enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */
enum { half_width = 8 };
enum { buf_extra = half_width*2 + end_frame_extra };
enum { phase_bits = 5 };
enum { phase_count = 1 << phase_bits };
enum { delta_bits = 15 };
enum { delta_unit = 1 << delta_bits };
enum { frac_bits = time_bits - pre_shift };
/* We could eliminate avail and encode whole samples in offset, but that would
limit the total buffered samples to blip_max_frame. That could only be
increased by decreasing time_bits, which would reduce resample ratio accuracy.
*/
/** Sample buffer that resamples to output rate and accumulates samples
until they're read out */
struct blip_t
{
fixed_t factor;
fixed_t offset;
int avail;
int size;
int integrator;
};
typedef int buf_t;
/* probably not totally portable */
#define SAMPLES( buf ) ((buf_t*) ((buf) + 1))
/* Arithmetic (sign-preserving) right shift */
#define ARITH_SHIFT( n, shift ) \
((n) >> (shift))
enum { max_sample = +32767 };
enum { min_sample = -32768 };
#define CLAMP( n ) \
{\
if ( (short) n != n )\
n = ARITH_SHIFT( n, 16 ) ^ max_sample;\
}
static void check_assumptions( void )
{
int n;
#if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF
#error "int must be at least 32 bits"
#endif
assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */
n = max_sample * 2;
CLAMP( n );
assert( n == max_sample );
n = min_sample * 2;
CLAMP( n );
assert( n == min_sample );
assert( blip_max_ratio <= time_unit );
assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
}
blip_t* blip_new( int size )
{
blip_t* m;
assert( size >= 0 );
m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
if ( m )
{
m->factor = time_unit / blip_max_ratio;
m->size = size;
blip_clear( m );
check_assumptions();
}
return m;
}
void blip_delete( blip_t* m )
{
if ( m != NULL )
{
/* Clear fields in case user tries to use after freeing */
memset( m, 0, sizeof *m );
free( m );
}
}
void blip_set_rates( blip_t* m, double clock_rate, double sample_rate )
{
double factor = time_unit * sample_rate / clock_rate;
m->factor = (fixed_t) factor;
/* Fails if clock_rate exceeds maximum, relative to sample_rate */
assert( 0 <= factor - m->factor && factor - m->factor < 1 );
/* Avoid requiring math.h. Equivalent to
m->factor = (int) ceil( factor ) */
if ( m->factor < factor )
m->factor++;
/* At this point, factor is most likely rounded up, but could still
have been rounded down in the floating-point calculation. */
}
void blip_clear( blip_t* m )
{
/* We could set offset to 0, factor/2, or factor-1. 0 is suitable if
factor is rounded up. factor-1 is suitable if factor is rounded down.
Since we don't know rounding direction, factor/2 accommodates either,
with the slight loss of showing an error in half the time. Since for
a 64-bit factor this is years, the halving isn't a problem. */
m->offset = m->factor / 2;
m->avail = 0;
m->integrator = 0;
memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) );
}
int blip_clocks_needed( const blip_t* m, int samples )
{
fixed_t needed;
/* Fails if buffer can't hold that many more samples */
assert( samples >= 0 && m->avail + samples <= m->size );
needed = (fixed_t) samples * time_unit;
if ( needed < m->offset )
return 0;
return (needed - m->offset + m->factor - 1) / m->factor;
}
void blip_end_frame( blip_t* m, unsigned t )
{
fixed_t off = t * m->factor + m->offset;
m->avail += off >> time_bits;
m->offset = off & (time_unit - 1);
/* Fails if buffer size was exceeded */
assert( m->avail <= m->size );
}
int blip_samples_avail( const blip_t* m )
{
return m->avail;
}
static void remove_samples( blip_t* m, int count )
{
buf_t* buf = SAMPLES( m );
int remain = m->avail + buf_extra - count;
m->avail -= count;
memmove( &buf [0], &buf [count], remain * sizeof buf [0] );
memset( &buf [remain], 0, count * sizeof buf [0] );
}
int blip_read_samples( blip_t* m, short out [], int count, int stereo )
{
assert( count >= 0 );
if ( count > m->avail )
count = m->avail;
if ( count )
{
int const step = stereo ? 2 : 1;
buf_t const* in = SAMPLES( m );
buf_t const* end = in + count;
int sum = m->integrator;
do
{
/* Eliminate fraction */
int s = ARITH_SHIFT( sum, delta_bits );
sum += *in++;
CLAMP( s );
*out = s;
out += step;
/* High-pass filter */
sum -= s << (delta_bits - bass_shift);
}
while ( in != end );
m->integrator = sum;
remove_samples( m, count );
}
return count;
}
/* Things that didn't help performance on x86:
__attribute__((aligned(128)))
#define short int
restrict
*/
/* Sinc_Generator( 0.9, 0.55, 4.5 ) */
static short const bl_step [phase_count + 1] [half_width] =
{
{ 43, -115, 350, -488, 1136, -914, 5861,21022},
{ 44, -118, 348, -473, 1076, -799, 5274,21001},
{ 45, -121, 344, -454, 1011, -677, 4706,20936},
{ 46, -122, 336, -431, 942, -549, 4156,20829},
{ 47, -123, 327, -404, 868, -418, 3629,20679},
{ 47, -122, 316, -375, 792, -285, 3124,20488},
{ 47, -120, 303, -344, 714, -151, 2644,20256},
{ 46, -117, 289, -310, 634, -17, 2188,19985},
{ 46, -114, 273, -275, 553, 117, 1758,19675},
{ 44, -108, 255, -237, 471, 247, 1356,19327},
{ 43, -103, 237, -199, 390, 373, 981,18944},
{ 42, -98, 218, -160, 310, 495, 633,18527},
{ 40, -91, 198, -121, 231, 611, 314,18078},
{ 38, -84, 178, -81, 153, 722, 22,17599},
{ 36, -76, 157, -43, 80, 824, -241,17092},
{ 34, -68, 135, -3, 8, 919, -476,16558},
{ 32, -61, 115, 34, -60, 1006, -683,16001},
{ 29, -52, 94, 70, -123, 1083, -862,15422},
{ 27, -44, 73, 106, -184, 1152,-1015,14824},
{ 25, -36, 53, 139, -239, 1211,-1142,14210},
{ 22, -27, 34, 170, -290, 1261,-1244,13582},
{ 20, -20, 16, 199, -335, 1301,-1322,12942},
{ 18, -12, -3, 226, -375, 1331,-1376,12293},
{ 15, -4, -19, 250, -410, 1351,-1408,11638},
{ 13, 3, -35, 272, -439, 1361,-1419,10979},
{ 11, 9, -49, 292, -464, 1362,-1410,10319},
{ 9, 16, -63, 309, -483, 1354,-1383, 9660},
{ 7, 22, -75, 322, -496, 1337,-1339, 9005},
{ 6, 26, -85, 333, -504, 1312,-1280, 8355},
{ 4, 31, -94, 341, -507, 1278,-1205, 7713},
{ 3, 35, -102, 347, -506, 1238,-1119, 7082},
{ 1, 40, -110, 350, -499, 1190,-1021, 6464},
{ 0, 43, -115, 350, -488, 1136, -914, 5861}
};
/* Shifting by pre_shift allows calculation using unsigned int rather than
possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient.
And by having pre_shift 32, a 32-bit platform can easily do the shift by
simply ignoring the low half. */
void blip_add_delta( blip_t* m, unsigned time, int delta )
{
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
int const phase_shift = frac_bits - phase_bits;
int phase = fixed >> phase_shift & (phase_count - 1);
short const* in = bl_step [phase];
short const* rev = bl_step [phase_count - phase];
int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1);
int delta2 = (delta * interp) >> delta_bits;
delta -= delta2;
/* Fails if buffer size was exceeded */
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
out [0] += in[0]*delta + in[half_width+0]*delta2;
out [1] += in[1]*delta + in[half_width+1]*delta2;
out [2] += in[2]*delta + in[half_width+2]*delta2;
out [3] += in[3]*delta + in[half_width+3]*delta2;
out [4] += in[4]*delta + in[half_width+4]*delta2;
out [5] += in[5]*delta + in[half_width+5]*delta2;
out [6] += in[6]*delta + in[half_width+6]*delta2;
out [7] += in[7]*delta + in[half_width+7]*delta2;
in = rev;
out [ 8] += in[7]*delta + in[7-half_width]*delta2;
out [ 9] += in[6]*delta + in[6-half_width]*delta2;
out [10] += in[5]*delta + in[5-half_width]*delta2;
out [11] += in[4]*delta + in[4-half_width]*delta2;
out [12] += in[3]*delta + in[3-half_width]*delta2;
out [13] += in[2]*delta + in[2-half_width]*delta2;
out [14] += in[1]*delta + in[1-half_width]*delta2;
out [15] += in[0]*delta + in[0-half_width]*delta2;
}
void blip_add_delta_fast( blip_t* m, unsigned time, int delta )
{
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1);
int delta2 = delta * interp;
/* Fails if buffer size was exceeded */
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
out [7] += delta * delta_unit - delta2;
out [8] += delta2;
}

View File

@ -1,72 +0,0 @@
/** \file
Sample buffer that resamples from input clock rate to output sample rate */
/* blip_buf 1.1.0 */
#ifndef BLIP_BUF_H
#define BLIP_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/** First parameter of most functions is blip_t*, or const blip_t* if nothing
is changed. */
typedef struct blip_t blip_t;
/** Creates new buffer that can hold at most sample_count samples. Sets rates
so that there are blip_max_ratio clocks per sample. Returns pointer to new
buffer, or NULL if insufficient memory. */
blip_t* blip_new( int sample_count );
/** Sets approximate input clock rate and output sample rate. For every
clock_rate input clocks, approximately sample_rate samples are generated. */
void blip_set_rates( blip_t*, double clock_rate, double sample_rate );
enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate,
clock_rate must not be greater than sample_rate*blip_max_ratio. */
blip_max_ratio = 1 << 20 };
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
void blip_clear( blip_t* );
/** Adds positive/negative delta into buffer at specified clock time. */
void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
/** Length of time frame, in clocks, needed to make sample_count additional
samples available. */
int blip_clocks_needed( const blip_t*, int sample_count );
enum { /** Maximum number of samples that can be generated from one time frame. */
blip_max_frame = 4000 };
/** Makes input clocks before clock_duration available for reading as output
samples. Also begins new time frame at clock_duration, so that clock time 0 in
the new time frame specifies the same clock as clock_duration in the old time
frame specified. Deltas can have been added slightly past clock_duration (up to
however many clocks there are in two output samples). */
void blip_end_frame( blip_t*, unsigned int clock_duration );
/** Number of buffered samples available for reading. */
int blip_samples_avail( const blip_t* );
/** Reads and removes at most 'count' samples and writes them to 'out'. If
'stereo' is true, writes output to every other element of 'out', allowing easy
interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
samples. Returns number of samples actually read. */
int blip_read_samples( blip_t*, short out [], int count, int stereo );
/** Frees buffer. No effect if NULL is passed. */
void blip_delete( blip_t* );
/* Deprecated */
typedef blip_t blip_buffer_t;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -31,7 +31,7 @@
uint8_t blitter_ram[0x100]; uint8_t blitter_ram[0x100];
void BlitterMidsummer2(void); static void BlitterMidsummer2(void);
#define REG(A) (((uint32_t)blitter_ram[(A)] << 24) | ((uint32_t)blitter_ram[(A)+1] << 16) \ #define REG(A) (((uint32_t)blitter_ram[(A)] << 24) | ((uint32_t)blitter_ram[(A)+1] << 16) \
| ((uint32_t)blitter_ram[(A)+2] << 8) | (uint32_t)blitter_ram[(A)+3]) | ((uint32_t)blitter_ram[(A)+2] << 8) | (uint32_t)blitter_ram[(A)+3])
@ -286,7 +286,7 @@ static int32_t a1_clip_x, a1_clip_y;
// //
// Generic blit handler // Generic blit handler
// //
void blitter_generic(uint32_t cmd) static void blitter_generic(uint32_t cmd)
{ {
uint32_t srcdata, srczdata, dstdata, dstzdata, writedata, inhibit; uint32_t srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
uint32_t bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07)); uint32_t bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
@ -654,7 +654,7 @@ void blitter_generic(uint32_t cmd)
WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF)); WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
} }
void blitter_blit(uint32_t cmd) static void blitter_blit(uint32_t cmd)
{ {
uint32_t pitchValue[4] = { 0, 1, 3, 2 }; uint32_t pitchValue[4] = { 0, 1, 3, 2 };
colour_index = 0; colour_index = 0;
@ -831,10 +831,6 @@ void BlitterReset(void)
memset(blitter_ram, 0x00, 0xA0); memset(blitter_ram, 0x00, 0xA0);
} }
void BlitterDone(void)
{
}
uint8_t BlitterReadByte(uint32_t offset, uint32_t who) uint8_t BlitterReadByte(uint32_t offset, uint32_t who)
{ {
offset &= 0xFF; offset &= 0xFF;
@ -958,34 +954,33 @@ void BlitterWriteLong(uint32_t offset, uint32_t data, uint32_t who)
BlitterWriteWord(offset + 2, data & 0xFFFF, who); BlitterWriteWord(offset + 2, data & 0xFFFF, who);
} }
void ADDRGEN(uint32_t &, uint32_t &, bool, bool, static void ADDRGEN(uint32_t &, uint32_t &, bool, bool,
uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t); uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t);
void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, static void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix, uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2, uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
uint32_t zinc, uint32_t zstep); uint32_t zinc, uint32_t zstep);
void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh); static void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh);
void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y, static void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y, int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst, int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
bool adda_yconst, bool addareg, bool suba_x, bool suba_y); bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y, static void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y); int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y);
void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel); static void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y); uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y);
void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite, static void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel, bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd, uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode, bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize, bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize,
uint64_t &srcz, uint64_t dstz, uint32_t zinc); uint64_t &srcz, uint64_t dstz, uint32_t zinc);
void COMP_CTRL(uint8_t &dbinh, bool &nowrite, static void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount, bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp); uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp);
void BlitterMidsummer2(void) static void BlitterMidsummer2(void)
{ {
uint32_t cmd = GET32(blitter_ram, COMMAND); uint32_t cmd = GET32(blitter_ram, COMMAND);
@ -1742,7 +1737,7 @@ void BlitterMidsummer2(void)
SET16(blitter_ram, A2_PIXEL + 0, a2_y); SET16(blitter_ram, A2_PIXEL + 0, a2_y);
} }
void ADDRGEN(uint32_t &address, uint32_t &pixa, bool gena2, bool zaddr, static void ADDRGEN(uint32_t &address, uint32_t &pixa, bool gena2, bool zaddr,
uint16_t a1_x, uint16_t a1_y, uint32_t a1_base, uint8_t a1_pitch, uint8_t a1_pixsize, uint8_t a1_width, uint8_t a1_zoffset, uint16_t a1_x, uint16_t a1_y, uint32_t a1_base, uint8_t a1_pitch, uint8_t a1_pixsize, uint8_t a1_width, uint8_t a1_zoffset,
uint16_t a2_x, uint16_t a2_y, uint32_t a2_base, uint8_t a2_pitch, uint8_t a2_pixsize, uint8_t a2_width, uint8_t a2_zoffset) uint16_t a2_x, uint16_t a2_y, uint32_t a2_base, uint8_t a2_pitch, uint8_t a2_pixsize, uint8_t a2_width, uint8_t a2_zoffset)
{ {
@ -1774,7 +1769,7 @@ void ADDRGEN(uint32_t &address, uint32_t &pixa, bool gena2, bool zaddr,
pixa &= 0x07; pixa &= 0x07;
} }
void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, static void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix, uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2, uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
uint32_t zinc, uint32_t zstep) uint32_t zinc, uint32_t zstep)
@ -1848,7 +1843,7 @@ void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddm
ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh); ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
} }
void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh) static void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh)
{ {
uint8_t carry[4]; uint8_t carry[4];
uint32_t qt = (a & 0xFF) + (b & 0xFF) + cin; uint32_t qt = (a & 0xFF) + (b & 0xFF) + cin;
@ -1899,7 +1894,7 @@ suba_x, suba_y complement the X and Y values
*/ */
void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y, static void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y, int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst, int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
bool adda_yconst, bool addareg, bool suba_x, bool suba_y) bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
@ -1928,7 +1923,7 @@ pointers, or the A1 fractional part. It can also be zero, so that the step
registers load directly into the pointers. registers load directly into the pointers.
*/ */
void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y, static void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y) int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y)
{ {
int16_t xterm[4], yterm[4]; int16_t xterm[4], yterm[4];
@ -1938,17 +1933,6 @@ void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, in
addb_y = yterm[addbsel & 0x03]; addb_y = yterm[addbsel & 0x03];
} }
/** DATAMUX - Address local data bus selection ******************
Select between the adder output and the input data bus
*/
void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel)
{
data_x = (addqsel ? addq_x : (int16_t)(gpu_din & 0xFFFF));
data_y = (addqsel ? addq_y : (int16_t)(gpu_din >> 16));
}
/****************************************************************** /******************************************************************
addradd addradd
29/11/90 29/11/90
@ -1969,7 +1953,7 @@ modx[0..2] take values
******************************************************************/ ******************************************************************/
void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi, static void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y) uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y)
{ {
static uint16_t co_x = 0, co_y = 0; static uint16_t co_x = 0, co_y = 0;
@ -1985,7 +1969,7 @@ void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
addq_y = addqt_y & 0xFFFF; addq_y = addqt_y & 0xFFFF;
} }
void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite, static void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel, bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd, uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode, bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
@ -2184,7 +2168,7 @@ performed. The is taken care of within the zed comparator by
pipe-lining the comparator inputs where appropriate. pipe-lining the comparator inputs where appropriate.
*/ */
void COMP_CTRL(uint8_t &dbinh, bool &nowrite, static void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount, bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp) uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp)
{ {

View File

@ -9,7 +9,6 @@
void BlitterInit(void); void BlitterInit(void);
void BlitterReset(void); void BlitterReset(void);
void BlitterDone(void);
uint8_t BlitterReadByte(uint32_t, uint32_t who = UNKNOWN); uint8_t BlitterReadByte(uint32_t, uint32_t who = UNKNOWN);
uint16_t BlitterReadWord(uint32_t, uint32_t who = UNKNOWN); uint16_t BlitterReadWord(uint32_t, uint32_t who = UNKNOWN);
@ -18,7 +17,4 @@ void BlitterWriteByte(uint32_t, uint8_t, uint32_t who = UNKNOWN);
void BlitterWriteWord(uint32_t, uint16_t, uint32_t who = UNKNOWN); void BlitterWriteWord(uint32_t, uint16_t, uint32_t who = UNKNOWN);
void BlitterWriteLong(uint32_t, uint32_t, uint32_t who = UNKNOWN); 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);
#endif // __BLITTER_H__ #endif // __BLITTER_H__

View File

@ -7,6 +7,7 @@
#include "dac.h" #include "dac.h"
#include "dsp.h" #include "dsp.h"
#include "event.h" #include "event.h"
#include "settings.h"
#include "m68000/m68kinterface.h" #include "m68000/m68kinterface.h"
#include <assert.h> #include <assert.h>
@ -20,11 +21,17 @@
#define TOC_BASE_ADDR 0x2C00 #define TOC_BASE_ADDR 0x2C00
// arbitrary number, but something is needed here
// too short, and games FMVs misbehave (Space Ace is entirely FMVs!!!)
// too long, and games will time out on CD reads
// NTSC and PAL probably shouldn't have different timings here...
#define CD_DELAY_USECS (vjs.hardwareTypeNTSC ? 270 : 280)
static bool cd_setup; static bool cd_setup;
static bool cd_initm; static bool cd_initm;
static bool cd_muted; static bool cd_muted;
static bool cd_paused; static bool cd_paused;
bool cd_jerry; static bool cd_jerry;
static uint8_t cd_mode; static uint8_t cd_mode;
static uint8_t cd_osamp; static uint8_t cd_osamp;
@ -232,10 +239,6 @@ void CDHLEReset(void)
} }
} }
void CDHLEDone(void)
{
}
static void RefillCDBuf() static void RefillCDBuf()
{ {
memmove(&cd_buf2352[0], &cd_buf2352[cd_buf_pos], cd_buf_rm); memmove(&cd_buf2352[0], &cd_buf2352[cd_buf_pos], cd_buf_rm);
@ -267,10 +270,10 @@ static void CDHLECallback(void)
{ {
if (cd_is_reading) if (cd_is_reading)
{ {
if (!GPURunning()) if (!GPUIsRunning())
fprintf(stderr, "CDHLECallback called with GPU inactive\n"); fprintf(stderr, "CDHLECallback called with GPU inactive\n");
if (GPURunning() && !cd_paused) if (GPUIsRunning() && !cd_paused)
{ {
if (cd_buf_rm < 64) if (cd_buf_rm < 64)
{ {
@ -299,7 +302,7 @@ static void CDHLECallback(void)
//GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE); //GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE);
} }
SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); SetCallbackTime(CDHLECallback, CD_DELAY_USECS >> (cd_mode & 1));
} }
} }
@ -337,7 +340,7 @@ static void ResetCallback(void)
RemoveCallback(CDHLECallback); RemoveCallback(CDHLECallback);
if (!cd_jerry) if (!cd_jerry)
{ {
SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); SetCallbackTime(CDHLECallback, CD_DELAY_USECS >> (cd_mode & 1));
} }
} }

View File

@ -5,7 +5,6 @@
void CDHLEInit(void); void CDHLEInit(void);
void CDHLEReset(void); void CDHLEReset(void);
void CDHLEDone(void);
void CDHLEHook(uint32_t which); void CDHLEHook(uint32_t which);
bool CDHLEJerryCallback(void); bool CDHLEJerryCallback(void);

View File

@ -1,38 +0,0 @@
//
// OS agnostic CDROM interface functions
//
// by James Hammons
// (C) 2010 Underground Software
//
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- ------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
//
#include "cdintf.h"
bool CDIntfInit(void)
{
return false;
}
void CDIntfDone(void)
{
}
bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
{
return false;
}
uint8_t CDIntfGetSessionInfo(uint32_t session, uint32_t offset)
{
return 0xFF;
}
uint8_t CDIntfGetTrackInfo(uint32_t track, uint32_t offset)
{
return 0xFF;
}

View File

@ -1,18 +0,0 @@
//
// CDINTF.H: OS agnostic CDROM access funcions
//
// by James Hammons
//
#ifndef __CDINTF_H__
#define __CDINTF_H__
#include <stdint.h>
bool CDIntfInit(void);
void CDIntfDone(void);
bool CDIntfReadBlock(uint32_t, uint8_t *);
uint8_t CDIntfGetSessionInfo(uint32_t, uint32_t);
uint8_t CDIntfGetTrackInfo(uint32_t, uint32_t);
#endif // __CDINTF_H__

View File

@ -16,7 +16,6 @@
#include "cdrom.h" #include "cdrom.h"
#include <string.h> #include <string.h>
#include "cdintf.h"
#include "dac.h" #include "dac.h"
// Private function prototypes // Private function prototypes
@ -37,34 +36,16 @@ static uint16_t CDROMBusRead(void);
#define UNKNOWN BUTCH + 0x2C // Seems to be some sort of I2S interface #define UNKNOWN BUTCH + 0x2C // Seems to be some sort of I2S interface
uint8_t cdRam[0x100]; uint8_t cdRam[0x100];
static uint16_t cdCmd = 0, cdPtr = 0;
static bool haveCDGoodness;
static uint32_t min, sec, frm, block;
static uint8_t cdBuf[2352 + 96];
static uint32_t cdBufPtr = 2352;
void CDROMInit(void) void CDROMInit(void)
{ {
haveCDGoodness = CDIntfInit();
} }
void CDROMReset(void) void CDROMReset(void)
{ {
memset(cdRam, 0x00, 0x100); memset(cdRam, 0x00, sizeof(cdRam));
cdCmd = 0;
} }
void CDROMDone(void)
{
CDIntfDone();
}
//
// This approach is probably wrong, but let's do it for now.
// What's needed is a complete overhaul of the interrupt system so that
// interrupts are handled as they're generated--instead of the current
// scheme where they're handled on scanline boundaries.
//
void BUTCHExec(uint32_t cycles) void BUTCHExec(uint32_t cycles)
{ {
} }
@ -78,7 +59,7 @@ uint8_t CDROMReadByte(uint32_t offset, uint32_t who)
return cdRam[offset & 0xFF]; return cdRam[offset & 0xFF];
} }
static uint8_t trackNum = 1, minTrack, maxTrack; static uint8_t minTrack, maxTrack;
uint16_t CDROMReadWord(uint32_t offset, uint32_t who) uint16_t CDROMReadWord(uint32_t offset, uint32_t who)
{ {
@ -86,103 +67,10 @@ uint16_t CDROMReadWord(uint32_t offset, uint32_t who)
uint16_t data = 0x0000; uint16_t data = 0x0000;
if (offset == BUTCH)
data = 0x0000;
else if (offset == BUTCH + 2)
data = (haveCDGoodness ? cdRam[BUTCH + 3] << 8 : 0x0000);
else if (offset == DS_DATA && haveCDGoodness)
{
if ((cdCmd & 0xFF00) == 0x0100)
{
cdPtr++;
switch (cdPtr)
{
case 1:
data = 0x0000;
break;
case 2:
data = 0x0100;
break;
case 3:
data = 0x0200;
break;
case 4:
data = 0x0300;
break;
case 5:
data = 0x0400;
}
}
else if ((cdCmd & 0xFF00) == 0x0200)
{
data = 0x0400;
}
else if ((cdCmd & 0xFF00) == 0x0300)
{
data = CDIntfGetSessionInfo(cdCmd & 0xFF, cdPtr);
if (data == 0xFF)
{
data = 0x0400;
}
else
{
data |= (0x20 | cdPtr++) << 8;
}
}
else if ((cdCmd & 0xFF00) == 0x1000 || (cdCmd & 0xFF00) == 0x1100 || (cdCmd & 0xFF00) == 0x1200)
data = 0x0100;
else if ((cdCmd & 0xFF00) == 0x1400)
{
if (trackNum > maxTrack)
{
data = 0x400;
}
else
{
if (cdPtr < 0x62)
data = (cdPtr << 8) | trackNum;
else if (cdPtr < 0x65)
data = (cdPtr << 8) | CDIntfGetTrackInfo(trackNum, (cdPtr - 2) & 0x0F);
cdPtr++;
if (cdPtr == 0x65)
cdPtr = 0x60, trackNum++;
}
}
else if ((cdCmd & 0xFF00) == 0x1500)
{
data = cdCmd | 0x0200;
}
else if ((cdCmd & 0xFF00) == 0x1800)
{
data = cdCmd;
}
else if ((cdCmd & 0xFF00) == 0x5400)
{
data = cdCmd | 0x00;
}
else if ((cdCmd & 0xFF00) == 0x7000)
{
data = cdCmd;
}
else
{
data = 0x0400;
}
}
else if (offset == DS_DATA && !haveCDGoodness)
data = 0x0400;
else if (offset >= FIFO_DATA && offset <= FIFO_DATA + 3)
{
}
else if (offset >= FIFO_DATA + 4 && offset <= FIFO_DATA + 7)
{
}
else
data = GET16(cdRam, offset);
if (offset == UNKNOWN + 2) if (offset == UNKNOWN + 2)
data = CDROMBusRead(); data = CDROMBusRead();
else if (offset < FIFO_DATA || offset > FIFO_DATA + 7)
data = GET16(cdRam, offset);
return data; return data;
} }
@ -198,52 +86,6 @@ void CDROMWriteWord(uint32_t offset, uint16_t data, uint32_t who)
offset &= 0xFF; offset &= 0xFF;
SET16(cdRam, offset, data); SET16(cdRam, offset, data);
if (offset == DS_DATA)
{
cdCmd = data;
if ((data & 0xFF00) == 0x0200)
{
cdPtr = 0;
}
else if ((data & 0xFF00) == 0x0300)
{
cdPtr = 0;
}
else if ((data & 0xFF00) == 0x1000)
{
min = data & 0x00FF;
}
else if ((data & 0xFF00) == 0x1100)
{
sec = data & 0x00FF;
}
else if ((data & 0xFF00) == 0x1200)
{
frm = data & 0x00FF;
block = (((min * 60) + sec) * 75) + frm;
cdBufPtr = 2352;
}
else if ((data & 0xFF00) == 0x1400)
{
cdPtr = 0x60,
minTrack = CDIntfGetSessionInfo(data & 0xFF, 0),
maxTrack = CDIntfGetSessionInfo(data & 0xFF, 1);
trackNum = minTrack;
}
else if ((data & 0xFF00) == 0x1500)
{
}
else if ((data & 0xFF00) == 0x1800)
{
}
else if ((data & 0xFF00) == 0x5400)
{
}
else if ((data & 0xFF00) == 0x7000)
{
}
}
if (offset == UNKNOWN + 2) if (offset == UNKNOWN + 2)
CDROMBusWrite(data); CDROMBusWrite(data);
} }
@ -257,9 +99,8 @@ static ButchState currentState = ST_INIT;
static uint16_t counter = 0; static uint16_t counter = 0;
static bool cmdTx = false; static bool cmdTx = false;
static uint16_t busCmd; static uint16_t busCmd;
static uint16_t rxData, txData; static uint16_t rxData;
static uint16_t rxDataBit; static uint16_t rxDataBit;
static bool firstTime = false;
static void CDROMBusWrite(uint16_t data) static void CDROMBusWrite(uint16_t data)
{ {
@ -304,14 +145,10 @@ static void CDROMBusWrite(uint16_t data)
rxData = 0x0001; rxData = 0x0001;
counter = 0; counter = 0;
firstTime = true;
txData = 0;
} }
} }
else else
{ {
txData = (txData << 1) | ((data & 0x04) >> 2);
rxDataBit = (rxData & 0x8000) >> 12; rxDataBit = (rxData & 0x8000) >> 12;
rxData <<= 1; rxData <<= 1;
counter++; counter++;
@ -330,60 +167,3 @@ static uint16_t CDROMBusRead(void)
{ {
return rxDataBit; return rxDataBit;
} }
static uint8_t cdBuf2[2532 + 96], cdBuf3[2532 + 96];
uint16_t GetWordFromButchSSI(uint32_t offset, uint32_t who)
{
bool go = ((offset & 0x0F) == 0x0A || (offset & 0x0F) == 0x0E ? true : false);
if (!go)
return 0x000;
cdBufPtr += 2;
if (cdBufPtr >= 2352)
{
CDIntfReadBlock(block - 150, cdBuf2);
CDIntfReadBlock(block - 149, cdBuf3);
for(int i=0; i<2352-4; i+=4)
{
cdBuf[i+0] = cdBuf2[i+4];
cdBuf[i+1] = cdBuf2[i+5];
cdBuf[i+2] = cdBuf2[i+2];
cdBuf[i+3] = cdBuf2[i+3];
}
cdBuf[2348] = cdBuf3[0];
cdBuf[2349] = cdBuf3[1];
cdBuf[2350] = cdBuf2[2350];
cdBuf[2351] = cdBuf2[2351];
block++, cdBufPtr = 0;
}
return (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0];
}
bool ButchIsReadyToSend(void)
{
return (cdRam[I2CNTRL + 3] & 0x02 ? true : false);
}
void SetSSIWordsXmittedFromButch(void)
{
cdBufPtr += 4;
if (cdBufPtr >= 2352)
{
CDIntfReadBlock(block, cdBuf2);
CDIntfReadBlock(block + 1, cdBuf3);
memcpy(cdBuf, cdBuf2 + 2, 2350);
cdBuf[2350] = cdBuf3[0];
cdBuf[2351] = cdBuf3[1];
block++, cdBufPtr = 0;
}
lrxd = (cdBuf[cdBufPtr + 3] << 8) | cdBuf[cdBufPtr + 2],
rrxd = (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0];
}

View File

@ -9,7 +9,6 @@
void CDROMInit(void); void CDROMInit(void);
void CDROMReset(void); void CDROMReset(void);
void CDROMDone(void);
void BUTCHExec(uint32_t cycles); void BUTCHExec(uint32_t cycles);
@ -18,8 +17,4 @@ uint16_t CDROMReadWord(uint32_t offset, uint32_t who = UNKNOWN);
void CDROMWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN); void CDROMWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN);
void CDROMWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN); void CDROMWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
bool ButchIsReadyToSend(void);
uint16_t GetWordFromButchSSI(uint32_t offset, uint32_t who = UNKNOWN);
void SetSSIWordsXmittedFromButch(void);
#endif // __CDROM_H__ #endif // __CDROM_H__

View File

@ -15,47 +15,47 @@
#include "crc32.h" #include "crc32.h"
static unsigned long crctable[256] = static const uint32_t crctable[256] =
{ {
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
}; };
int crc32_calcCheckSum(unsigned char * data, unsigned int length) uint32_t crc32_calcCheckSum(uint8_t * data, uint32_t length)
{ {
unsigned long crc = 0xFFFFFFFF; uint32_t crc = 0xFFFFFFFF;
for(unsigned int i=0; i<length; i++) for(uint32_t i=0; i<length; i++)
crc = crctable[(crc ^ *data++) & 0xFF] ^ (crc >> 8); crc = crctable[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
return crc ^ 0xFFFFFFFF; return crc ^ 0xFFFFFFFF;

View File

@ -5,6 +5,8 @@
#ifndef __CRC32_H__ #ifndef __CRC32_H__
#define __CRC32_H__ #define __CRC32_H__
int crc32_calcCheckSum(unsigned char * data, unsigned int length); #include <stdint.h>
uint32_t crc32_calcCheckSum(uint8_t * data, uint32_t length);
#endif // __CRC32_H__ #endif // __CRC32_H__

View File

@ -1,7 +1,7 @@
// //
// Red Color Values for CrY<->RGB Color Conversion // Red Color Values for CrY<->RGB Color Conversion
// //
uint8_t redcv[16][16] = { static const uint8_t redcv[16][16] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F // 0 1 2 3 4 5 6 7 8 9 A B C D E F
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0
@ -25,7 +25,7 @@ uint8_t redcv[16][16] = {
// //
// Green Color Values for CrY<->RGB Color Conversion // Green Color Values for CrY<->RGB Color Conversion
// //
uint8_t greencv[16][16] = { static const uint8_t greencv[16][16] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F // 0 1 2 3 4 5 6 7 8 9 A B C D E F
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
{ 0, 17, 34, 51,68, 85, 102,119,136,153,170,187,204,221,238,255}, // 0 { 0, 17, 34, 51,68, 85, 102,119,136,153,170,187,204,221,238,255}, // 0
@ -49,7 +49,7 @@ uint8_t greencv[16][16] = {
// //
// Blue Color Values for CrY<->RGB Color Conversion // Blue Color Values for CrY<->RGB Color Conversion
// //
uint8_t bluecv[16][16] = { static const uint8_t bluecv[16][16] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F // 0 1 2 3 4 5 6 7 8 9 A B C D E F
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
{ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}, // 0 { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}, // 0

View File

@ -14,32 +14,6 @@
// JLH 04/30/2012 Changed SDL audio handler to run JERRY // JLH 04/30/2012 Changed SDL audio handler to run JERRY
// //
// Need to set up defaults that the BIOS sets for the SSI here in DACInit()... !!! FIX !!!
// or something like that... Seems like it already does, but it doesn't seem to
// work correctly...! Perhaps just need to set up SSI stuff so BUTCH doesn't get
// confused...
// After testing on a real Jaguar, it seems clear that the I2S interrupt drives
// the audio subsystem. So while you can drive the audio at a *slower* rate than
// set by SCLK, you can't drive it any *faster*. Also note, that if the I2S
// interrupt is not enabled/running on the DSP, then there is no audio. Also,
// audio can be muted by clearing bit 8 of JOYSTICK (JOY1).
//
// Approach: We can run the DSP in the host system's audio IRQ, by running the
// DSP for the alloted time (depending on the host buffer size & sample rate)
// by simply reading the L/R_I2S (L/RTXD) registers at regular intervals. We
// would also have to time the I2S/TIMER0/TIMER1 interrupts in the DSP as well.
// This way, we can run the host audio IRQ at, say, 48 KHz and not have to care
// so much about SCLK and running a separate buffer and all the attendant
// garbage that comes with that awful approach.
//
// There would still be potential gotchas, as the SCLK can theoretically drive
// the I2S at 26590906 / 2 (for SCLK == 0) = 13.3 MHz which corresponds to an
// audio rate 416 KHz (dividing the I2S rate by 32, for 16-bit stereo). It
// seems doubtful that anything useful could come of such a high rate, and we
// can probably safely ignore any such ridiculously high audio rates. It won't
// sound the same as on a real Jaguar, but who cares? :-)
#include "dac.h" #include "dac.h"
#include "cdrom.h" #include "cdrom.h"
@ -50,8 +24,7 @@
#include "m68000/m68kinterface.h" #include "m68000/m68kinterface.h"
#include "settings.h" #include "settings.h"
#define BUFFER_SIZE 0x10000 // Make the DAC buffers 64K x 16 bits #define DAC_AUDIO_RATE 44100.0 // Set the audio rate to 44.1 KHz
#define DAC_AUDIO_RATE 48000 // Set the audio rate to 48 KHz
// Jaguar memory locations // Jaguar memory locations
@ -62,15 +35,18 @@
#define SCLK 0xF1A150 #define SCLK 0xF1A150
#define SMODE 0xF1A154 #define SMODE 0xF1A154
// Private function prototypes static uint16_t * sampleBuffer;
static uint32_t bufferIndex;
static uint32_t maxSamples;
extern bool audioEnabled;
void DSPSampleCallback(void); static void DSPSampleCallback(void);
void DACInit(void) void DACInit(void)
{ {
ltxd = lrxd = 0;
sclk = 19; sclk = 19;
maxSamples = 2048; // bleh
DACReset();
} }
// //
@ -78,81 +54,31 @@ void DACInit(void)
// //
void DACReset(void) void DACReset(void)
{ {
ltxd = lrxd = 0; ltxd = rtxd = 0;
RemoveCallback(DSPSampleCallback);
SetCallbackTime(DSPSampleCallback, 1000000.0 / DAC_AUDIO_RATE);
} }
void DACDone(void) // Call this every frame with your buffer or NULL
// Returns amount of samples last outputted
uint32_t DACResetBuffer(void * buffer)
{ {
} sampleBuffer = (uint16_t*)buffer;
uint32_t ret = bufferIndex / 2;
// Approach: Run the DSP for however many cycles needed to correspond to whatever sample rate
// we've set the audio to run at. So, e.g., if we run it at 48 KHz, then we would run the DSP
// for however much time it takes to fill the buffer. So with a 2K buffer, this would correspond
// to running the DSP for 0.042666... seconds. At 26590906 Hz, this would correspond to
// running the DSP for 1134545 cycles. You would then sample the L/RTXD registers every
// 1134545 / 2048 = 554 cycles to fill the buffer. You would also have to manage interrupt
// timing as well (generating them at the proper times), but that shouldn't be too difficult...
// If the DSP isn't running, then fill the buffer with L/RTXD and exit.
//
// 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.
if (!DSPIsRunning())
{
for(int i=0; i<(length/2); i+=2)
{
buffer[i + 0] = ltxd;
buffer[i + 1] = rtxd;
}
return;
}
bufferIndex = 0; bufferIndex = 0;
sampleBuffer = buffer; return ret;
numberOfSamples = length / 2;
bufferDone = false;
SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY);
do
{
double timeToNextEvent = GetTimeToNextEvent(EVENT_JERRY);
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
HandleNextEvent(EVENT_JERRY);
}
while (!bufferDone);
} }
static void DSPSampleCallback(void)
void DSPSampleCallback(void)
{ {
sampleBuffer[bufferIndex + 0] = ltxd; if (bufferIndex != maxSamples)
sampleBuffer[bufferIndex + 1] = rtxd;
bufferIndex += 2;
if (bufferIndex == numberOfSamples)
{ {
bufferDone = true; sampleBuffer[bufferIndex + 0] = audioEnabled ? ltxd : 0;
return; sampleBuffer[bufferIndex + 1] = audioEnabled ? rtxd : 0;
bufferIndex += 2;
} }
SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY); SetCallbackTime(DSPSampleCallback, 1000000.0 / DAC_AUDIO_RATE);
} }
// //

View File

@ -9,7 +9,7 @@
void DACInit(void); void DACInit(void);
void DACReset(void); void DACReset(void);
void DACDone(void); uint32_t DACResetBuffer(void * buffer);
// DAC memory access // DAC memory access

View File

@ -176,7 +176,7 @@ static uint32_t dsp_flags;
static uint32_t dsp_matrix_control; static uint32_t dsp_matrix_control;
static uint32_t dsp_pointer_to_matrix; static uint32_t dsp_pointer_to_matrix;
static uint32_t dsp_data_organization; static uint32_t dsp_data_organization;
uint32_t dsp_control; static uint32_t dsp_control;
static uint32_t dsp_div_control; static uint32_t dsp_div_control;
static uint8_t dsp_flag_z, dsp_flag_n, dsp_flag_c; static uint8_t dsp_flag_z, dsp_flag_n, dsp_flag_c;
static uint32_t * dsp_reg = NULL, * dsp_alternate_reg = NULL; static uint32_t * dsp_reg = NULL, * dsp_alternate_reg = NULL;
@ -194,7 +194,7 @@ static uint8_t branch_condition_table[32 * 8];
static uint16_t mirror_table[65536]; static uint16_t mirror_table[65536];
uint8_t dsp_ram_8[0x2000]; uint8_t dsp_ram_8[0x2000];
void dsp_build_branch_condition_table(void) static void dsp_build_branch_condition_table(void)
{ {
for(int i=0; i<65536; i++) for(int i=0; i<65536; i++)
{ {
@ -231,6 +231,64 @@ void dsp_build_branch_condition_table(void)
} }
} }
//
// Update the DSP register file pointers depending on REGPAGE bit
//
static void DSPUpdateRegisterBanks(void)
{
int bank = (dsp_flags & REGPAGE);
if (dsp_flags & IMASK)
bank = 0;
if (bank)
dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
else
dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
}
//
// Check for and handle any asserted DSP IRQs
//
static void DSPHandleIRQs(void)
{
if (dsp_flags & IMASK)
return;
uint32_t bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
bits &= mask;
if (!bits)
return;
int which = 0;
if (bits & 0x01)
which = 0;
if (bits & 0x02)
which = 1;
if (bits & 0x04)
which = 2;
if (bits & 0x08)
which = 3;
if (bits & 0x10)
which = 4;
if (bits & 0x20)
which = 5;
dsp_flags |= IMASK;
DSPUpdateRegisterBanks();
dsp_reg[31] -= 4;
dsp_reg[30] = dsp_pc - 2;
DSPWriteLong(dsp_reg[31], dsp_reg[30], DSP);
dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
}
uint8_t DSPReadByte(uint32_t offset, uint32_t who) uint8_t DSPReadByte(uint32_t offset, uint32_t who)
{ {
if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF)) if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
@ -460,64 +518,6 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who)
JaguarWriteLong(offset, data, who); JaguarWriteLong(offset, data, who);
} }
//
// Update the DSP register file pointers depending on REGPAGE bit
//
void DSPUpdateRegisterBanks(void)
{
int bank = (dsp_flags & REGPAGE);
if (dsp_flags & IMASK)
bank = 0;
if (bank)
dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
else
dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
}
//
// Check for and handle any asserted DSP IRQs
//
void DSPHandleIRQsNP(void)
{
if (dsp_flags & IMASK)
return;
uint32_t bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
bits &= mask;
if (!bits)
return;
int which = 0;
if (bits & 0x01)
which = 0;
if (bits & 0x02)
which = 1;
if (bits & 0x04)
which = 2;
if (bits & 0x08)
which = 3;
if (bits & 0x10)
which = 4;
if (bits & 0x20)
which = 5;
dsp_flags |= IMASK;
DSPUpdateRegisterBanks();
dsp_reg[31] -= 4;
dsp_reg[30] = dsp_pc - 2;
DSPWriteLong(dsp_reg[31], dsp_reg[30], DSP);
dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
}
// //
// Set the specified DSP IRQ line to a given state // Set the specified DSP IRQ line to a given state
// //
@ -529,7 +529,7 @@ void DSPSetIRQLine(int irqline, int state)
if (state) if (state)
{ {
dsp_control |= mask; dsp_control |= mask;
DSPHandleIRQsNP(); DSPHandleIRQs();
} }
} }
@ -570,10 +570,6 @@ void DSPReset(void)
*((uint32_t *)(&dsp_ram_8[i])) = rand(); *((uint32_t *)(&dsp_ram_8[i])) = rand();
} }
void DSPDone(void)
{
}
// //
// DSP execution core // DSP execution core
// //
@ -585,7 +581,7 @@ void DSPExec(int32_t cycles)
if (IMASKCleared && !dsp_inhibit_interrupt) if (IMASKCleared && !dsp_inhibit_interrupt)
{ {
DSPHandleIRQsNP(); DSPHandleIRQs();
IMASKCleared = false; IMASKCleared = false;
} }

View File

@ -13,8 +13,6 @@
void DSPInit(void); void DSPInit(void);
void DSPReset(void); void DSPReset(void);
void DSPExec(int32_t); void DSPExec(int32_t);
void DSPDone(void);
void DSPUpdateRegisterBanks(void);
void DSPSetIRQLine(int irqline, int state); void DSPSetIRQLine(int irqline, int state);
uint8_t DSPReadByte(uint32_t offset, uint32_t who = UNKNOWN); uint8_t DSPReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t DSPReadWord(uint32_t offset, uint32_t who = UNKNOWN); uint16_t DSPReadWord(uint32_t offset, uint32_t who = UNKNOWN);

View File

@ -22,7 +22,6 @@
uint16_t eeprom_ram[64]; uint16_t eeprom_ram[64];
bool eeprom_dirty; bool eeprom_dirty;
static void EEPROMSave(void);
static void eeprom_set_di(uint32_t state); static void eeprom_set_di(uint32_t state);
static void eeprom_set_cs(uint32_t state); static void eeprom_set_cs(uint32_t state);
static uint32_t eeprom_get_do(void); static uint32_t eeprom_get_do(void);
@ -52,15 +51,6 @@ void EepromReset(void)
{ {
} }
void EepromDone(void)
{
}
static void EEPROMSave(void)
{
eeprom_dirty = true;
}
uint8_t EepromReadByte(uint32_t offset) uint8_t EepromReadByte(uint32_t offset)
{ {
switch (offset) switch (offset)
@ -164,7 +154,7 @@ static void eeprom_set_di(uint32_t data)
for(int i=0; i<64; i++) for(int i=0; i<64; i++)
eeprom_ram[i] = jerry_ee_data; eeprom_ram[i] = jerry_ee_data;
EEPROMSave(); eeprom_dirty = true;
} }
jerry_ee_state = EE_STATE_BUSY; jerry_ee_state = EE_STATE_BUSY;
@ -198,7 +188,7 @@ static void eeprom_set_di(uint32_t data)
if (jerry_writes_enabled) if (jerry_writes_enabled)
{ {
eeprom_ram[jerry_ee_address_data] = jerry_ee_data; eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
EEPROMSave(); eeprom_dirty = true;
} }
jerry_ee_state = EE_STATE_BUSY; jerry_ee_state = EE_STATE_BUSY;
@ -269,7 +259,6 @@ static void eeprom_set_cs(uint32_t)
jerry_writes_enabled = 1; jerry_writes_enabled = 1;
} }
static uint32_t eeprom_get_do(void) static uint32_t eeprom_get_do(void)
{ {
uint16_t data = 1; uint16_t data = 1;
@ -296,4 +285,3 @@ static uint32_t eeprom_get_do(void)
return data; return data;
} }

View File

@ -9,7 +9,6 @@
void EepromInit(void); void EepromInit(void);
void EepromReset(void); void EepromReset(void);
void EepromDone(void);
uint8_t EepromReadByte(uint32_t offset); uint8_t EepromReadByte(uint32_t offset);
uint16_t EepromReadWord(uint32_t offset); uint16_t EepromReadWord(uint32_t offset);

View File

@ -23,7 +23,7 @@
#include <stdint.h> #include <stdint.h>
#include <float.h> #include <float.h>
#define EVENT_LIST_SIZE 32 #define EVENT_LIST_SIZE 64
// Now, a bit of weirdness: It seems that the number of lines displayed on the screen // 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! // makes the effective refresh rate either 30 or 25 Hz!
@ -40,15 +40,12 @@
struct Event struct Event
{ {
bool valid; bool valid;
int eventType;
double eventTime; double eventTime;
void (* timerCallback)(void); void (* timerCallback)(void);
}; };
static Event eventList[EVENT_LIST_SIZE]; static Event eventList[EVENT_LIST_SIZE];
static Event eventListJERRY[EVENT_LIST_SIZE];
static uint32_t nextEvent; static uint32_t nextEvent;
static uint32_t nextEventJERRY;
static uint32_t numberOfEvents; static uint32_t numberOfEvents;
void InitializeEventList(void) void InitializeEventList(void)
@ -56,44 +53,23 @@ void InitializeEventList(void)
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++) for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{ {
eventList[i].valid = false; eventList[i].valid = false;
eventListJERRY[i].valid = false;
} }
numberOfEvents = 0; numberOfEvents = 0;
} }
void SetCallbackTime(void (* callback)(void), double time, int type) void SetCallbackTime(void (* callback)(void), double time)
{ {
if (type == EVENT_MAIN) for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{ {
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++) if (!eventList[i].valid)
{ {
if (!eventList[i].valid) eventList[i].timerCallback = callback;
{ eventList[i].eventTime = time;
eventList[i].timerCallback = callback; eventList[i].valid = true;
eventList[i].eventTime = time; numberOfEvents++;
eventList[i].eventType = type;
eventList[i].valid = true;
numberOfEvents++;
return; return;
}
}
}
else
{
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{
if (!eventListJERRY[i].valid)
{
eventListJERRY[i].timerCallback = callback;
eventListJERRY[i].eventTime = time;
eventListJERRY[i].eventType = type;
eventListJERRY[i].valid = true;
numberOfEvents++;
return;
}
} }
} }
} }
@ -107,33 +83,6 @@ void RemoveCallback(void (* callback)(void))
eventList[i].valid = false; eventList[i].valid = false;
numberOfEvents--; numberOfEvents--;
return;
}
else if (eventListJERRY[i].valid && eventListJERRY[i].timerCallback == callback)
{
eventListJERRY[i].valid = false;
numberOfEvents--;
return;
}
}
}
void AdjustCallbackTime(void (* callback)(void), double time)
{
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{
if (eventList[i].valid && eventList[i].timerCallback == callback)
{
eventList[i].eventTime = time;
return;
}
else if (eventListJERRY[i].valid && eventListJERRY[i].timerCallback == callback)
{
eventListJERRY[i].eventTime = time;
return; return;
} }
} }
@ -143,74 +92,36 @@ void AdjustCallbackTime(void (* callback)(void), double time)
// Since our list is unordered WRT time, we have to search it to find the next event // 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 // Returns time to next event & sets nextEvent to that event
// //
double GetTimeToNextEvent(int type) double GetTimeToNextEvent()
{ {
if (type == EVENT_MAIN) double time = DBL_MAX;
nextEvent = EVENT_LIST_SIZE;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{ {
double time = DBL_MAX; if (eventList[i].valid && (eventList[i].eventTime < time))
nextEvent = EVENT_LIST_SIZE;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{ {
if (eventList[i].valid && (eventList[i].eventTime < time)) time = eventList[i].eventTime;
{ nextEvent = i;
time = eventList[i].eventTime;
nextEvent = i;
}
} }
assert(nextEvent != EVENT_LIST_SIZE);
return time;
} }
else
{
double time = DBL_MAX;
nextEventJERRY = EVENT_LIST_SIZE;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++) assert(nextEvent != EVENT_LIST_SIZE);
{ return time;
if (eventListJERRY[i].valid && (eventListJERRY[i].eventTime < time))
{
time = eventListJERRY[i].eventTime;
nextEventJERRY = i;
}
}
assert(nextEventJERRY != EVENT_LIST_SIZE);
return time;
}
} }
void HandleNextEvent(int type) void HandleNextEvent()
{ {
if (type == EVENT_MAIN) double elapsedTime = eventList[nextEvent].eventTime;
void (* event)(void) = eventList[nextEvent].timerCallback;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{ {
double elapsedTime = eventList[nextEvent].eventTime; eventList[i].eventTime -= elapsedTime;
void (* event)(void) = eventList[nextEvent].timerCallback;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
{
eventList[i].eventTime -= elapsedTime;
}
eventList[nextEvent].valid = false;
numberOfEvents--;
(*event)();
} }
else
{
double elapsedTime = eventListJERRY[nextEventJERRY].eventTime;
void (* event)(void) = eventListJERRY[nextEventJERRY].timerCallback;
for(uint32_t i=0; i<EVENT_LIST_SIZE; i++) eventList[nextEvent].valid = false;
{ numberOfEvents--;
eventListJERRY[i].eventTime -= elapsedTime;
}
eventListJERRY[nextEventJERRY].valid = false; (*event)();
numberOfEvents--;
(*event)();
}
} }

View File

@ -7,8 +7,6 @@
#ifndef __EVENT_H__ #ifndef __EVENT_H__
#define __EVENT_H__ #define __EVENT_H__
enum { EVENT_MAIN, EVENT_JERRY };
//NTSC Timings... //NTSC Timings...
#define RISC_CYCLE_IN_USEC 0.03760684198 #define RISC_CYCLE_IN_USEC 0.03760684198
#define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2) #define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2)
@ -23,10 +21,9 @@ enum { EVENT_MAIN, EVENT_JERRY };
#define USEC_TO_M68K_CYCLES(u) (uint32_t)(((u) / (vjs.hardwareTypeNTSC ? M68K_CYCLE_IN_USEC : M68K_CYCLE_PAL_IN_USEC)) + 0.5) #define USEC_TO_M68K_CYCLES(u) (uint32_t)(((u) / (vjs.hardwareTypeNTSC ? M68K_CYCLE_IN_USEC : M68K_CYCLE_PAL_IN_USEC)) + 0.5)
void InitializeEventList(void); void InitializeEventList(void);
void SetCallbackTime(void (* callback)(void), double time, int type = EVENT_MAIN); void SetCallbackTime(void (* callback)(void), double time);
void RemoveCallback(void (* callback)(void)); void RemoveCallback(void (* callback)(void));
void AdjustCallbackTime(void (* callback)(void), double time); double GetTimeToNextEvent(void);
double GetTimeToNextEvent(int type = EVENT_MAIN); void HandleNextEvent(void);
void HandleNextEvent(int type = EVENT_MAIN);
#endif // __EVENT_H__ #endif // __EVENT_H__

View File

@ -1,20 +0,0 @@
//
// FILE.H
//
// File support
//
#ifndef __FILE_H__
#define __FILE_H__
#include <stdint.h>
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 };
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);
#endif // __FILE_H__

View File

@ -59,12 +59,6 @@
#define REGPAGE 0x4000 #define REGPAGE 0x4000
#define DMAEN 0x8000 #define DMAEN 0x8000
// External global variables
// Private function prototypes
void GPUUpdateRegisterBanks(void);
static void gpu_opcode_add(void); static void gpu_opcode_add(void);
static void gpu_opcode_addc(void); static void gpu_opcode_addc(void);
static void gpu_opcode_addq(void); static void gpu_opcode_addq(void);
@ -189,11 +183,6 @@ static uint32_t gpu_inhibit_interrupt;
static uint8_t branch_condition_table[32 * 8]; static uint8_t branch_condition_table[32 * 8];
bool GPURunning(void)
{
return GPU_RUNNING;
}
void build_branch_condition_table(void) void build_branch_condition_table(void)
{ {
for(int i=0; i<8; i++) for(int i=0; i<8; i++)
@ -219,6 +208,54 @@ void build_branch_condition_table(void)
} }
} }
//
// Change register banks if necessary
//
static void GPUUpdateRegisterBanks(void)
{
int bank = (gpu_flags & REGPAGE);
if (gpu_flags & IMASK)
bank = 0;
if (bank)
gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
else
gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
}
static void GPUHandleIRQs(void)
{
if (gpu_flags & IMASK)
return;
uint32_t bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
bits &= mask;
if (!bits)
return;
uint32_t which = 0;
if (bits & 0x01)
which = 0;
if (bits & 0x02)
which = 1;
if (bits & 0x04)
which = 2;
if (bits & 0x08)
which = 3;
if (bits & 0x10)
which = 4;
gpu_flags |= IMASK;
GPUUpdateRegisterBanks();
gpu_reg[31] -= 4;
GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
}
// //
// GPU byte access (read) // GPU byte access (read)
// //
@ -480,54 +517,6 @@ void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who)
JaguarWriteLong(offset, data, who); JaguarWriteLong(offset, data, who);
} }
//
// Change register banks if necessary
//
void GPUUpdateRegisterBanks(void)
{
int bank = (gpu_flags & REGPAGE);
if (gpu_flags & IMASK)
bank = 0;
if (bank)
gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
else
gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
}
void GPUHandleIRQs(void)
{
if (gpu_flags & IMASK)
return;
uint32_t bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
bits &= mask;
if (!bits)
return;
uint32_t which = 0;
if (bits & 0x01)
which = 0;
if (bits & 0x02)
which = 1;
if (bits & 0x04)
which = 2;
if (bits & 0x08)
which = 3;
if (bits & 0x10)
which = 4;
gpu_flags |= IMASK;
GPUUpdateRegisterBanks();
gpu_reg[31] -= 4;
GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
}
void GPUSetIRQLine(int irqline, int state) void GPUSetIRQLine(int irqline, int state)
{ {
uint32_t mask = 0x0040 << irqline; uint32_t mask = 0x0040 << irqline;
@ -540,10 +529,14 @@ void GPUSetIRQLine(int irqline, int state)
} }
} }
bool GPUIsRunning(void)
{
return GPU_RUNNING;
}
void GPUInit(void) void GPUInit(void)
{ {
build_branch_condition_table(); build_branch_condition_table();
GPUReset(); GPUReset();
} }
@ -575,10 +568,6 @@ void GPUReset(void)
*((uint32_t *)(&gpu_ram_8[i])) = rand(); *((uint32_t *)(&gpu_ram_8[i])) = rand();
} }
void GPUDone(void)
{
}
// //
// Main GPU execution core // Main GPU execution core
// //

View File

@ -13,9 +13,6 @@
void GPUInit(void); void GPUInit(void);
void GPUReset(void); void GPUReset(void);
void GPUExec(int32_t); void GPUExec(int32_t);
void GPUDone(void);
void GPUUpdateRegisterBanks(void);
void GPUHandleIRQs(void);
void GPUSetIRQLine(int irqline, int state); void GPUSetIRQLine(int irqline, int state);
uint8_t GPUReadByte(uint32_t offset, uint32_t who = UNKNOWN); uint8_t GPUReadByte(uint32_t offset, uint32_t who = UNKNOWN);
@ -25,7 +22,7 @@ void GPUWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN);
void GPUWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN); void GPUWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN); void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN);
bool GPURunning(void); bool GPUIsRunning(void);
// GPU interrupt numbers (from $F00100, bits 4-8) // GPU interrupt numbers (from $F00100, bits 4-8)

View File

@ -443,22 +443,12 @@ void JaguarReset(void)
SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0)); SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
} }
void JaguarDone(void)
{
CDHLEDone();
CDROMDone();
GPUDone();
DSPDone();
TOMDone();
JERRYDone();
}
// //
// New Jaguar execution stack // Jaguar execution stack
// This executes 1 frame's worth of code. // This executes 1 frame's worth of code.
// //
bool frameDone; bool frameDone;
void JaguarExecuteNew(void) void JaguarAdvance(void)
{ {
frameDone = false; frameDone = false;
TOMStartFrame(); TOMStartFrame();
@ -468,8 +458,8 @@ void JaguarExecuteNew(void)
double timeToNextEvent = GetTimeToNextEvent(); double timeToNextEvent = GetTimeToNextEvent();
m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent)); m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
HandleNextEvent(); HandleNextEvent();
} }
@ -522,11 +512,10 @@ void HalflineCallback(void)
m68k_set_irq(2); m68k_set_irq(2);
} }
TOMExecHalfline(vc, true); TOMExecHalfline(vc);
if ((vc & 0x7FF) == 0) if ((vc & 0x7FF) == 0)
{ {
JoystickExec();
frameDone = true; frameDone = true;
} }

View File

@ -6,7 +6,6 @@
void JaguarInit(void); void JaguarInit(void);
void JaguarReset(void); void JaguarReset(void);
void JaguarDone(void);
uint8_t JaguarReadByte(uint32_t offset, uint32_t who = UNKNOWN); uint8_t JaguarReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t JaguarReadWord(uint32_t offset, uint32_t who = UNKNOWN); uint16_t JaguarReadWord(uint32_t offset, uint32_t who = UNKNOWN);
@ -15,7 +14,7 @@ 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 JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN); void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who = UNKNOWN);
void JaguarExecuteNew(void); void JaguarAdvance(void);
// Exports from JAGUAR.CPP // Exports from JAGUAR.CPP

View File

@ -29,7 +29,7 @@
#include "wavetable.h" #include "wavetable.h"
#include "cdhle.h" #include "cdhle.h"
/*static*/ uint8_t jerry_ram_8[0x10000]; uint8_t jerry_ram_8[0x10000];
// JERRY Registers (write, offset from $F10000) // JERRY Registers (write, offset from $F10000)
#define JPIT1 0x00 #define JPIT1 0x00
@ -46,8 +46,6 @@
#define SCLK 0xA150 #define SCLK 0xA150
#define SMODE 0xA154 #define SMODE 0xA154
uint8_t analog_x, analog_y;
static uint32_t JERRYPIT1Prescaler; static uint32_t JERRYPIT1Prescaler;
static uint32_t JERRYPIT1Divider; static uint32_t JERRYPIT1Divider;
static uint32_t JERRYPIT2Prescaler; static uint32_t JERRYPIT2Prescaler;
@ -56,22 +54,17 @@ static int32_t jerry_timer_1_counter;
static int32_t jerry_timer_2_counter; static int32_t jerry_timer_2_counter;
int32_t JERRYI2SInterruptTimer = -1; int32_t JERRYI2SInterruptTimer = -1;
uint32_t jerryI2SCycles; static uint32_t jerryI2SCycles;
uint32_t jerryIntPending;
static uint16_t jerryInterruptMask = 0; static uint16_t jerryInterruptMask = 0;
static uint16_t jerryPendingInterrupt = 0; static uint16_t jerryPendingInterrupt = 0;
// Private function prototypes static void JERRYResetPIT1(void);
static void JERRYResetPIT2(void);
void JERRYResetPIT1(void); static void JERRYResetI2S(void);
void JERRYResetPIT2(void);
void JERRYResetI2S(void);
void JERRYPIT1Callback(void);
void JERRYPIT2Callback(void);
void JERRYI2SCallback(void);
static void JERRYPIT1Callback(void);
static void JERRYPIT2Callback(void);
void JERRYResetI2S(void) void JERRYResetI2S(void)
{ {
@ -86,7 +79,7 @@ void JERRYResetPIT1(void)
if (JERRYPIT1Prescaler | JERRYPIT1Divider) if (JERRYPIT1Prescaler | JERRYPIT1Divider)
{ {
double usecs = (float)(JERRYPIT1Prescaler + 1) * (float)(JERRYPIT1Divider + 1) * RISC_CYCLE_IN_USEC; double usecs = (float)(JERRYPIT1Prescaler + 1) * (float)(JERRYPIT1Divider + 1) * RISC_CYCLE_IN_USEC;
SetCallbackTime(JERRYPIT1Callback, usecs, EVENT_JERRY); SetCallbackTime(JERRYPIT1Callback, usecs);
} }
} }
@ -97,7 +90,7 @@ void JERRYResetPIT2(void)
if (JERRYPIT1Prescaler | JERRYPIT1Divider) if (JERRYPIT1Prescaler | JERRYPIT1Divider)
{ {
double usecs = (float)(JERRYPIT2Prescaler + 1) * (float)(JERRYPIT2Divider + 1) * RISC_CYCLE_IN_USEC; double usecs = (float)(JERRYPIT2Prescaler + 1) * (float)(JERRYPIT2Divider + 1) * RISC_CYCLE_IN_USEC;
SetCallbackTime(JERRYPIT2Callback, usecs, EVENT_JERRY); SetCallbackTime(JERRYPIT2Callback, usecs);
} }
} }
@ -139,7 +132,7 @@ void JERRYI2SCallback(void)
{ {
DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
double usecs = (float)jerryI2SCycles * (vjs.hardwareTypeNTSC ? RISC_CYCLE_IN_USEC : RISC_CYCLE_PAL_IN_USEC); double usecs = (float)jerryI2SCycles * (vjs.hardwareTypeNTSC ? RISC_CYCLE_IN_USEC : RISC_CYCLE_PAL_IN_USEC);
SetCallbackTime(JERRYI2SCallback, usecs, EVENT_JERRY); SetCallbackTime(JERRYI2SCallback, usecs);
} }
else else
{ {
@ -147,7 +140,7 @@ void JERRYI2SCallback(void)
{ {
DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
} }
SetCallbackTime(JERRYI2SCallback, 22.675737, EVENT_JERRY); SetCallbackTime(JERRYI2SCallback, 22.675737);
} }
} }
@ -187,14 +180,6 @@ void JERRYReset(void)
DACReset(); DACReset();
} }
void JERRYDone(void)
{
JoystickDone();
DACDone();
EepromDone();
MTDone();
}
bool JERRYIRQEnabled(int irq) bool JERRYIRQEnabled(int irq)
{ {
return jerryInterruptMask & irq; return jerryInterruptMask & irq;
@ -262,8 +247,6 @@ uint16_t JERRYReadWord(uint32_t offset, uint32_t who)
// //
void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who) void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{ {
jerry_ram_8[offset & 0xFFFF] = data;
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20)) if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20))
{ {
DSPWriteByte(offset, data, who); DSPWriteByte(offset, data, who);
@ -294,6 +277,11 @@ void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{ {
EepromWriteByte(offset, data); EepromWriteByte(offset, data);
} }
if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
return;
jerry_ram_8[offset & 0xFFFF] = data;
} }
// //
@ -301,9 +289,6 @@ void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who)
// //
void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who) void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who)
{ {
jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20)) if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20))
{ {
DSPWriteWord(offset, data, who); DSPWriteWord(offset, data, who);
@ -335,6 +320,7 @@ void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who)
case 6: case 6:
JERRYPIT2Divider = data; JERRYPIT2Divider = data;
JERRYResetPIT2(); JERRYResetPIT2();
break;
} }
} }
else if (offset >= 0xF10020 && offset <= 0xF10022) else if (offset >= 0xF10020 && offset <= 0xF10022)
@ -351,16 +337,10 @@ void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who)
{ {
EepromWriteWord(offset, data); EepromWriteWord(offset, data);
} }
}
int JERRYGetPIT1Frequency(void) if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
{ return;
int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
return systemClockFrequency / ((JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1));
}
int JERRYGetPIT2Frequency(void) jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
{ jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL);
return systemClockFrequency / ((JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1));
} }

View File

@ -9,28 +9,18 @@
void JERRYInit(void); void JERRYInit(void);
void JERRYReset(void); void JERRYReset(void);
void JERRYDone(void);
uint8_t JERRYReadByte(uint32_t offset, uint32_t who = UNKNOWN); uint8_t JERRYReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t JERRYReadWord(uint32_t offset, uint32_t who = UNKNOWN); uint16_t JERRYReadWord(uint32_t offset, uint32_t who = UNKNOWN);
void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN); void JERRYWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN);
void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN); void JERRYWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void JERRYExecPIT(uint32_t cycles);
void JERRYI2SExec(uint32_t cycles);
int JERRYGetPIT1Frequency(void);
int JERRYGetPIT2Frequency(void);
// 68000 Interrupt bit positions (enabled at $F10020) // 68000 Interrupt bit positions (enabled at $F10020)
enum { IRQ2_EXTERNAL=0x01, IRQ2_DSP=0x02, IRQ2_TIMER1=0x04, IRQ2_TIMER2=0x08, IRQ2_ASI=0x10, IRQ2_SSI=0x20 }; enum { IRQ2_EXTERNAL=0x01, IRQ2_DSP=0x02, IRQ2_TIMER1=0x04, IRQ2_TIMER2=0x08, IRQ2_ASI=0x10, IRQ2_SSI=0x20 };
bool JERRYIRQEnabled(int irq); bool JERRYIRQEnabled(int irq);
void JERRYSetPendingIRQ(int irq); void JERRYSetPendingIRQ(int irq);
// This should stay inside this file, but it's here for now...
// Need to set up an interface function so that this can go back
void JERRYI2SCallback(void); void JERRYI2SCallback(void);
// External variables // External variables

View File

@ -19,12 +19,11 @@
#include "jaguar.h" #include "jaguar.h"
#include "settings.h" #include "settings.h"
// Global vars
static uint8_t joystick_ram[4]; static uint8_t joystick_ram[4];
uint8_t joypad0Buttons[21]; uint8_t joypad0Buttons[21];
uint8_t joypad1Buttons[21]; uint8_t joypad1Buttons[21];
static bool joysticksEnabled; static bool joysticksEnabled;
bool audioEnabled;
extern bool lagged; extern bool lagged;
@ -33,20 +32,13 @@ void JoystickInit(void)
JoystickReset(); JoystickReset();
} }
void JoystickExec(void)
{
}
void JoystickReset(void) void JoystickReset(void)
{ {
memset(joystick_ram, 0x00, 4); memset(joystick_ram, 0x00, 4);
memset(joypad0Buttons, 0, 21); memset(joypad0Buttons, 0, 21);
memset(joypad1Buttons, 0, 21); memset(joypad1Buttons, 0, 21);
joysticksEnabled = false; joysticksEnabled = false;
} audioEnabled = false;
void JoystickDone(void)
{
} }
uint16_t JoystickReadWord(uint32_t offset) uint16_t JoystickReadWord(uint32_t offset)
@ -140,6 +132,7 @@ void JoystickWriteWord(uint32_t offset, uint16_t data)
if (offset == 0) if (offset == 0)
{ {
joysticksEnabled = (data & 0x8000 ? true : false); audioEnabled = data & 0x0100;
joysticksEnabled = data & 0x8000;
} }
} }

View File

@ -33,10 +33,8 @@ BUTTON_PAUSE = 20, BUTTON_LAST = 20 };
void JoystickInit(void); void JoystickInit(void);
void JoystickReset(void); void JoystickReset(void);
void JoystickDone(void);
void JoystickWriteWord(uint32_t, uint16_t); void JoystickWriteWord(uint32_t, uint16_t);
uint16_t JoystickReadWord(uint32_t); uint16_t JoystickReadWord(uint32_t);
void JoystickExec(void);
extern uint8_t joypad0Buttons[]; extern uint8_t joypad0Buttons[];
extern uint8_t joypad1Buttons[]; extern uint8_t joypad1Buttons[];

View File

@ -22,6 +22,7 @@
#include "readcpu.h" #include "readcpu.h"
int nr_cpuop_funcs; int nr_cpuop_funcs;
struct instr table68k[65536];
const struct mnemolookup lookuptab[] = { const struct mnemolookup lookuptab[] = {
{ i_ILLG, "ILLEGAL" }, { i_ILLG, "ILLEGAL" },
@ -150,10 +151,6 @@ const struct mnemolookup lookuptab[] = {
{ i_ILLG, "" }, { i_ILLG, "" },
}; };
struct instr * table68k;
STATIC_INLINE amodes mode_from_str(const char * str) STATIC_INLINE amodes mode_from_str(const char * str)
{ {
if (strncmp (str, "Dreg", 4) == 0) return Dreg; if (strncmp (str, "Dreg", 4) == 0) return Dreg;
@ -173,7 +170,6 @@ STATIC_INLINE amodes mode_from_str(const char * str)
return 0; return 0;
} }
STATIC_INLINE amodes mode_from_mr(int mode, int reg) STATIC_INLINE amodes mode_from_mr(int mode, int reg)
{ {
switch (mode) switch (mode)
@ -203,7 +199,6 @@ STATIC_INLINE amodes mode_from_mr(int mode, int reg)
return 0; return 0;
} }
static void build_insn(int insn) static void build_insn(int insn)
{ {
int find = -1; int find = -1;
@ -220,14 +215,14 @@ static void build_insn(int insn)
{ {
switch (id.flaginfo[j].flagset) switch (id.flaginfo[j].flagset)
{ {
case fa_unset: break; case fa_unset: break;
case fa_isjmp: isjmp = 1; break; case fa_isjmp: isjmp = 1; break;
case fa_isbranch: isjmp = 1; break; case fa_isbranch: isjmp = 1; break;
case fa_zero: flagdead |= 1 << j; break; case fa_zero: flagdead |= 1 << j; break;
case fa_one: flagdead |= 1 << j; break; case fa_one: flagdead |= 1 << j; break;
case fa_dontcare: flagdead |= 1 << j; break; case fa_dontcare: flagdead |= 1 << j; break;
case fa_unknown: isjmp = 1; flagdead = -1; goto out1; case fa_unknown: isjmp = 1; flagdead = -1; goto out1;
case fa_set: flagdead |= 1 << j; break; case fa_set: flagdead |= 1 << j; break;
} }
} }
@ -236,11 +231,11 @@ out1:
{ {
switch (id.flaginfo[j].flaguse) switch (id.flaginfo[j].flaguse)
{ {
case fu_unused: break; case fu_unused: break;
case fu_isjmp: isjmp = 1; flaglive |= 1 << j; break; case fu_isjmp: isjmp = 1; flaglive |= 1 << j; break;
case fu_maybecc: isjmp = 1; flaglive |= 1 << j; break; case fu_maybecc: isjmp = 1; flaglive |= 1 << j; break;
case fu_unknown: isjmp = 1; flaglive |= 1 << j; break; case fu_unknown: isjmp = 1; flaglive |= 1 << j; break;
case fu_used: flaglive |= 1 << j; break; case fu_used: flaglive |= 1 << j; break;
} }
} }
@ -318,19 +313,19 @@ out1:
switch (opcstr[pos]) switch (opcstr[pos])
{ {
case 'B': sz = sz_byte; break; case 'B': sz = sz_byte; break;
case 'W': sz = sz_word; break; case 'W': sz = sz_word; break;
case 'L': sz = sz_long; break; case 'L': sz = sz_long; break;
case 'z': case 'z':
switch (bitval[bitz]) switch (bitval[bitz])
{ {
case 0: sz = sz_byte; break; case 0: sz = sz_byte; break;
case 1: sz = sz_word; break; case 1: sz = sz_word; break;
case 2: sz = sz_long; break; case 2: sz = sz_long; break;
default: abort();
}
break;
default: abort(); default: abort();
}
break;
default: abort();
} }
} }
else else
@ -342,9 +337,9 @@ out1:
find = -1; find = -1;
switch (bitval[bitf]) switch (bitval[bitf])
{ {
case 0: mnemonic[mnp] = 'R'; break; case 0: mnemonic[mnp] = 'R'; break;
case 1: mnemonic[mnp] = 'L'; break; case 1: mnemonic[mnp] = 'L'; break;
default: abort(); default: abort();
} }
} }
@ -365,252 +360,252 @@ out1:
usesrc = 1; usesrc = 1;
switch (opcstr[pos++]) switch (opcstr[pos++])
{ {
case 'D': case 'D':
srcmode = Dreg; srcmode = Dreg;
switch (opcstr[pos++]) switch (opcstr[pos++])
{
case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
default: abort();
}
break;
case 'A':
srcmode = Areg;
switch (opcstr[pos++])
{
case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
default: abort();
}
switch (opcstr[pos])
{
case 'p': srcmode = Apdi; pos++; break;
case 'P': srcmode = Aipi; pos++; break;
}
break;
case 'L':
srcmode = absl;
break;
case '#':
switch (opcstr[pos++])
{
case 'z': srcmode = imm; break;
case '0': srcmode = imm0; break;
case '1': srcmode = imm1; break;
case '2': srcmode = imm2; break;
case 'i':
srcmode = immi; srcreg = (int32_t)(int8_t)bitval[biti];
if (CPU_EMU_SIZE < 4)
{ {
srctype = 1; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
srcgather = 1; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
srcpos = bitpos[biti]; default: abort();
} }
break; break;
case 'j': case 'A':
srcmode = immi; srcreg = bitval[bitj]; srcmode = Areg;
if (CPU_EMU_SIZE < 3) switch (opcstr[pos++])
{ {
srcgather = 1; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
srctype = 3; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
srcpos = bitpos[bitj]; default: abort();
} }
switch (opcstr[pos])
{
case 'p': srcmode = Apdi; pos++; break;
case 'P': srcmode = Aipi; pos++; break;
}
break; break;
case 'J':
srcmode = immi; srcreg = bitval[bitJ];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 2;
srcpos = bitpos[bitJ];
}
case 'L':
srcmode = absl;
break; break;
case 'k': case '#':
srcmode = immi; srcreg = bitval[bitk]; switch (opcstr[pos++])
if (CPU_EMU_SIZE < 3)
{ {
srcgather = 1; case 'z': srcmode = imm; break;
srctype = 4; case '0': srcmode = imm0; break;
srcpos = bitpos[bitk]; case '1': srcmode = imm1; break;
} case '2': srcmode = imm2; break;
case 'i':
srcmode = immi; srcreg = (int32_t)(int8_t)bitval[biti];
break; if (CPU_EMU_SIZE < 4)
case 'K':
srcmode = immi; srcreg = bitval[bitK];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 5;
srcpos = bitpos[bitK];
}
break;
case 'p':
srcmode = immi; srcreg = bitval[bitK];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 7;
srcpos = bitpos[bitp];
}
break;
default: abort();
}
break;
case 'd':
srcreg = bitval[bitD];
srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
if (srcmode == am_illg)
continue;
if (CPU_EMU_SIZE < 2
&& (srcmode == Areg || srcmode == Dreg || srcmode == Aind
|| srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
|| srcmode == Apdi))
{
srcgather = 1;
srcpos = bitpos[bitD];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == srcmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
}
else
{
if (opcstr[pos + 4] == '-')
{
if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
else
goto nomatch;
pos += 10;
}
else
{
while(mode_from_str(opcstr + pos) != srcmode)
{ {
pos += 4; srctype = 1;
srcgather = 1;
if (opcstr[pos] == ']') srcpos = bitpos[biti];
goto nomatch;
pos++;
} }
while(opcstr[pos] != ']')
pos++;
pos++;
break; break;
} case 'j':
srcmode = immi; srcreg = bitval[bitj];
if (CPU_EMU_SIZE < 3)
{
srcgather = 1;
srctype = 3;
srcpos = bitpos[bitj];
}
break;
case 'J':
srcmode = immi; srcreg = bitval[bitJ];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 2;
srcpos = bitpos[bitJ];
}
break;
case 'k':
srcmode = immi; srcreg = bitval[bitk];
if (CPU_EMU_SIZE < 3)
{
srcgather = 1;
srctype = 4;
srcpos = bitpos[bitk];
}
break;
case 'K':
srcmode = immi; srcreg = bitval[bitK];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 5;
srcpos = bitpos[bitK];
}
break;
case 'p':
srcmode = immi; srcreg = bitval[bitK];
if (CPU_EMU_SIZE < 5)
{
srcgather = 1;
srctype = 7;
srcpos = bitpos[bitp];
}
break;
default: abort();
} }
}
if (srcmode == imm || srcmode == PC16 || srcmode == PC8r) break;
goto nomatch; case 'd':
srcreg = bitval[bitD];
srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
break; if (srcmode == am_illg)
case 's': continue;
srcreg = bitval[bitS];
srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
if (srcmode == am_illg) if (CPU_EMU_SIZE < 2
continue; && (srcmode == Areg || srcmode == Dreg || srcmode == Aind
|| srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
if (CPU_EMU_SIZE < 2 || srcmode == Apdi))
&& (srcmode == Areg || srcmode == Dreg || srcmode == Aind
|| srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
|| srcmode == Apdi))
{
srcgather = 1;
srcpos = bitpos[bitS];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{ {
do srcgather = 1;
{ srcpos = bitpos[bitD];
pos++; }
if (mode_from_str(opcstr + pos) == srcmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
if (opcstr[pos] == '[')
{
pos++; pos++;
}
else
{
if (opcstr[pos + 4] == '-')
{
if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
else
goto nomatch;
pos += 10; if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == srcmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
} }
else else
{ {
while(mode_from_str(opcstr+pos) != srcmode) if (opcstr[pos + 4] == '-')
{ {
pos += 4; if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
if (opcstr[pos] == ']') else
goto nomatch; goto nomatch;
pos++; pos += 10;
} }
else
{
while(mode_from_str(opcstr + pos) != srcmode)
{
pos += 4;
if (opcstr[pos] == ']')
goto nomatch;
pos++;
}
while(opcstr[pos] != ']')
pos++;
while(opcstr[pos] != ']')
pos++; pos++;
break;
}
}
}
if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
goto nomatch;
break;
case 's':
srcreg = bitval[bitS];
srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
if (srcmode == am_illg)
continue;
if (CPU_EMU_SIZE < 2
&& (srcmode == Areg || srcmode == Dreg || srcmode == Aind
|| srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
|| srcmode == Apdi))
{
srcgather = 1;
srcpos = bitpos[bitS];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == srcmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++; pos++;
} }
else
{
if (opcstr[pos + 4] == '-')
{
if (mode_from_str(opcstr + pos) == srcmode)
srcmode = mode_from_str(opcstr + pos + 5);
else
goto nomatch;
pos += 10;
}
else
{
while(mode_from_str(opcstr+pos) != srcmode)
{
pos += 4;
if (opcstr[pos] == ']')
goto nomatch;
pos++;
}
while(opcstr[pos] != ']')
pos++;
pos++;
}
}
} }
} break;
break; default: abort();
default: abort();
} }
if (srcmode != Areg && srcmode != Dreg && srcmode != Aind if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
@ -632,196 +627,196 @@ out1:
switch (opcstr[pos++]) switch (opcstr[pos++])
{ {
case 'D': case 'D':
destmode = Dreg; destmode = Dreg;
switch (opcstr[pos++]) switch (opcstr[pos++])
{ {
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
default: abort(); default: abort();
} }
if (dstpos < 0 || dstpos >= 32) if (dstpos < 0 || dstpos >= 32)
abort(); abort();
break; break;
case 'A': case 'A':
destmode = Areg; destmode = Areg;
switch (opcstr[pos++]) switch (opcstr[pos++])
{ {
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
default: abort(); default: abort();
} }
if (dstpos < 0 || dstpos >= 32) if (dstpos < 0 || dstpos >= 32)
abort(); abort();
switch (opcstr[pos]) switch (opcstr[pos])
{ {
case 'p': destmode = Apdi; pos++; break; case 'p': destmode = Apdi; pos++; break;
case 'P': destmode = Aipi; pos++; break; case 'P': destmode = Aipi; pos++; break;
} }
break; break;
case 'L': case 'L':
destmode = absl; destmode = absl;
break; break;
case '#': case '#':
switch (opcstr[pos++]) switch (opcstr[pos++])
{ {
case 'z': destmode = imm; break; case 'z': destmode = imm; break;
case '0': destmode = imm0; break; case '0': destmode = imm0; break;
case '1': destmode = imm1; break; case '1': destmode = imm1; break;
case '2': destmode = imm2; break; case '2': destmode = imm2; break;
case 'i': destmode = immi; destreg = (int32_t)(int8_t)bitval[biti]; break; case 'i': destmode = immi; destreg = (int32_t)(int8_t)bitval[biti]; break;
case 'j': destmode = immi; destreg = bitval[bitj]; break; case 'j': destmode = immi; destreg = bitval[bitj]; break;
case 'J': destmode = immi; destreg = bitval[bitJ]; break; case 'J': destmode = immi; destreg = bitval[bitJ]; break;
case 'k': destmode = immi; destreg = bitval[bitk]; break; case 'k': destmode = immi; destreg = bitval[bitk]; break;
case 'K': destmode = immi; destreg = bitval[bitK]; break; case 'K': destmode = immi; destreg = bitval[bitK]; break;
default: abort(); default: abort();
} }
break; break;
case 'd': case 'd':
destreg = bitval[bitD]; destreg = bitval[bitD];
destmode = mode_from_mr(bitval[bitd],bitval[bitD]); destmode = mode_from_mr(bitval[bitd],bitval[bitD]);
if (destmode == am_illg) if (destmode == am_illg)
continue;
if (CPU_EMU_SIZE < 1
&& (destmode == Areg || destmode == Dreg || destmode == Aind
|| destmode == Ad16 || destmode == Ad8r || destmode == Aipi
|| destmode == Apdi))
{
dstgather = 1;
dstpos = bitpos[bitD];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == destmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
}
else
{
if (opcstr[pos+4] == '-')
{
if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
else
goto nomatch;
pos += 10;
}
else
{
while(mode_from_str(opcstr + pos) != destmode)
{
pos += 4;
if (opcstr[pos] == ']')
goto nomatch;
pos++;
}
while(opcstr[pos] != ']')
pos++;
pos++;
break;
}
}
}
if (destmode == imm || destmode == PC16 || destmode == PC8r)
goto nomatch;
break;
case 's':
destreg = bitval[bitS];
destmode = mode_from_mr(bitval[bits], bitval[bitS]);
if (destmode == am_illg)
continue; continue;
if (CPU_EMU_SIZE < 1
if (CPU_EMU_SIZE < 1 && (destmode == Areg || destmode == Dreg || destmode == Aind
&& (destmode == Areg || destmode == Dreg || destmode == Aind || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
|| destmode == Ad16 || destmode == Ad8r || destmode == Aipi || destmode == Apdi))
|| destmode == Apdi))
{
dstgather = 1;
dstpos = bitpos[bitD];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{ {
do dstgather = 1;
{ dstpos = bitpos[bitS];
pos++;
if (mode_from_str(opcstr + pos) == destmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
} }
else
{
if (opcstr[pos+4] == '-')
{
if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
else
goto nomatch;
pos += 10; if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == destmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
} }
else else
{ {
while(mode_from_str(opcstr + pos) != destmode) if (opcstr[pos+4] == '-')
{ {
pos += 4; if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
if (opcstr[pos] == ']') else
goto nomatch; goto nomatch;
pos++; pos += 10;
} }
while(opcstr[pos] != ']')
pos++;
pos++;
break;
}
}
}
if (destmode == imm || destmode == PC16 || destmode == PC8r)
goto nomatch;
break;
case 's':
destreg = bitval[bitS];
destmode = mode_from_mr(bitval[bits], bitval[bitS]);
if (destmode == am_illg)
continue;
if (CPU_EMU_SIZE < 1
&& (destmode == Areg || destmode == Dreg || destmode == Aind
|| destmode == Ad16 || destmode == Ad8r || destmode == Aipi
|| destmode == Apdi))
{
dstgather = 1;
dstpos = bitpos[bitS];
}
if (opcstr[pos] == '[')
{
pos++;
if (opcstr[pos] == '!')
{
do
{
pos++;
if (mode_from_str(opcstr + pos) == destmode)
goto nomatch;
pos += 4;
}
while (opcstr[pos] == ',');
pos++;
}
else
{
if (opcstr[pos+4] == '-')
{
if (mode_from_str(opcstr + pos) == destmode)
destmode = mode_from_str(opcstr + pos + 5);
else else
goto nomatch;
pos += 10;
}
else
{
while (mode_from_str(opcstr + pos) != destmode)
{ {
pos += 4; while (mode_from_str(opcstr + pos) != destmode)
{
pos += 4;
if (opcstr[pos] == ']') if (opcstr[pos] == ']')
goto nomatch; goto nomatch;
pos++;
}
while (opcstr[pos] != ']')
pos++;
pos++; pos++;
} }
while (opcstr[pos] != ']')
pos++;
pos++;
} }
} }
} break;
break; default: abort();
default: abort();
} }
if (destmode != Areg && destmode != Dreg && destmode != Aind if (destmode != Areg && destmode != Dreg && destmode != Aind
@ -890,7 +885,6 @@ nomatch:
void read_table68k(void) void read_table68k(void)
{ {
int i; int i;
table68k = (struct instr *)malloc(65536 * sizeof(struct instr));
for(i=0; i<65536; i++) for(i=0; i<65536; i++)
{ {
@ -920,24 +914,24 @@ static void handle_merges(long int opcode)
{ {
switch (table68k[opcode].stype) switch (table68k[opcode].stype)
{ {
case 0: case 0:
smsk = 7; sbitdst = 8; break; smsk = 7; sbitdst = 8; break;
case 1: case 1:
smsk = 255; sbitdst = 256; break; smsk = 255; sbitdst = 256; break;
case 2: case 2:
smsk = 15; sbitdst = 16; break; smsk = 15; sbitdst = 16; break;
case 3: case 3:
smsk = 7; sbitdst = 8; break; smsk = 7; sbitdst = 8; break;
case 4: case 4:
smsk = 7; sbitdst = 8; break; smsk = 7; sbitdst = 8; break;
case 5: case 5:
smsk = 63; sbitdst = 64; break; smsk = 63; sbitdst = 64; break;
case 7: case 7:
smsk = 3; sbitdst = 4; break; smsk = 3; sbitdst = 4; break;
default: default:
smsk = 0; sbitdst = 0; smsk = 0; sbitdst = 0;
abort(); abort();
break; break;
} }
smsk <<= table68k[opcode].spos; smsk <<= table68k[opcode].spos;

View File

@ -87,7 +87,7 @@ struct instr_def {
extern const struct instr_def defs68k[]; extern const struct instr_def defs68k[];
extern int n_defs68k; extern int n_defs68k;
extern struct instr { struct instr {
long int handler; long int handler;
unsigned char dreg; unsigned char dreg;
unsigned char sreg; unsigned char sreg;
@ -108,7 +108,9 @@ extern struct instr {
unsigned int clev:3; unsigned int clev:3;
unsigned int isjmp:1; unsigned int isjmp:1;
unsigned int unused2:4; unsigned int unused2:4;
} *table68k; };
extern struct instr table68k[];
extern void read_table68k(void); extern void read_table68k(void);
extern void do_merges(void); extern void do_merges(void);

View File

@ -31,23 +31,22 @@ enum { MT_IDLE, MT_PHASE1, MT_PHASE2 };
uint8_t mtMem[0x20000]; uint8_t mtMem[0x20000];
bool mtDirty; bool mtDirty;
uint8_t mtCommand = MT_NONE; static uint8_t mtCommand;
uint8_t mtState = MT_IDLE; static uint8_t mtState;
void MTStateMachine(uint8_t reg, uint16_t data); static void MTStateMachine(uint8_t reg, uint16_t data);
void MTInit(void) void MTInit(void)
{ {
memset(mtMem, 0xFF, 0x20000); memset(mtMem, 0xFF, 0x20000);
mtDirty = false; mtDirty = false;
MTReset();
} }
void MTReset(void) void MTReset(void)
{ {
} mtCommand = MT_NONE;
mtState = MT_IDLE;
void MTDone(void)
{
} }
uint16_t MTReadWord(uint32_t addr) uint16_t MTReadWord(uint32_t addr)
@ -115,7 +114,7 @@ void MTWriteLong(uint32_t addr, uint32_t data)
MTWriteWord(addr + 2, data >> 16); MTWriteWord(addr + 2, data >> 16);
} }
void MTStateMachine(uint8_t reg, uint16_t data) static void MTStateMachine(uint8_t reg, uint16_t data)
{ {
switch (mtState) switch (mtState)
{ {

View File

@ -6,7 +6,6 @@
void MTInit(void); void MTInit(void);
void MTReset(void); void MTReset(void);
void MTDone(void);
uint16_t MTReadWord(uint32_t addr); uint16_t MTReadWord(uint32_t addr);
uint32_t MTReadLong(uint32_t addr); uint32_t MTReadLong(uint32_t addr);

View File

@ -38,12 +38,8 @@
#define CONDITION_OP_FLAG_SET 3 #define CONDITION_OP_FLAG_SET 3
#define CONDITION_SECOND_HALF_LINE 4 #define CONDITION_SECOND_HALF_LINE 4
// Private function prototypes static void OPProcessFixedBitmap(uint64_t p0, uint64_t p1);
static void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2);
void OPProcessFixedBitmap(uint64_t p0, uint64_t p1, bool render);
void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2, bool render);
void OPDiscoverObjects(uint32_t address);
uint64_t OPLoadPhrase(uint32_t offset);
// Local global variables // Local global variables
@ -108,13 +104,7 @@ void OPReset(void)
static uint32_t object[8192]; static uint32_t object[8192];
static uint32_t numberOfObjects; static uint32_t numberOfObjects;
void OPDone(void) static bool OPObjectExists(uint32_t address)
{
numberOfObjects = 0;
OPDiscoverObjects(OPGetListPointer());
}
bool OPObjectExists(uint32_t address)
{ {
for(uint32_t i=0; i<numberOfObjects; i++) for(uint32_t i=0; i<numberOfObjects; i++)
{ {
@ -125,7 +115,7 @@ bool OPObjectExists(uint32_t address)
return false; return false;
} }
void OPDiscoverObjects(uint32_t address) static void OPDiscoverObjects(uint32_t address)
{ {
uint8_t objectType = 0; uint8_t objectType = 0;
@ -152,23 +142,17 @@ void OPDiscoverObjects(uint32_t address)
while (objectType != 4); while (objectType != 4);
} }
uint32_t OPGetListPointer(void) static uint32_t OPGetListPointer(void)
{ {
return GET16(tomRam8, 0x20) | (GET16(tomRam8, 0x22) << 16); return GET16(tomRam8, 0x20) | (GET16(tomRam8, 0x22) << 16);
} }
uint32_t OPGetStatusRegister(void) static uint32_t OPGetStatusRegister(void)
{ {
return GET16(tomRam8, 0x26); return GET16(tomRam8, 0x26);
} }
void OPSetStatusRegister(uint32_t data) static void OPSetCurrentObject(uint64_t object)
{
tomRam8[0x26] = (data & 0x0000FF00) >> 8;
tomRam8[0x27] |= (data & 0xFE);
}
void OPSetCurrentObject(uint64_t object)
{ {
tomRam8[0x17] = object & 0xFF; object >>= 8; tomRam8[0x17] = object & 0xFF; object >>= 8;
tomRam8[0x16] = object & 0xFF; object >>= 8; tomRam8[0x16] = object & 0xFF; object >>= 8;
@ -181,14 +165,13 @@ void OPSetCurrentObject(uint64_t object)
tomRam8[0x10] = object & 0xFF; tomRam8[0x10] = object & 0xFF;
} }
static uint64_t OPLoadPhrase(uint32_t offset)
uint64_t OPLoadPhrase(uint32_t offset)
{ {
offset &= ~0x07; offset &= ~0x07;
return ((uint64_t)JaguarReadLong(offset, OP) << 32) | (uint64_t)JaguarReadLong(offset+4, OP); return ((uint64_t)JaguarReadLong(offset, OP) << 32) | (uint64_t)JaguarReadLong(offset+4, OP);
} }
void OPStorePhrase(uint32_t offset, uint64_t p) static void OPStorePhrase(uint32_t offset, uint64_t p)
{ {
offset &= ~0x07; offset &= ~0x07;
JaguarWriteLong(offset, p >> 32, OP); JaguarWriteLong(offset, p >> 32, OP);
@ -198,7 +181,7 @@ void OPStorePhrase(uint32_t offset, uint64_t p)
// //
// Object Processor main routine // Object Processor main routine
// //
void OPProcessList(int halfline, bool render) void OPProcessList(int halfline)
{ {
halfline &= 0x7FF; halfline &= 0x7FF;
@ -222,7 +205,7 @@ void OPProcessList(int halfline, bool render)
if (halfline >= ypos && height > 0) if (halfline >= ypos && height > 0)
{ {
uint64_t p1 = OPLoadPhrase(oldOPP | 0x08); uint64_t p1 = OPLoadPhrase(oldOPP | 0x08);
OPProcessFixedBitmap(p0, p1, render); OPProcessFixedBitmap(p0, p1);
height--; height--;
@ -253,7 +236,7 @@ void OPProcessList(int halfline, bool render)
{ {
uint64_t p1 = OPLoadPhrase(oldOPP | 0x08); uint64_t p1 = OPLoadPhrase(oldOPP | 0x08);
uint64_t p2 = OPLoadPhrase(oldOPP | 0x10); uint64_t p2 = OPLoadPhrase(oldOPP | 0x10);
OPProcessScaledBitmap(p0, p1, p2, render); OPProcessScaledBitmap(p0, p1, p2);
uint16_t remainder = (p2 >> 16) & 0xFF; uint16_t remainder = (p2 >> 16) & 0xFF;
uint8_t vscale = p2 >> 8; uint8_t vscale = p2 >> 8;
@ -357,7 +340,7 @@ void OPProcessList(int halfline, bool render)
// //
// Store fixed size bitmap in line buffer // Store fixed size bitmap in line buffer
// //
void OPProcessFixedBitmap(uint64_t p0, uint64_t p1, bool render) static void OPProcessFixedBitmap(uint64_t p0, uint64_t p1)
{ {
uint8_t depth = (p1 >> 12) & 0x07; uint8_t depth = (p1 >> 12) & 0x07;
int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4; int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4;
@ -375,14 +358,13 @@ void OPProcessFixedBitmap(uint64_t p0, uint64_t p1, bool render)
uint32_t pitch = (p1 >> 15) & 0x07; uint32_t pitch = (p1 >> 15) & 0x07;
pitch <<= 3; pitch <<= 3;
uint8_t * tomRam8 = TOMGetRamPointer();
uint8_t * paletteRAM = &tomRam8[0x400]; uint8_t * paletteRAM = &tomRam8[0x400];
uint16_t * paletteRAM16 = (uint16_t *)paletteRAM; uint16_t * paletteRAM16 = (uint16_t *)paletteRAM;
if (iwidth == 0) if (iwidth == 0)
iwidth = 1; iwidth = 1;
if (!render || iwidth == 0) if (iwidth == 0)
return; return;
int32_t startPos = xpos, endPos = xpos + int32_t startPos = xpos, endPos = xpos +
@ -620,7 +602,7 @@ void OPProcessFixedBitmap(uint64_t p0, uint64_t p1, bool render)
// //
// Store scaled bitmap in line buffer // Store scaled bitmap in line buffer
// //
void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2, bool render) static void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2)
{ {
uint8_t depth = (p1 >> 12) & 0x07; uint8_t depth = (p1 >> 12) & 0x07;
int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4; int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4;
@ -636,7 +618,6 @@ void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2, bool render)
uint8_t index = (p1 >> 37) & 0xFE; uint8_t index = (p1 >> 37) & 0xFE;
uint32_t pitch = (p1 >> 15) & 0x07; uint32_t pitch = (p1 >> 15) & 0x07;
uint8_t * tomRam8 = TOMGetRamPointer();
uint8_t * paletteRAM = &tomRam8[0x400]; uint8_t * paletteRAM = &tomRam8[0x400];
uint16_t * paletteRAM16 = (uint16_t *)paletteRAM; uint16_t * paletteRAM16 = (uint16_t *)paletteRAM;
@ -645,7 +626,7 @@ void OPProcessScaledBitmap(uint64_t p0, uint64_t p1, uint64_t p2, bool render)
int32_t scaledWidthInPixels = (iwidth * phraseWidthToPixels[depth] * hscale) >> 5; int32_t scaledWidthInPixels = (iwidth * phraseWidthToPixels[depth] * hscale) >> 5;
uint32_t scaledPhrasePixels = (phraseWidthToPixels[depth] * hscale) >> 5; uint32_t scaledPhrasePixels = (phraseWidthToPixels[depth] * hscale) >> 5;
if (!render || iwidth == 0 || hscale == 0) if (iwidth == 0 || hscale == 0)
return; return;
int32_t startPos = xpos, endPos = xpos + int32_t startPos = xpos, endPos = xpos +

View File

@ -11,21 +11,11 @@ void OPInit(void);
void OPReset(void); void OPReset(void);
void OPDone(void); void OPDone(void);
uint64_t OPLoadPhrase(uint32_t offset); void OPProcessList(int scanline);
void OPProcessList(int scanline, bool render);
uint32_t OPGetListPointer(void);
void OPSetStatusRegister(uint32_t data);
uint32_t OPGetStatusRegister(void);
void OPSetCurrentObject(uint64_t object);
#define OPFLAG_RELEASE 8 // Bus release bit #define OPFLAG_RELEASE 8 // Bus release bit
#define OPFLAG_TRANS 4 // Transparency bit #define OPFLAG_TRANS 4 // Transparency bit
#define OPFLAG_RMW 2 // Read-Modify-Write bit #define OPFLAG_RMW 2 // Read-Modify-Write bit
#define OPFLAG_REFLECT 1 // Horizontal mirror bit #define OPFLAG_REFLECT 1 // Horizontal mirror bit
// Exported variables
extern uint8_t objectp_running;
#endif // __OBJECTP_H__ #endif // __OBJECTP_H__

View File

@ -202,14 +202,20 @@ RISC_OPCODE(store_r14_indexed)
{ {
uint32_t address = risc_reg[14] + (risc_convert_zero[IMM_1] << 2); uint32_t address = risc_reg[14] + (risc_convert_zero[IMM_1] << 2);
ALERT_UNALIGNED_LONG(address); ALERT_UNALIGNED_LONG(address);
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC); if (IS_RISC_RAM(address))
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
else
RISCWriteLong(address, RN, RISC);
} }
RISC_OPCODE(store_r15_indexed) RISC_OPCODE(store_r15_indexed)
{ {
uint32_t address = risc_reg[15] + (risc_convert_zero[IMM_1] << 2); uint32_t address = risc_reg[15] + (risc_convert_zero[IMM_1] << 2);
ALERT_UNALIGNED_LONG(address); ALERT_UNALIGNED_LONG(address);
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC); if (IS_RISC_RAM(address))
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
else
RISCWriteLong(address, RN, RISC);
} }
RISC_OPCODE(load_r14_ri) RISC_OPCODE(load_r14_ri)
@ -230,14 +236,20 @@ RISC_OPCODE(store_r14_ri)
{ {
uint32_t address = risc_reg[14] + RM; uint32_t address = risc_reg[14] + RM;
ALERT_UNALIGNED_LONG(address); ALERT_UNALIGNED_LONG(address);
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC); if (IS_RISC_RAM(address))
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
else
RISCWriteLong(address, RN, RISC);
} }
RISC_OPCODE(store_r15_ri) RISC_OPCODE(store_r15_ri)
{ {
uint32_t address = risc_reg[15] + RM; uint32_t address = risc_reg[15] + RM;
ALERT_UNALIGNED_LONG(address); ALERT_UNALIGNED_LONG(address);
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC); if (IS_RISC_RAM(address))
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
else
RISCWriteLong(address, RN, RISC);
} }
RISC_OPCODE(nop) RISC_OPCODE(nop)
@ -259,13 +271,16 @@ RISC_OPCODE(storew)
if (IS_RISC_RAM(RM)) if (IS_RISC_RAM(RM))
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC); RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
else else
JaguarWriteWord(RM & 0xFFFFFFFE, RN, RISC); JaguarWriteWord(RM, RN, RISC);
} }
RISC_OPCODE(store) RISC_OPCODE(store)
{ {
ALERT_UNALIGNED_LONG(RM); ALERT_UNALIGNED_LONG(RM);
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC); if (IS_RISC_RAM(RM))
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
else
RISCWriteLong(RM, RN, RISC);
} }
RISC_OPCODE(loadb) RISC_OPCODE(loadb)
@ -283,7 +298,7 @@ RISC_OPCODE(loadw)
if (IS_RISC_RAM(RM)) if (IS_RISC_RAM(RM))
RN = RISCReadLong(RM & 0xFFFFFFFC, RISC); RN = RISCReadLong(RM & 0xFFFFFFFC, RISC);
else else
RN = JaguarReadWord(RM & 0xFFFFFFFE, RISC); RN = JaguarReadWord(RM, RISC);
} }
RISC_OPCODE(load) RISC_OPCODE(load)

View File

@ -1,7 +1,7 @@
// //
// FILE.CPP // ROM.CPP
// //
// File support // ROM support
// by James Hammons // by James Hammons
// (C) 2010 Underground Software // (C) 2010 Underground Software
// //
@ -15,7 +15,7 @@
// JLH 06/01/2012 Added function to check ZIP file CRCs against file DB // JLH 06/01/2012 Added function to check ZIP file CRCs against file DB
// //
#include "file.h" #include "rom.h"
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
@ -24,7 +24,7 @@
#include "jaguar.h" #include "jaguar.h"
#include "memory.h" #include "memory.h"
bool JaguarLoadFile(uint8_t * buffer, uint32_t size) bool JaguarLoadROM(uint8_t * buffer, uint32_t size)
{ {
jaguarROMSize = size; jaguarROMSize = size;
@ -32,7 +32,7 @@ bool JaguarLoadFile(uint8_t * buffer, uint32_t size)
EepromInit(); EepromInit();
jaguarRunAddress = 0x802000; jaguarRunAddress = 0x802000;
int fileType = ParseFileType(buffer, jaguarROMSize); int fileType = ParseROMType(buffer, jaguarROMSize);
jaguarCartInserted = false; jaguarCartInserted = false;
if (fileType == JST_ROM) if (fileType == JST_ROM)
@ -92,7 +92,7 @@ bool JaguarLoadFile(uint8_t * buffer, uint32_t size)
return false; return false;
} }
bool AlpineLoadFile(uint8_t * buffer, uint32_t size) bool AlpineLoadROM(uint8_t * buffer, uint32_t size)
{ {
jaguarROMSize = size; jaguarROMSize = size;
@ -110,7 +110,7 @@ bool AlpineLoadFile(uint8_t * buffer, uint32_t size)
return true; return true;
} }
uint32_t ParseFileType(uint8_t * buffer, uint32_t size) uint32_t ParseROMType(uint8_t * buffer, uint32_t size)
{ {
if (buffer[0] == 0x60 && buffer[1] == 0x1B) if (buffer[0] == 0x60 && buffer[1] == 0x1B)
return JST_ABS_TYPE1; return JST_ABS_TYPE1;

View File

@ -0,0 +1,19 @@
//
// ROM.H
//
// ROM support
//
#ifndef __ROM_H__
#define __ROM_H__
#include <stdint.h>
// JST = Jaguar Software Type
enum { JST_NONE = 0, JST_ROM, JST_ALPINE, JST_ABS_TYPE1, JST_ABS_TYPE2, JST_JAGSERVER, JST_WTFOMGBBQ };
bool JaguarLoadROM(uint8_t * buffer, uint32_t size);
bool AlpineLoadROM(uint8_t * buffer, uint32_t size);
uint32_t ParseROMType(uint8_t * buffer, uint32_t size);
#endif // __ROM_H__

View File

@ -79,11 +79,11 @@
#define BOTTOM_VISIBLE_VC_PAL 579 #define BOTTOM_VISIBLE_VC_PAL 579
uint8_t tomRam8[0x4000]; uint8_t tomRam8[0x4000];
uint32_t tomWidth, tomHeight; static uint32_t tomWidth, tomHeight;
uint32_t tomTimerPrescaler; static uint32_t tomTimerPrescaler;
uint32_t tomTimerDivider; static uint32_t tomTimerDivider;
int32_t tomTimerCounter; static int32_t tomTimerCounter;
uint16_t tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending, static uint16_t tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
tom_gpu_int_pending, tom_video_int_pending; tom_gpu_int_pending, tom_video_int_pending;
static uint32_t * scanlines[256]; static uint32_t * scanlines[256];
@ -91,15 +91,13 @@ static uint32_t scanlineWidths[256];
typedef void (render_xxx_scanline_fn)(uint32_t *); typedef void (render_xxx_scanline_fn)(uint32_t *);
// Private function prototypes static void tom_render_16bpp_cry_scanline(uint32_t * backbuffer);
static void tom_render_24bpp_scanline(uint32_t * backbuffer);
static void tom_render_16bpp_direct_scanline(uint32_t * backbuffer);
static void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer);
static void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer);
void tom_render_16bpp_cry_scanline(uint32_t * backbuffer); static render_xxx_scanline_fn * scanline_render[] =
void tom_render_24bpp_scanline(uint32_t * backbuffer);
void tom_render_16bpp_direct_scanline(uint32_t * backbuffer);
void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer);
void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer);
render_xxx_scanline_fn * scanline_render[] =
{ {
tom_render_16bpp_cry_scanline, tom_render_16bpp_cry_scanline,
tom_render_24bpp_scanline, tom_render_24bpp_scanline,
@ -111,11 +109,13 @@ render_xxx_scanline_fn * scanline_render[] =
tom_render_16bpp_rgb_scanline tom_render_16bpp_rgb_scanline
}; };
static void TOMResetPIT(void);
static uint32_t RGB16ToRGB32[0x10000]; static uint32_t RGB16ToRGB32[0x10000];
static uint32_t CRY16ToRGB32[0x10000]; static uint32_t CRY16ToRGB32[0x10000];
static uint32_t MIX16ToRGB32[0x10000]; static uint32_t MIX16ToRGB32[0x10000];
void TOMFillLookupTables(void) static void TOMFillLookupTables(void)
{ {
for(uint32_t i=0; i<0x10000; i++) for(uint32_t i=0; i<0x10000; i++)
RGB16ToRGB32[i] = RGB16ToRGB32[i] =
@ -138,12 +138,7 @@ void TOMFillLookupTables(void)
} }
} }
void TOMSetPendingJERRYInt(void) static void TOMSetPendingTimerInt(void)
{
tom_jerry_int_pending = 1;
}
void TOMSetPendingTimerInt(void)
{ {
tom_timer_int_pending = 1; tom_timer_int_pending = 1;
} }
@ -163,32 +158,17 @@ void TOMSetPendingVideoInt(void)
tom_video_int_pending = 1; tom_video_int_pending = 1;
} }
uint8_t * TOMGetRamPointer(void) static uint8_t TOMGetVideoMode(void)
{
return tomRam8;
}
uint8_t TOMGetVideoMode(void)
{ {
uint16_t vmode = GET16(tomRam8, VMODE); uint16_t vmode = GET16(tomRam8, VMODE);
return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1); return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
} }
uint16_t TOMGetVDB(void)
{
return GET16(tomRam8, VDB);
}
uint16_t TOMGetHC(void) uint16_t TOMGetHC(void)
{ {
return GET16(tomRam8, HC); return GET16(tomRam8, HC);
} }
uint16_t TOMGetVP(void)
{
return GET16(tomRam8, VP);
}
uint16_t TOMGetMEMCON1(void) uint16_t TOMGetMEMCON1(void)
{ {
return GET16(tomRam8, MEMCON1); return GET16(tomRam8, MEMCON1);
@ -197,7 +177,7 @@ uint16_t TOMGetMEMCON1(void)
// //
// 16 BPP CRY/RGB mixed mode rendering // 16 BPP CRY/RGB mixed mode rendering
// //
void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer) static void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer)
{ {
uint16_t width = tomWidth; uint16_t width = tomWidth;
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800]; uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
@ -232,7 +212,7 @@ void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer)
// //
// 16 BPP CRY mode rendering // 16 BPP CRY mode rendering
// //
void tom_render_16bpp_cry_scanline(uint32_t * backbuffer) static void tom_render_16bpp_cry_scanline(uint32_t * backbuffer)
{ {
uint16_t width = tomWidth; uint16_t width = tomWidth;
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800]; uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
@ -267,7 +247,7 @@ void tom_render_16bpp_cry_scanline(uint32_t * backbuffer)
// //
// 24 BPP mode rendering // 24 BPP mode rendering
// //
void tom_render_24bpp_scanline(uint32_t * backbuffer) static void tom_render_24bpp_scanline(uint32_t * backbuffer)
{ {
uint16_t width = tomWidth; uint16_t width = tomWidth;
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800]; uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
@ -304,7 +284,7 @@ void tom_render_24bpp_scanline(uint32_t * backbuffer)
// //
// 16 BPP direct mode rendering // 16 BPP direct mode rendering
// //
void tom_render_16bpp_direct_scanline(uint32_t * backbuffer) static void tom_render_16bpp_direct_scanline(uint32_t * backbuffer)
{ {
uint16_t width = tomWidth; uint16_t width = tomWidth;
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800]; uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
@ -321,7 +301,7 @@ void tom_render_16bpp_direct_scanline(uint32_t * backbuffer)
// //
// 16 BPP RGB mode rendering // 16 BPP RGB mode rendering
// //
void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer) static void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
{ {
uint16_t width = tomWidth; uint16_t width = tomWidth;
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800]; uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
@ -356,7 +336,7 @@ void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
// //
// Process a single halfline // Process a single halfline
// //
void TOMExecHalfline(uint16_t halfline, bool render) void TOMExecHalfline(uint16_t halfline)
{ {
uint16_t field2 = halfline & 0x0800; uint16_t field2 = halfline & 0x0800;
halfline &= 0x07FF; halfline &= 0x07FF;
@ -373,17 +353,14 @@ void TOMExecHalfline(uint16_t halfline, bool render)
if ((halfline >= startingHalfline) && (halfline < endingHalfline)) if ((halfline >= startingHalfline) && (halfline < endingHalfline))
{ {
if (render) uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
{ uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
if (GET16(tomRam8, VMODE) & BGEN) if (GET16(tomRam8, VMODE) & BGEN)
for(uint32_t i=0; i<720; i++) for(uint32_t i=0; i<720; i++)
*current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO; *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
OPProcessList(halfline, render); OPProcessList(halfline);
}
} }
else else
inActiveDisplayArea = false; inActiveDisplayArea = false;
@ -424,7 +401,7 @@ void TOMInit(void)
{ {
for (uint32_t i = 0; i < 256; i++) for (uint32_t i = 0; i < 256; i++)
{ {
scanlines[i] = alloc_invisible<uint32_t>(LCM_SCREEN_WIDTH); scanlines[i] = alloc_invisible<uint32_t>(MAX_SCREEN_WIDTH);
} }
TOMFillLookupTables(); TOMFillLookupTables();
@ -433,19 +410,13 @@ void TOMInit(void)
TOMReset(); TOMReset();
} }
void TOMDone(void) static uint32_t TOMGetVideoModeWidth(void)
{
OPDone();
BlitterDone();
}
uint32_t TOMGetVideoModeWidth(void)
{ {
uint16_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1; uint16_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
return LCM_SCREEN_WIDTH / pwidth; return MAX_SCREEN_WIDTH / pwidth;
} }
uint32_t TOMGetVideoModeHeight(void) static uint32_t TOMGetVideoModeHeight(void)
{ {
return (vjs.hardwareTypeNTSC ? 240 : 256); return (vjs.hardwareTypeNTSC ? 240 : 256);
} }
@ -561,6 +532,23 @@ uint16_t TOMReadWord(uint32_t offset, uint32_t who)
return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who); return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
} }
#define MASK(x) 0xFF00 >> (24 - x), 0xFF
static const uint8_t videoRegMasks[22]
{
MASK(12), // 0x28 VMODE 11 - 0
MASK(16), // 0x2A BORDH 15 - 0
MASK(16), // 0x2C BORDL 15 - 0
MASK(10), // 0x2E HP 9 - 0
MASK(11), // 0x30 HBB 10 - 0
MASK(11), // 0x32 HBE 10 - 0
MASK(11), // 0x34 HS 10 - 0
MASK(11), // 0x36 HVE 10 - 0
MASK(11), // 0x38 HDB1 10 - 0
MASK(11), // 0x3A HDB2 10 - 0
MASK(11), // 0x3C HDE 10 - 0
};
#undef MASK
// //
// TOM byte access (write) // TOM byte access (write)
// //
@ -572,8 +560,6 @@ void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who)
if ((offset < 0xF00000) || (offset > 0xF03FFF)) if ((offset < 0xF00000) || (offset > 0xF03FFF))
return; return;
tomRam8[offset & 0x3FFF] = data;
if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20)) if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
{ {
GPUWriteByte(offset, data, who); GPUWriteByte(offset, data, who);
@ -595,7 +581,6 @@ void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{ {
tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data; tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
TOMResetPIT(); TOMResetPIT();
return;
} }
else if (offset == 0xF00052) else if (offset == 0xF00052)
{ {
@ -611,7 +596,17 @@ void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who)
{ {
offset &= 0x5FF; offset &= 0x5FF;
tomRam8[offset] = data, tomRam8[offset + 0x200] = data; tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
return;
} }
offset &= 0x3FFF;
if (offset == 0x54)
data &= 0x03;
else if (offset >= 0x28 && offset <= 0x3D)
data &= videoRegMasks[offset - 0x28];
tomRam8[offset] = data;
} }
// //
@ -625,30 +620,23 @@ void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who)
if ((offset < 0xF00000) || (offset > 0xF03FFF)) if ((offset < 0xF00000) || (offset > 0xF03FFF))
return; return;
tomRam8[(offset + 0) & 0x3FFF] = data >> 8;
tomRam8[(offset + 1) & 0x3FFF] = data & 0xFF;
if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20)) if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
{ {
GPUWriteWord(offset, data, who); GPUWriteWord(offset, data, who);
return;
} }
else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000)) else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
{ {
GPUWriteWord(offset, data, who); GPUWriteWord(offset, data, who);
return;
} }
else if (offset == 0xF00050) else if (offset == 0xF00050)
{ {
tomTimerPrescaler = data; tomTimerPrescaler = data;
TOMResetPIT(); TOMResetPIT();
return;
} }
else if (offset == 0xF00052) else if (offset == 0xF00052)
{ {
tomTimerDivider = data; tomTimerDivider = data;
TOMResetPIT(); TOMResetPIT();
return;
} }
else if (offset == 0xF000E0) else if (offset == 0xF000E0)
{ {
@ -666,21 +654,24 @@ void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who)
else if ((offset >= 0xF02200) && (offset <= 0xF0229F)) else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
{ {
BlitterWriteWord(offset, data, who); BlitterWriteWord(offset, data, who);
return;
} }
else if (offset >= 0xF00400 && offset <= 0xF007FE) else if (offset >= 0xF00400 && offset <= 0xF007FE)
{ {
offset &= 0x5FF; offset &= 0x5FF;
SET16(tomRam8, offset, data); SET16(tomRam8, offset, data);
SET16(tomRam8, offset + 0x200, data); SET16(tomRam8, offset + 0x200, data);
return;
} }
offset &= 0x3FFF; offset &= 0x3FFF;
if (offset >= 0x30 && offset <= 0x4E) if (offset == 0x54)
data &= 0x07FF;
if (offset == 0x2E || offset == 0x36 || offset == 0x54)
data &= 0x03FF; data &= 0x03FF;
else if (offset >= 0x28 && offset <= 0x3C)
data &= (videoRegMasks[offset - 0x28] << 8) | videoRegMasks[offset - 0x27];
tomRam8[(offset + 0) & 0x3FFF] = data >> 8;
tomRam8[(offset + 1) & 0x3FFF] = data & 0xFF;
if ((offset >= 0x28) && (offset <= 0x4F)) if ((offset >= 0x28) && (offset <= 0x4F))
{ {
@ -698,9 +689,9 @@ int TOMIRQEnabled(int irq)
return tomRam8[INT1 + 1] & (1 << irq); return tomRam8[INT1 + 1] & (1 << irq);
} }
void TOMPITCallback(void); static void TOMPITCallback(void);
void TOMResetPIT(void) static void TOMResetPIT(void)
{ {
RemoveCallback(TOMPITCallback); RemoveCallback(TOMPITCallback);
@ -711,26 +702,7 @@ void TOMResetPIT(void)
} }
} }
void TOMExecPIT(uint32_t cycles) static void TOMPITCallback(void)
{
if (tomTimerPrescaler)
{
tomTimerCounter -= cycles;
if (tomTimerCounter <= 0)
{
TOMSetPendingTimerInt();
GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);
if (TOMIRQEnabled(IRQ_TIMER))
m68k_set_irq(2);
TOMResetPIT();
}
}
}
void TOMPITCallback(void)
{ {
TOMSetPendingTimerInt(); TOMSetPendingTimerInt();
GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);
@ -748,17 +720,16 @@ void TOMStartFrame(void)
void TOMBlit(uint32_t * videoBuffer, int32_t & width, int32_t & height) void TOMBlit(uint32_t * videoBuffer, int32_t & width, int32_t & height)
{ {
uint32_t lines = vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL; uint32_t const lines = vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL;
uint32_t targetWidth = scanlineWidths[0]; uint32_t targetWidth = scanlineWidths[0];
bool multiWidth = false; bool multiWidth = false;
for (uint32_t i = 1; i < lines; i++) for (uint32_t i = 1; i < lines; i++)
{ {
if (targetWidth < scanlineWidths[i]) uint32_t const w = scanlineWidths[i];
{ multiWidth |= targetWidth != w;
targetWidth = scanlineWidths[i]; if (targetWidth < w)
multiWidth = true; targetWidth = w;
}
} }
if (!targetWidth) // skip rendering this I guess? if (!targetWidth) // skip rendering this I guess?
@ -768,21 +739,21 @@ void TOMBlit(uint32_t * videoBuffer, int32_t & width, int32_t & height)
return; return;
} }
if (__builtin_expect(multiWidth, false)) if (multiWidth)
{ {
for (uint32_t i = 0; i < lines; i++) for (uint32_t i = 0; i < lines; i++)
{ {
uint32_t const w = scanlineWidths[i]; uint32_t const w = scanlineWidths[i];
if (__builtin_expect(LCM_SCREEN_WIDTH == w, false)) if (__builtin_expect(MAX_SCREEN_WIDTH == w, false))
{ {
memcpy(videoBuffer, scanlines[i], LCM_SCREEN_WIDTH * sizeof(uint32_t)); memcpy(videoBuffer, scanlines[i], MAX_SCREEN_WIDTH * sizeof(uint32_t));
videoBuffer += LCM_SCREEN_WIDTH; videoBuffer += MAX_SCREEN_WIDTH;
} }
else if (__builtin_expect(w > 0, true)) else if (__builtin_expect(w > 0, true))
{ {
uint32_t wf = LCM_SCREEN_WIDTH / w; uint32_t const wf = MAX_SCREEN_WIDTH / w;
uint32_t * src = scanlines[i]; uint32_t * src = scanlines[i];
uint32_t * dstNext = videoBuffer + LCM_SCREEN_WIDTH; uint32_t const * const dstNext = videoBuffer + MAX_SCREEN_WIDTH;
for (uint32_t x = 0; x < w; x++) for (uint32_t x = 0; x < w; x++)
{ {
for (uint32_t n = 0; n < wf; n++) for (uint32_t n = 0; n < wf; n++)
@ -794,7 +765,7 @@ void TOMBlit(uint32_t * videoBuffer, int32_t & width, int32_t & height)
} }
else else
{ {
videoBuffer += LCM_SCREEN_WIDTH; // skip rendering this line videoBuffer += MAX_SCREEN_WIDTH; // skip rendering this line
} }
} }
} }
@ -807,6 +778,6 @@ void TOMBlit(uint32_t * videoBuffer, int32_t & width, int32_t & height)
} }
} }
width = multiWidth ? LCM_SCREEN_WIDTH : targetWidth; width = multiWidth ? MAX_SCREEN_WIDTH : targetWidth;
height = lines; height = lines;
} }

View File

@ -16,7 +16,7 @@
#define VIRTUAL_SCREEN_HEIGHT_NTSC 240 #define VIRTUAL_SCREEN_HEIGHT_NTSC 240
#define VIRTUAL_SCREEN_HEIGHT_PAL 256 #define VIRTUAL_SCREEN_HEIGHT_PAL 256
#define LCM_SCREEN_WIDTH (VIRTUAL_SCREEN_WIDTH * 4) #define MAX_SCREEN_WIDTH (VIRTUAL_SCREEN_WIDTH * 4)
// 68000 Interrupt bit positions (enabled at $F000E0) // 68000 Interrupt bit positions (enabled at $F000E0)
@ -24,47 +24,24 @@ enum { IRQ_VIDEO = 0, IRQ_GPU, IRQ_OPFLAG, IRQ_TIMER, IRQ_DSP };
void TOMInit(void); void TOMInit(void);
void TOMReset(void); void TOMReset(void);
void TOMDone(void);
uint8_t TOMReadByte(uint32_t offset, uint32_t who = UNKNOWN); uint8_t TOMReadByte(uint32_t offset, uint32_t who = UNKNOWN);
uint16_t TOMReadWord(uint32_t offset, uint32_t who = UNKNOWN); uint16_t TOMReadWord(uint32_t offset, uint32_t who = UNKNOWN);
void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN); void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who = UNKNOWN);
void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN); void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who = UNKNOWN);
void TOMExecHalfline(uint16_t halfline, bool render); void TOMExecHalfline(uint16_t halfline);
uint32_t TOMGetVideoModeWidth(void);
uint32_t TOMGetVideoModeHeight(void);
uint8_t TOMGetVideoMode(void);
uint8_t * TOMGetRamPointer(void);
uint16_t TOMGetHDB(void);
uint16_t TOMGetVDB(void);
uint16_t TOMGetHC(void); uint16_t TOMGetHC(void);
uint16_t TOMGetVP(void);
uint16_t TOMGetMEMCON1(void); uint16_t TOMGetMEMCON1(void);
void TOMDumpIORegistersToLog(void);
int TOMIRQEnabled(int irq); int TOMIRQEnabled(int irq);
uint16_t TOMIRQControlReg(void);
void TOMSetIRQLatch(int irq, int enabled);
void TOMExecPIT(uint32_t cycles);
void TOMSetPendingJERRYInt(void);
void TOMSetPendingTimerInt(void);
void TOMSetPendingObjectInt(void); void TOMSetPendingObjectInt(void);
void TOMSetPendingGPUInt(void); void TOMSetPendingGPUInt(void);
void TOMSetPendingVideoInt(void); void TOMSetPendingVideoInt(void);
void TOMResetPIT(void);
void TOMStartFrame(void); void TOMStartFrame(void);
void TOMBlit(uint32_t * framebuffer, int32_t & width, int32_t & height); void TOMBlit(uint32_t * framebuffer, int32_t & width, int32_t & height);
// Exported variables
extern uint32_t tomWidth;
extern uint32_t tomHeight;
extern uint8_t tomRam8[]; extern uint8_t tomRam8[];
extern uint32_t tomTimerPrescaler;
extern uint32_t tomTimerDivider;
extern int32_t tomTimerCounter;
#endif // __TOM_H__ #endif // __TOM_H__