// by James L. Hammons
//
-#include <string.h>
#include <dirent.h>
#include <SDL.h>
+#include <string>
+#include <vector>
+#include <algorithm>
#include "types.h"
#include "tom.h"
+#include "video.h"
#include "font1.h"
#include "gui.h"
-// Private function prototypes
+using namespace std; // For STL stuff
-uint32 CountROMFiles(char * path);
+// Private function prototypes
void InitGUI(void)
{
}
-//
-// Render the backbuffer to the primary screen surface
-//
-void BlitBackbuffer(void)
-{
- extern SDL_Surface * surface, * mainSurface;
- extern int16 * backbuffer;
-
- if (SDL_MUSTLOCK(surface))
- while (SDL_LockSurface(surface) < 0)
- SDL_Delay(10);
-
- memcpy(surface->pixels, backbuffer, tom_getVideoModeWidth() * tom_getVideoModeHeight() * 2);
-
- if (SDL_MUSTLOCK(surface))
- SDL_UnlockSurface(surface);
-
- SDL_Rect srcrect, dstrect;
- srcrect.x = srcrect.y = 0, srcrect.w = surface->w, srcrect.h = surface->h;
- dstrect.x = dstrect.y = 0, dstrect.w = surface->w, dstrect.h = surface->h;
- SDL_BlitSurface(surface, &srcrect, mainSurface, &dstrect);
- SDL_Flip(mainSurface);
-}
-
//
// Draw text at the given x/y coordinates. Can invert text as well.
//
-void DrawText(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
+void DrawString(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
{
char string[4096];
va_list arg;
vsprintf(string, text, arg);
va_end(arg);
- uint32 pitch = TOMGetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
+ uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
uint32 length = strlen(string), address = x + (y * pitch);
for(uint32 i=0; i<length; i++)
//
// Very very crude GUI file selector
//
-#ifndef FILENAME_MAX
-#define FILENAME_MAX 2048
-#endif
bool UserSelectFile(char * path, char * filename)
{
extern int16 * backbuffer;
- uint32 numFiles = CountROMFiles(path);
+ vector<string> fileList;
- if (numFiles == 0)
- return false;
+ // Read in the candidate files from the directory pointed to by "path"
- char * names = (char *)malloc(numFiles * FILENAME_MAX);
-
- if (names == NULL)
- {
- WriteLog("Could not allocate memory for %u files!\nAborting!\n", numFiles);
- return false;
- }
-
- int i = 0;
DIR * dp = opendir(path);
dirent * de;
while ((de = readdir(dp)) != NULL)
{
char * ext = strrchr(de->d_name, '.');
+
if (ext != NULL)
- {
if (stricmp(ext, ".zip") == 0 || stricmp(ext, ".jag") == 0)
- {
- // Do a QnD insertion sort...
- // (Yeah, it's n^2/2 time, but there aren't that many items...)
- uint32 pos = 0;
-
- for(int k=0; k<i; k++)
- {
- if (stricmp(&names[k * FILENAME_MAX], de->d_name) < 0)
- pos++;
- else
- break;
- }
-
- uint32 blockSize = (i - pos) * FILENAME_MAX;
-
- if (blockSize)
-//This only works on Win32 for some reason...
-// memcpy(&names[(pos + 1) * FILENAME_MAX], &names[pos * FILENAME_MAX], blockSize);
- for(int k=blockSize-1; k>=0; k--)
- names[((pos + 1) * FILENAME_MAX) + k] = names[(pos * FILENAME_MAX) + k];
-
- strcpy(&names[pos * FILENAME_MAX], de->d_name);
- i++;
- }
- }
+ fileList.push_back(string(de->d_name));
}
closedir(dp);
uint32 cursor = 0, startFile = 0;
- if (numFiles > 1) // Only go GUI if more than one possibility!
+ if (fileList.size() > 1) // Only go GUI if more than one possibility!
{
+ sort(fileList.begin(), fileList.end());
+
bool done = false;
- uint32 limit = (numFiles > 24 ? 24 : numFiles);
+ uint32 limit = (fileList.size() > 24 ? 24 : fileList.size());
SDL_Event event;
while (!done)
for(uint32 i=0; i<limit; i++)
{
bool invert = (cursor == i ? true : false);
- char buf[41];
- // Guarantee that we clip our strings to fit in the screen...
- memcpy(buf, &names[(startFile + i) * FILENAME_MAX], 38);
- buf[38] = 0;
- DrawText(backbuffer, 0, i*8, invert, " %s ", buf);
+ // Clip our strings to guarantee that they fit on the screen...
+ string s = fileList[startFile + i];
+ if (s.length() > 38)
+ s[38] = 0;
+ DrawString(backbuffer, 0, i*8, invert, " %s ", s.c_str());
}
- BlitBackbuffer();
+ RenderBackbuffer();
if (event.type == SDL_KEYDOWN)
{
cursor++;
else // Otherwise, scroll the window...
{
- if (cursor + startFile != numFiles - 1)
+ if (cursor + startFile != fileList.size() - 1)
startFile++;
}
}
{
// Advance cursor to filename with first letter pressed...
uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
- for(uint32 i=0; i<numFiles; i++)
+
+ for(uint32 i=0; i<fileList.size(); i++)
{
- if ((names[i * FILENAME_MAX] & 0xDF) == which)
+ if ((fileList[i][0] & 0xDF) == which)
{
cursor = i - startFile;
if (i > startFile + limit - 1)
}
strcpy(filename, path);
- // Potential GPF here: If length of dir is zero, then this will cause a page fault!
- if (path[strlen(path) - 1] != '/')
- strcat(filename, "/");
- strcat(filename, &names[(cursor + startFile) * FILENAME_MAX]);
- free(names);
-
- return true;
-}
-
-//
-// Count # of possible ROM files in the current directory
-//
-uint32 CountROMFiles(char * path)
-{
- uint32 numFiles = 0;
- DIR * dp = opendir(path);
- if (dp == NULL)
- {
- WriteLog("VJ: Could not open directory \"%s\"!\nAborting!\n", path);
- return 0;
- }
- else
- {
- dirent * de;
+ if (strlen(path) > 0)
+ if (path[strlen(path) - 1] != '/')
+ strcat(filename, "/");
- while ((de = readdir(dp)) != NULL)
- {
- char * ext = strrchr(de->d_name, '.');
- if (ext != NULL)
- if (stricmp(ext, ".zip") == 0 || stricmp(ext, ".jag") == 0)
- numFiles++;
- }
+ strcat(filename, fileList[startFile + cursor].c_str());
- closedir(dp);
- }
-
- return numFiles;
+ return true;
}
#ifndef __GUI_H__
#define __GUI_H__
-void BlitBackbuffer(void);
-void DrawText(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void DrawString(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
bool UserSelectFile(char * path, char * filename);
+#ifdef __cplusplus
+}
+#endif
+
#endif // __GUI_H__
#ifndef __JAGUAR_H__
#define __JAGUAR_H__
+#include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
#include "types.h"
#include "log.h"
#include "version.h"
//
#include "jaguar.h"
+#include "video.h"
//#include "m68kdasmAG.h"
#define CPU_DEBUG
// External variables
-extern bool hardwareTypeNTSC; // Set to false for PAL
+extern bool hardwareTypeNTSC; // Set to false for PAL
#ifdef CPU_DEBUG_MEMORY
-extern bool startMemLog; // Set by "e" key
+extern bool startMemLog; // Set by "e" key
extern int effect_start;
extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
#endif
// These values are overridden by command line switches...
-bool dsp_enabled = false;
-bool jaguar_use_bios = true; // Default is now to USE the BIOS
+extern bool dsp_enabled;
+extern bool jaguar_use_bios; // Default is now to USE the BIOS
uint32 jaguar_active_memory_dumps = 0;
uint32 jaguar_mainRom_crc32;
void M68KInstructionHook(void)
{
uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
+/* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
+ {
+ static char buffer[2048];
+ m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
+ WriteLog("%08X: %s", m68kPC, buffer);
+ WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
+ m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
+ m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
+ }//*/
/* if (m68kPC == 0x8D0E48 && effect_start5)
{
WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
M68K_show_context();
log_done();
exit(0);
- }
+ }//*/
}
//
else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
JERRYWriteWord(address, value, M68K);
else
+ {
jaguar_unknown_writeword(address, value, M68K);
+ WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
+ m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
+ m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
+ }
}
void m68k_write_memory_32(unsigned int address, unsigned int value)
// Unknown read/write byte/word routines
//
+// It's hard to believe that developers would be sloppy with their memory writes, yet in
+// some cases the developers screwed up royal. E.g., Club Drive has the following code:
+//
+// 807EC4: movea.l #$f1b000, A1
+// 807ECA: movea.l #$8129e0, A0
+// 807ED0: move.l A0, D0
+// 807ED2: move.l #$f1bb94, D1
+// 807ED8: sub.l D0, D1
+// 807EDA: lsr.l #2, D1
+// 807EDC: move.l (A0)+, (A1)+
+// 807EDE: dbra D1, 807edc
+//
+// The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
+// in. This mistake causes it to try and overwrite approximately $700000 worth of address
+// space! (That is, unless the 68K causes a bus error...)
+
void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
{
#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
{
//TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
-//if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
-//WriteLog("[JWW16] --> Possible GPU RAM mirror access! [%08X]", offset);
-//if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
-// WriteLog("JagWW: Writing %04X at %08X\n", data, offset);
+// PLUS, you would handle this in the GPU/DSP WroteLong code! Not here!
offset &= 0xFFFFFF;
-
+
if (offset <= 0x3FFFFE)
{
+if (offset == 0x670C)
+ WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);
+
jaguar_mainRam[(offset+0) & 0x3FFFFF] = (data>>8) & 0xFF;
jaguar_mainRam[(offset+1) & 0x3FFFFF] = data & 0xFF;
return;
}
- else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
+ else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
{
CDROMWriteWord(offset, data, who);
return;
}
- else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
+ else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
{
TOMWriteWord(offset, data, who);
return;
}
- else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
+ else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
{
JERRYWriteWord(offset, data, who);
return;
}
-
+ // Don't bomb on attempts to write to ROM
+ else if (offset >= 0x800000 && offset <= 0xEFFFFF)
+ return;
+
jaguar_unknown_writeword(offset, data, who);
}
memory_malloc_secure((void **)&jaguar_mainRom, 0x600000, "Jaguar 68K CPU ROM");
memset(jaguar_mainRam, 0x00, 0x400000);
// memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
- memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
+// memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
+ memset(jaguar_mainRom, 0x01, 0x600000); // & set it to all 01s...
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\Brain Dead 13.cdi");
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\baldies.cdi");
jaguar_dasm(0x802B00, 500);
WriteLog("\n");//*/
-/* WriteLog("\n\nM68000 disassembly at $8099F8...\n");
+/* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
jaguar_dasm(0x809900, 500);
WriteLog("\n");//*/
//8099F8
+/* WriteLog("\n\nDump of $8093C8:\n\n");
+ for(int i=0x8093C8; i<0x809900; i+=4)
+ WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
+/* WriteLog("\n\nM68000 disassembly at $90006C...\n");
+ jaguar_dasm(0x90006C, 500);
+ WriteLog("\n");//*/
// WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
if (!(i & 0x01)) // Execute OP only on even lines (non-interlaced only!)
{
tom_exec_scanline(backbuffer, i/2, render); // i/2 is a kludge...
- backbuffer += TOMGetSDLScreenPitch() / 2; // Convert bytes to words...
+ backbuffer += GetSDLScreenPitch() / 2; // Convert bytes to words...
}
}
}
#include <time.h>
#include <SDL.h>
#include "jaguar.h"
+#include "video.h"
#define BUTTON_U 0
#define BUTTON_D 1
// Private function prototypes
-void main_screen_switch(void);
+//void main_screen_switch(void);
// Global vars
bool startMemLog = false;
-void main_screen_switch(void)
-{
- extern SDL_Surface * mainSurface;
- extern Uint32 mainSurfaceFlags;
- extern bool fullscreen;
-
- fullscreen = !fullscreen;
- mainSurfaceFlags &= ~SDL_FULLSCREEN;
- if (fullscreen)
- mainSurfaceFlags |= SDL_FULLSCREEN;
-
- mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
-
- if (mainSurface == NULL)
- {
- WriteLog("Joystick: SDL is unable to set the video mode: %s\n", SDL_GetError());
- exit(1);
- }
-
- SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");
-}
-
void joystick_init(void)
{
joystick_reset();
iLeft = iRight = false;
if ((keystate[SDLK_LALT] || keystate[SDLK_RALT]) & keystate[SDLK_RETURN])
- main_screen_switch();
+ ToggleFullscreen();
/* Added/Changed by SDLEMU (http://sdlemu.ngemu.com) */
// F02298 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z0 - Z0
// ------------------------------------------------------------
-#include <SDL.h>
+//#include <SDL.h>
#include "tom.h"
+#include "video.h"
#include "gpu.h"
#include "objectp.h"
#include "cry2rgb.h"
#define BG 0x58
#define INT1 0xE0
+// Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks)
+/*#define LEFT_VISIBLE_HC 208
+#define RIGHT_VISIBLE_HC 1528//*/
+#define LEFT_VISIBLE_HC 208
+#define RIGHT_VISIBLE_HC 1488
+
//This can be defined in the makefile as well...
//(It's easier to do it here, though...)
//#define TOM_DEBUG
render_xxx_scanline_fn * scanline_render[8];
+// Screen info for various games...
+/*
+Doom
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 123
+TOM: Vertical Display Begin written by M68K: 25
+TOM: Vertical Display End written by M68K: 2047
+TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
+Also does PWIDTH = 4...
+Vertical resolution: 238 lines
+
+Rayman
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 123
+TOM: Vertical Display Begin written by M68K: 25
+TOM: Vertical Display End written by M68K: 2047
+TOM: Vertical Interrupt written by M68K: 507
+TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
+TOM: Horizontal Display Begin 1 written by M68K: 208
+TOM: Horizontal Display End written by M68K: 1670
+Display starts at 31, then 52!
+Vertical resolution: 238 lines
+
+Atari Karts
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 123
+TOM: Vertical Display Begin written by M68K: 25
+TOM: Vertical Display End written by M68K: 2047
+TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
+TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
+Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
+
+Iron Soldier
+TOM: Vertical Interrupt written by M68K: 2047
+TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 123
+TOM: Vertical Display Begin written by M68K: 25
+TOM: Vertical Display End written by M68K: 2047
+TOM: Vertical Interrupt written by M68K: 507
+TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
+TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
+TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
+Display starts at 31
+Vertical resolution: 238 lines
+[Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
+
+JagMania
+TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
+TOM: Horizontal Blank Begin written by M68K: 1713
+TOM: Horizontal Blank End written by M68K: 125
+TOM: Horizontal Display End written by M68K: 1696
+TOM: Horizontal Display Begin 1 written by M68K: 166
+TOM: Vertical Period written by M68K: 523 (non-interlaced)
+TOM: Vertical Blank End written by M68K: 24
+TOM: Vertical Display Begin written by M68K: 46
+TOM: Vertical Display End written by M68K: 496
+TOM: Vertical Blank Begin written by M68K: 500
+TOM: Vertical Sync written by M68K: 517
+TOM: Vertical Interrupt written by M68K: 497
+TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
+Display starts at 55
+
+Double Dragon V
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 123
+TOM: Vertical Display Begin written by M68K: 25
+TOM: Vertical Display End written by M68K: 2047
+TOM: Vertical Interrupt written by M68K: 507
+TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
+
+Dino Dudes
+TOM: Horizontal Display End written by M68K: 1823
+TOM: Horizontal Display Begin 1 written by M68K: 45
+TOM: Vertical Display Begin written by M68K: 40
+TOM: Vertical Display End written by M68K: 2047
+TOM: Vertical Interrupt written by M68K: 491
+TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
+Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
+Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
+Vertical resolution: 238 lines
+
+Flashback
+TOM: Horizontal Display End written by M68K: 1727
+TOM: Horizontal Display Begin 1 written by M68K: 188
+TOM: Vertical Display Begin written by M68K: 1
+TOM: Vertical Display End written by M68K: 2047
+TOM: Vertical Interrupt written by M68K: 483
+TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
+Width would be 303 with above scheme, but border width would be 13 pixels
+
+Trevor McFur
+Vertical resolution: 238 lines
+*/
+
+
void tom_calc_cry_rgb_mix_lut(void)
{
memory_malloc_secure((void **)&tom_cry_rgb_mix_lut, 2 * 0x10000, "CRY/RGB mixed mode LUT");
uint16 width = tom_width;
uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800];
+ //New stuff--restrict our drawing...
+ uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
+ //NOTE: May have to check HDB2 as well!
+ int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks
+ startPos /= pwidth;
+ if (startPos < 0)
+ current_line_buffer += 2 * -startPos;
+ else
+ backbuffer += 2 * startPos, width -= startPos;
+
while (width)
{
uint16 color = (*current_line_buffer++) << 8;
uint16 width = tom_width;
uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800];
+ //New stuff--restrict our drawing...
+ uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
+ //NOTE: May have to check HDB2 as well!
+ int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks
+ startPos /= pwidth;
+ if (startPos < 0)
+ current_line_buffer += 2 * -startPos;
+ else
+ backbuffer += 2 * startPos, width -= startPos;
+
while (width)
{
uint16 color = (*current_line_buffer++) << 8;
uint16 width = tom_width;
uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800];
+ //New stuff--restrict our drawing...
+ uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
+ //NOTE: May have to check HDB2 as well!
+ int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks
+ startPos /= pwidth;
+ if (startPos < 0)
+ current_line_buffer += 4 * -startPos;
+ else
+ backbuffer += 2 * startPos, width -= startPos;
+
while (width)
{
+ // This is NOT a good 8 -> 5 bit RGB conversion! (It saturates values below 8
+ // to zero and throws away almost *half* the color resolution!)
uint16 green = (*current_line_buffer++) >> 3;
uint16 red = (*current_line_buffer++) >> 3;
current_line_buffer++;
uint16 width = tom_width;
uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800];
+ //New stuff--restrict our drawing...
+ uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
+ //NOTE: May have to check HDB2 as well!
+ int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks
+ startPos /= pwidth;
+ if (startPos < 0)
+ current_line_buffer += 2 * -startPos;
+ else
+ backbuffer += 2 * startPos, width -= startPos;
+
while (width)
{
uint16 color = (*current_line_buffer++) << 8;
}
}
-uint32 TOMGetSDLScreenPitch(void)
-{
- extern SDL_Surface * surface;
-
- return surface->pitch;
-}
-
//
// TOM initialization
//
// return width[(GET16(tom_ram_8, VMODE) & PWIDTH) >> 9];
// Now, we just calculate it...
- uint16 hdb1 = GET16(tom_ram_8, HDB1), hde = GET16(tom_ram_8, HDE),
+/* uint16 hdb1 = GET16(tom_ram_8, HDB1), hde = GET16(tom_ram_8, HDE),
hbb = GET16(tom_ram_8, HBB), pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
// return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
//Temporary, for testing Doom...
- return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth = 8 ? 4 : pwidth);
+ return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
+
+ // To make it easier to make a quasi-fixed display size, we restrict the viewing
+ // area to an arbitrary range of the Horizontal Count.
+ uint16 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1;
+// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / pwidth;
+//Temporary, for testing Doom...
+ return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
// More speculating...
// According to the JTRM, the number of potential pixels across is given by the
// which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
// to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
// backbuffer + 5 pixels).
+
+// That's basically what we're doing now...!
}
// *** SPECULATION ***
// It might work better to virtualize the height settings, i.e., set the vertical
// height at 240 lines and clip using the VDB and VDE/VP registers...
-// Same with the width...
+// Same with the width... [Width is pretty much virtualized now.]
uint32 tom_getVideoModeHeight(void)
{
WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
if (offset == VMODE)
WriteLog("TOM: Video Mode written by %s: %04X. PWIDTH = %u, MODE = %s, flags:%s%s (VC = %u)\n", whoName[who], data, ((data >> 9) & 0x07) + 1, videoMode_to_str[(data & MODE) >> 1], (data & BGEN ? " BGEN" : ""), (data & VARMOD ? " VARMOD" : ""), GET16(tom_ram_8, VC));
-/*#define MODE 0x0006 // Line buffer to video generator mode
-#define BGEN 0x0080 // Background enable (CRY & RGB16 only)
-#define VARMOD 0x0100 // Mixed CRY/RGB16 mode
-#define PWIDTH 0x0E00 // Pixel width in video clock cycles (value written + 1)*/
// detect screen resolution changes
//This may go away in the future, if we do the virtualized screen thing...
+//This may go away soon!
if ((offset >= 0x28) && (offset <= 0x4F))
{
uint32 width = tom_getVideoModeWidth(), height = tom_getVideoModeHeight();
tom_real_internal_width = width;
-//This looks like an attempt to render non-square pixels (though wrong...)
-/* if (width == 640)
- {
- memcpy(scanline_render, scanline_render_stretch, sizeof(scanline_render));
- width = 320;
- }
- else
- memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));//*/
-
if ((width != tom_width) || (height != tom_height))
{
- extern SDL_Surface * surface, * mainSurface;
- extern Uint32 mainSurfaceFlags;
- static char window_title[256];
+// extern SDL_Surface * surface, * mainSurface;
+// extern Uint32 mainSurfaceFlags;
+// static char window_title[256];
tom_width = width, tom_height = height;
- SDL_FreeSurface(surface);
+ ResizeScreen(tom_width, tom_height);
+/* SDL_FreeSurface(surface);
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, tom_width, tom_height,
16, 0x7C00, 0x03E0, 0x001F, 0);
if (surface == NULL)
}
sprintf(window_title, "Virtual Jaguar (%i x %i)", (int)tom_width, (int)tom_height);
-//???Should we do this??? No!
-// SDL_FreeSurface(mainSurface);
mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
if (mainSurface == NULL)
exit(1);
}
- SDL_WM_SetCaption(window_title, window_title);
+ SDL_WM_SetCaption(window_title, window_title);//*/
}
}
}