3123 lines
103 KiB
C++
3123 lines
103 KiB
C++
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Name: sharpmz.cpp
|
|
// Created: July 2018
|
|
// Author(s): Philip Smart
|
|
// Description: Sharp MZ series MiSTer Menu Add-On.
|
|
// This module is an extension to the MiSTer control program. It adds extensions to
|
|
// the menu system and additional I/O control specific to the Sharp MZ series
|
|
// emulation.
|
|
//
|
|
// Credits:
|
|
// Copyright: (c) 2018 Philip Smart <philip.smart@net2net.org>
|
|
//
|
|
// History: July 2018 - Initial module written.
|
|
// Sept 2018 - Synchronised with main MiSTer codebase.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// This source file is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published
|
|
// by the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This source file is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
#include "malloc.h"
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include "../../hardware.h"
|
|
#include "../../fpga_io.h"
|
|
#include "sharpmz.h"
|
|
#include "../../osd.h"
|
|
#include "../../menu.h"
|
|
#include "../../debug.h"
|
|
#include "../../user_io.h"
|
|
|
|
// Names of the supported machines.
|
|
//
|
|
static const char *MZMACHINES[MAX_MZMACHINES] = { "MZ80K", "MZ80C", "MZ1200", "MZ80A", "MZ700", "MZ800", "MZ80B", "MZ2000" };
|
|
|
|
#define sharpmz_debugf(a, ...)
|
|
//#define sharpmz_debugf(a, ...) printf("\033[1;31mSHARPMZ: " a "\033[0m\n", ##__VA_ARGS__)
|
|
#define sharpmz__x_debugf(a, ...)
|
|
//#define sharpmz_x_debugf(a, ...) printf("\033[1;32mSHARPMZ: " a "\033[0m\n", ##__VA_ARGS__)
|
|
|
|
static sharpmz_config_t config;
|
|
static uint8_t sector_buffer[1024];
|
|
static sharpmz_tape_header_t tapeHeader;
|
|
static tape_queue_t tapeQueue;
|
|
|
|
// Method to open a file for writing.
|
|
//
|
|
int sharpmz_file_write(fileTYPE *file, const char *fileName)
|
|
{
|
|
int ret;
|
|
char fullPath[1024];
|
|
|
|
sprintf(fullPath, "%s/%s/%s", getRootDir(), SHARPMZ_CORE_NAME, fileName);
|
|
|
|
const int mode = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | S_IRWXU | S_IRWXG | S_IRWXO;
|
|
ret = FileOpenEx(file, fullPath, mode);
|
|
if (!ret)
|
|
{
|
|
sharpmz_debugf("sharpmz_file_write (FileOpenEx) - File:%s, error: %d.\n", fullPath, ret);
|
|
}
|
|
|
|
// Success.
|
|
return 1;
|
|
}
|
|
|
|
// Method to load a rom into the emulator.
|
|
//
|
|
void sharpmz_set_rom(romData_t &image)
|
|
{
|
|
if(image.romEnabled)
|
|
{
|
|
sharpmz_debugf("Rom enabled: sharpmz_set_rom(%04x, %04x, %s)\n", image.loadAddr, image.loadSize, image.romFileName);
|
|
sharpmz_send_file(image, 0);
|
|
} else
|
|
{
|
|
sharpmz_debugf("Rom not enabled: sharpmz_set_rom(%04x, %04x, %s)\n", image.loadAddr, image.loadSize, image.romFileName);
|
|
}
|
|
}
|
|
|
|
// Save current configuration to SD Card.
|
|
//
|
|
int sharpmz_save_config(void)
|
|
{
|
|
FileSaveConfig(SHARPMZ_CONFIG_FILENAME, &config, sizeof(config));
|
|
|
|
// For calls from the UI, return a state to progress on to.
|
|
//
|
|
return(MENU_SHARPMZ_MAIN1);
|
|
}
|
|
|
|
// Method to reset the emulator.
|
|
//
|
|
void sharpmz_reset(unsigned long preResetSleep, unsigned long postResetSleep)
|
|
{
|
|
// Set the reset bit.
|
|
//
|
|
config.system_ctrl |= 1;
|
|
user_io_8bit_set_status(config.system_ctrl, (1));
|
|
|
|
// Sleep and hold device in reset for given period.
|
|
//
|
|
if(preResetSleep > 0)
|
|
usleep(preResetSleep);
|
|
|
|
// Remove reset.
|
|
//
|
|
config.system_ctrl &= ~(1);
|
|
user_io_8bit_set_status(config.system_ctrl, (1));
|
|
|
|
// Sleep and hold device in reset for given period.
|
|
//
|
|
if(postResetSleep > 0)
|
|
usleep(postResetSleep);
|
|
}
|
|
|
|
// Reset the configuration to inbuilt defaults.
|
|
//
|
|
int sharpmz_reset_config(short setStatus)
|
|
{
|
|
int i;
|
|
char buf[1024];
|
|
|
|
// Setup config defaults.
|
|
//
|
|
config.system_ctrl = 0;
|
|
for(i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
config.system_reg[i] = 0x00; // sharpmz_read_config_register(i);
|
|
}
|
|
for(i=0; i < MAX_MZMACHINES; i++)
|
|
{
|
|
sprintf(buf, "%s_mrom.ROM", MZMACHINES[i]);
|
|
strcpy(config.romMonitor[i][MONITOR].romFileName, buf);
|
|
config.romMonitor[i][MONITOR].romEnabled = 0;
|
|
config.romMonitor[i][MONITOR].loadAddr = MZLOADADDR[MROM_IDX][i];
|
|
config.romMonitor[i][MONITOR].loadSize = MZLOADSIZE[MROM_IDX][i];
|
|
sprintf(buf, "%s_80c_mrom.ROM", MZMACHINES[i]);
|
|
strcpy(config.romMonitor[i][MONITOR_80C].romFileName, buf);
|
|
config.romMonitor[i][MONITOR_80C].romEnabled = 0;
|
|
config.romMonitor[i][MONITOR_80C].loadAddr = MZLOADADDR[MROM_80C_IDX][i];
|
|
config.romMonitor[i][MONITOR_80C].loadSize = MZLOADSIZE[MROM_80C_IDX][i];
|
|
sprintf(buf, "%s_cgrom.ROM", MZMACHINES[i]);
|
|
strcpy(config.romCG[i].romFileName, buf);
|
|
config.romCG[i].romEnabled = 0;
|
|
config.romCG[i].loadAddr = MZLOADADDR[CGROM_IDX][i];
|
|
config.romCG[i].loadSize = MZLOADSIZE[CGROM_IDX][i];
|
|
sprintf(buf, "%s_keymap.ROM", MZMACHINES[i]);
|
|
strcpy(config.romKeyMap[i].romFileName, buf);
|
|
config.romKeyMap[i].romEnabled = 0;
|
|
config.romKeyMap[i].loadAddr = MZLOADADDR[KEYMAP_IDX][i];
|
|
config.romKeyMap[i].loadSize = MZLOADSIZE[KEYMAP_IDX][i];
|
|
sprintf(buf, "%s_user.ROM", MZMACHINES[i]);
|
|
strcpy(config.romUser[i].romFileName, buf);
|
|
config.romUser[i].romEnabled = 0;
|
|
config.romUser[i].loadAddr = MZLOADADDR[USERROM_IDX][i];
|
|
config.romUser[i].loadSize = MZLOADSIZE[USERROM_IDX][i];
|
|
sprintf(buf, "%s_fdc.ROM", MZMACHINES[i]);
|
|
strcpy(config.romFDC[i].romFileName, buf);
|
|
config.romFDC[i].romEnabled = 0;
|
|
config.romFDC[i].loadAddr = MZLOADADDR[FDCROM_IDX][i];
|
|
config.romFDC[i].loadSize = MZLOADSIZE[FDCROM_IDX][i];
|
|
}
|
|
|
|
// Set the status values.
|
|
//
|
|
if(setStatus)
|
|
{
|
|
user_io_8bit_set_status(config.system_ctrl, 0xffffffff);
|
|
|
|
// Set the registers.
|
|
//
|
|
for(int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_set_config_register(i, config.system_reg[i]);
|
|
}
|
|
}
|
|
|
|
// For calls from the UI, return a state to progress on to.
|
|
//
|
|
return(MENU_SHARPMZ_MAIN1);
|
|
}
|
|
|
|
// Load the configuration from the HPS.
|
|
//
|
|
int sharpmz_reload_config(short setStatus)
|
|
{
|
|
short success = 0;
|
|
|
|
// Try to load config from the filesystem.
|
|
//
|
|
int size = FileLoadConfig(SHARPMZ_CONFIG_FILENAME, 0, 0);
|
|
if (size > 0 && size == sizeof(sharpmz_config_t))
|
|
{
|
|
FileLoadConfig(SHARPMZ_CONFIG_FILENAME, &config, sizeof(sharpmz_config_t));
|
|
success = 1;
|
|
sharpmz_debugf("Config loaded successfully.");
|
|
}
|
|
else
|
|
{
|
|
sharpmz_debugf("No %s config found, creating using defaults", SHARPMZ_CONFIG_FILENAME);
|
|
sharpmz_reset_config(0);
|
|
sharpmz_save_config();
|
|
}
|
|
|
|
// Set the status values and control registers as requested..
|
|
//
|
|
if(setStatus && success)
|
|
{
|
|
user_io_8bit_set_status(config.system_ctrl, 0xffffffff);
|
|
|
|
// Set the registers.
|
|
//
|
|
for(int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_set_config_register(i, config.system_reg[i]);
|
|
}
|
|
}
|
|
|
|
// Let caller know if we succeeded to load config.
|
|
//
|
|
return(success);
|
|
}
|
|
|
|
// Initialisation of the machine, upload roms etc.
|
|
//
|
|
void sharpmz_init(void)
|
|
{
|
|
int i;
|
|
|
|
sharpmz_debugf("Sharp MZ Series Initialisation");
|
|
|
|
// Necessary sleep to allow the reset to complete and the registers to become available.
|
|
//
|
|
usleep(50000);
|
|
|
|
// Try and load the SD config.
|
|
//
|
|
if(sharpmz_reload_config(0) == 0)
|
|
{
|
|
// Set configuration to default in case we cannot load the file based configuration.
|
|
//
|
|
sharpmz_reset_config(0);
|
|
}
|
|
|
|
// Setup the status values based on the config.
|
|
//
|
|
user_io_8bit_set_status(config.system_ctrl, 0xffffffff);
|
|
|
|
// Set the control registers according to config.
|
|
//
|
|
for(int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_set_config_register(i, config.system_reg[i]);
|
|
}
|
|
|
|
// Upload defined rom files.
|
|
//
|
|
for(i=0; i < MAX_MZMACHINES; i++)
|
|
{
|
|
// Load given machine rom images at defined addresses.
|
|
//
|
|
sharpmz_set_rom(config.romMonitor[i][0]);
|
|
sharpmz_set_rom(config.romMonitor[i][1]);
|
|
sharpmz_set_rom(config.romCG[i]);
|
|
sharpmz_set_rom(config.romKeyMap[i]);
|
|
}
|
|
|
|
// Debug, show registers.
|
|
for(i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_debugf("Register (%02x) = %02x", i, sharpmz_read_config_register(i));
|
|
}
|
|
|
|
// Initialise tape queue.
|
|
//
|
|
tapeQueue.top=tapeQueue.bottom = NULL;
|
|
tapeQueue.elements = 0;
|
|
|
|
sharpmz_debugf("Initialisation complete.");
|
|
}
|
|
|
|
// Poll handler, perform any periodic tasks via this hook.
|
|
//
|
|
void sharpmz_poll(void)
|
|
{
|
|
// Locals.
|
|
static unsigned long time = GetTimer(0);
|
|
unsigned long timeElapsed;
|
|
char *fileName;
|
|
|
|
// Get elapsed time since last poll.
|
|
//
|
|
timeElapsed = GetTimer(0) - time;
|
|
|
|
// Every 2 seconds (READY signal takes 1 second to become active after previous load) to see if the tape buffer is empty.
|
|
//
|
|
if(timeElapsed > 2000)
|
|
{
|
|
// Check to see if the Tape READY signal is inactive, if it is and we have items in the queue, load up the next
|
|
// tape file and send it.
|
|
//
|
|
if( !((sharpmz_read_config_register(REGISTER_CMT)) & 0x01) )
|
|
{
|
|
// Check the tape queue, if items available, pop oldest and upload.
|
|
//
|
|
if(tapeQueue.elements > 0)
|
|
{
|
|
fileName = sharpmz_pop_filename();
|
|
if(fileName != 0)
|
|
{
|
|
sharpmz_debugf("Loading tape: %s\n", fileName);
|
|
sharpmz_load_tape_to_ram(fileName, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check to see if the RECORD_READY flag is set.
|
|
if( !((sharpmz_read_config_register(REGISTER_CMT)) & 0x04) )
|
|
{
|
|
// Ok, so now see if the auto save feature is enabled.
|
|
//
|
|
if(config.autoSave)
|
|
{
|
|
// Save the CMT cache ram to file. The action of reading will reset the READY flag.
|
|
//
|
|
sharpmz_save_tape_from_cmt((const char *)0);
|
|
}
|
|
}
|
|
|
|
// Reset the timer.
|
|
time = GetTimer(0);
|
|
}
|
|
}
|
|
|
|
// Method to push a tape filename onto the queue.
|
|
//
|
|
void sharpmz_push_filename(char *fileName)
|
|
{
|
|
// Locals.
|
|
tape_queue_node_t *ptr=(tape_queue_node_t *)malloc(sizeof(tape_queue_node_t));
|
|
|
|
// Copy filename into queue.
|
|
strcpy(ptr->fileName, fileName);
|
|
|
|
// Tag onto end of queue.
|
|
ptr->next=NULL;
|
|
if (tapeQueue.top == NULL && tapeQueue.bottom == NULL)
|
|
{
|
|
tapeQueue.top=tapeQueue.bottom = ptr;
|
|
}
|
|
else
|
|
{
|
|
tapeQueue.top->next = ptr;
|
|
tapeQueue.top = ptr;
|
|
}
|
|
tapeQueue.elements++;
|
|
}
|
|
|
|
// Method to read the oldest tape filename entered and return it.
|
|
//
|
|
char *sharpmz_pop_filename(void)
|
|
{
|
|
// Locals.
|
|
tape_queue_node_t *ptr;
|
|
static char fileName[MAX_FILENAME_SIZE];
|
|
|
|
// Queue empty, just return.
|
|
if(tapeQueue.bottom == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Get item in a FIFO order.
|
|
ptr=tapeQueue.bottom;
|
|
if(tapeQueue.top == tapeQueue.bottom)
|
|
{
|
|
tapeQueue.top = NULL;
|
|
}
|
|
tapeQueue.bottom = tapeQueue.bottom->next;
|
|
|
|
// Store in static buffer and free node.
|
|
strcpy(fileName, ptr->fileName);
|
|
tapeQueue.elements--;
|
|
free(ptr);
|
|
|
|
// Return filename.
|
|
return(fileName);
|
|
}
|
|
|
|
// Method to iterate through the list of filenames.
|
|
//
|
|
char *sharpmz_get_next_filename(char reset)
|
|
{
|
|
static tape_queue_node_t *ptr = NULL;
|
|
|
|
// Queue empty, just return.
|
|
if(tapeQueue.bottom == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Reset is active, start at beginning of list.
|
|
//
|
|
if(reset || ptr == NULL)
|
|
{
|
|
ptr = tapeQueue.bottom;
|
|
} else
|
|
{
|
|
// At end of list, stop.
|
|
if(ptr != NULL)
|
|
{
|
|
ptr = ptr->next;
|
|
}
|
|
}
|
|
|
|
// Return filename if available.
|
|
//
|
|
return(ptr == NULL ? 0 : index(ptr->fileName, '/')+1);
|
|
}
|
|
|
|
// Method to clear the queued tape list.
|
|
//
|
|
void sharpmz_clear_filelist(void)
|
|
{
|
|
// Locals.
|
|
tape_queue_node_t *ptr;
|
|
|
|
// Queue empty, just return.
|
|
if(tapeQueue.bottom == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Go from bottom to top, freeing the bottom item in each iteration.
|
|
for(ptr=tapeQueue.bottom; ptr != NULL; ptr=tapeQueue.bottom)
|
|
{
|
|
tapeQueue.bottom = ptr->next;
|
|
free(ptr);
|
|
}
|
|
tapeQueue.top = NULL;
|
|
tapeQueue.elements = 0;
|
|
}
|
|
|
|
// Return fast tape status bits. Bit 0,1 of system_reg, 0 = Off, 1 = 2x, 2 = 4x, 3 = 16x
|
|
//
|
|
int sharpmz_get_fasttape(void)
|
|
{
|
|
return (config.system_reg[REGISTER_CMT] & 0x00000007);
|
|
}
|
|
|
|
// Get the group to which the current machine belongs:
|
|
// 0 - MZ80K/C/A type
|
|
// 1 - MZ700 type
|
|
// 2 - MZ80B/2000 type
|
|
//
|
|
short sharpmz_get_machine_group(void)
|
|
{
|
|
short machineModel = config.system_reg[REGISTER_MODEL] & 0x07;
|
|
short machineGroup = 0;
|
|
|
|
// Set value according to machine model.
|
|
//
|
|
switch(machineModel)
|
|
{
|
|
// These machines currently underdevelopment, so fall through to MZ80K
|
|
case MZ80B_IDX: // MZ80B
|
|
case MZ2000_IDX: // MZ2000
|
|
machineGroup = 2;
|
|
|
|
case MZ80K_IDX: // MZ80K
|
|
case MZ80C_IDX: // MZ80C
|
|
case MZ1200_IDX: // MZ1200
|
|
case MZ80A_IDX: // MZ80A
|
|
machineGroup = 0;
|
|
break;
|
|
|
|
case MZ700_IDX: // MZ700
|
|
case MZ800_IDX: // MZ800
|
|
machineGroup = 1;
|
|
break;
|
|
|
|
default:
|
|
machineGroup = 0;
|
|
break;
|
|
}
|
|
|
|
return(machineGroup);
|
|
}
|
|
|
|
// Return string showing Fast Tape mode.
|
|
//
|
|
const char *sharpmz_get_fasttape_string(void)
|
|
{
|
|
short fastTape = (config.system_reg[REGISTER_CMT]) & 0x00000007;
|
|
|
|
return(SHARPMZ_FAST_TAPE[ (sharpmz_get_machine_group() * 8) + fastTape ]);
|
|
}
|
|
|
|
// Set fast tape status bits to given value.
|
|
//
|
|
void sharpmz_set_fasttape(short mode, short setStatus)
|
|
{
|
|
short machineGroup = sharpmz_get_machine_group();
|
|
|
|
// Clear out current setting.
|
|
config.system_reg[REGISTER_CMT] &= ~0x07;
|
|
|
|
if((machineGroup == 0 && mode > 5) || (machineGroup == 1 && mode > 5) || (machineGroup == 2 && mode > 4)) mode = 0;
|
|
config.system_reg[REGISTER_CMT] |= (mode & 0x07);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_CMT, config.system_reg[REGISTER_CMT]);
|
|
}
|
|
|
|
// Return tape buttons status bits. Bit 2, 3 of system_reg, 0 = Off, 1 = Play, 2 = Record, 3 = Auto.
|
|
//
|
|
int sharpmz_get_tape_buttons(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_CMT] >> 3) & 0x00000003 );
|
|
}
|
|
|
|
// Return string showing tape buttons setting.
|
|
//
|
|
const char *sharpmz_get_tape_buttons_string(void)
|
|
{
|
|
short tapeSW = (config.system_reg[REGISTER_CMT] >> 3) & 0x00000003;
|
|
|
|
return(SHARPMZ_TAPE_BUTTONS[ tapeSW ]);
|
|
}
|
|
|
|
// Set tape buttons status bits to given value.
|
|
//
|
|
void sharpmz_set_tape_buttons(short mode, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_CMT] &= ~(3 << 3);
|
|
config.system_reg[REGISTER_CMT] |= (mode & 0x03) << 3;
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_CMT, config.system_reg[REGISTER_CMT]);
|
|
}
|
|
|
|
// Method to return the next memory bank name string in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_memory_bank(void)
|
|
{
|
|
static short memoryBank = SHARPMZ_MEMBANK_SYSROM;
|
|
|
|
if(memoryBank == 1) memoryBank = SHARPMZ_MEMBANK_SYSRAM; // SYSROM spans 2 physical banks.
|
|
if(memoryBank >= SHARPMZ_MEMBANK_MAXBANKS) memoryBank = SHARPMZ_MEMBANK_SYSROM; // Loop round when we get to the end.
|
|
return (memoryBank++);
|
|
}
|
|
|
|
// Return string showing memory bank name.
|
|
//
|
|
const char *sharpmz_get_memory_bank_string(short memoryBank)
|
|
{
|
|
return(SHARPMZ_MEMORY_BANK[ memoryBank ]);
|
|
}
|
|
|
|
// Return string showing memory bank dump file name.
|
|
//
|
|
const char *sharpmz_get_memory_bank_file(short memoryBank)
|
|
{
|
|
return(SHARPMZ_MEMORY_BANK_FILE[ memoryBank ]);
|
|
}
|
|
|
|
// Return display type status bits. Bit 0, 1, 2 of system_reg.
|
|
//
|
|
int sharpmz_get_display_type(void)
|
|
{
|
|
return (config.system_reg[REGISTER_DISPLAY] & 0x00000007 );
|
|
}
|
|
|
|
// Return string showing Display Type.
|
|
//
|
|
const char *sharpmz_get_display_type_string(void)
|
|
{
|
|
short displayType = (config.system_reg[REGISTER_DISPLAY]) & 0x00000007;
|
|
|
|
return(SHARPMZ_DISPLAY_TYPE[ displayType ]);
|
|
}
|
|
|
|
// Set display type status bits to given value.
|
|
//
|
|
void sharpmz_set_display_type(short displayType, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(displayType > 3) displayType = 0;
|
|
//if(displayType == 1) displayType = 3; // Skip unassigned hardware.
|
|
//if(displayType == 2) displayType = 3;
|
|
|
|
config.system_reg[REGISTER_DISPLAY] &= ~(0x07);
|
|
config.system_reg[REGISTER_DISPLAY] |= (displayType & 0x07);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DISPLAY, config.system_reg[REGISTER_DISPLAY]);
|
|
}
|
|
|
|
// Return aspect ratio status bits. Bit 1 of systemctrl, 0 = Off, 1 = On
|
|
//
|
|
int sharpmz_get_aspect_ratio(void)
|
|
{
|
|
return ((config.system_ctrl & 0x00000002) != 0);
|
|
}
|
|
|
|
// Return string showing Aspect Ratio.
|
|
//
|
|
const char *sharpmz_get_aspect_ratio_string(void)
|
|
{
|
|
short aspectRatio = (config.system_ctrl & 0x00000002);
|
|
|
|
return(SHARPMZ_ASPECT_RATIO[ aspectRatio ]);
|
|
}
|
|
|
|
// Set aspect ratio status bit to given value.
|
|
//
|
|
void sharpmz_set_aspect_ratio(short on, short setStatus)
|
|
{
|
|
config.system_ctrl &= ~(1 << 1);
|
|
config.system_ctrl |= (on == 1 ? 1 << 1 : 0);
|
|
|
|
if(setStatus)
|
|
user_io_8bit_set_status(config.system_ctrl, (1 << 1));
|
|
}
|
|
|
|
// Return Scan doubler fx status bits. Bits 2,3,4 of systemctrl.
|
|
//
|
|
int sharpmz_get_scandoubler_fx(void)
|
|
{
|
|
return ((config.system_ctrl >> 2) & 0x00000007 );
|
|
}
|
|
|
|
// Return string showing Scandoubler Fx mode.
|
|
//
|
|
const char *sharpmz_get_scandoubler_fx_string(void)
|
|
{
|
|
short scandoublerFx = ((config.system_ctrl >> 2) & 0x00000007 );
|
|
|
|
return(SHARPMZ_SCANDOUBLER_FX[ scandoublerFx ]);
|
|
}
|
|
|
|
// Set scan doubler status bits to given value.
|
|
//
|
|
void sharpmz_set_scandoubler_fx(short doubler, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(doubler > 4) doubler = 0;
|
|
|
|
config.system_ctrl &= ~(0x07 << 2);
|
|
config.system_ctrl |= (doubler & 0x07) << 2;
|
|
|
|
if(setStatus)
|
|
user_io_8bit_set_status(config.system_ctrl, (0x07 << 2));
|
|
}
|
|
|
|
// Return VRAM wait state mode status bit. Bit 6 of system_reg, 0 = Off, 1 = On
|
|
//
|
|
int sharpmz_get_vram_wait_mode(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DISPLAY] >> 6) & 0x00000001 );
|
|
}
|
|
|
|
// Return string showing VRAM wait state mode.
|
|
//
|
|
const char *sharpmz_get_vram_wait_mode_string(void)
|
|
{
|
|
short vramWaitMode = ((config.system_reg[REGISTER_DISPLAY] >> 6) & 0x00000001 );
|
|
|
|
return(SHARPMZ_VRAMWAIT_MODE[ vramWaitMode ]);
|
|
}
|
|
|
|
// Set VRAM wait state mode status bit to given value.
|
|
//
|
|
void sharpmz_set_vram_wait_mode(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DISPLAY] &= ~(1 << 6);
|
|
config.system_reg[REGISTER_DISPLAY] |= (on == 1 ? 1 << 6 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DISPLAY, config.system_reg[REGISTER_DISPLAY]);
|
|
}
|
|
|
|
// Return VRAM Output Disable bit. Bit 4 of system_reg, 0 = Output Enabled, 1 = Output Disabled
|
|
//
|
|
int sharpmz_get_vram_disable_mode(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DISPLAY] >> 4) & 0x00000001 );
|
|
}
|
|
|
|
// Return string showing VRAM Output Disable mode.
|
|
//
|
|
const char *sharpmz_get_vram_disable_mode_string(void)
|
|
{
|
|
short vramDisableMode = ((config.system_reg[REGISTER_DISPLAY] >> 4) & 0x00000001 );
|
|
|
|
return(SHARPMZ_VRAMDISABLE_MODE[ vramDisableMode ]);
|
|
}
|
|
|
|
// Set VRAM Output Disable mode bit to given value.
|
|
//
|
|
void sharpmz_set_vram_disable_mode(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DISPLAY] &= ~(1 << 4);
|
|
config.system_reg[REGISTER_DISPLAY] |= (on == 1 ? 1 << 4 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DISPLAY, config.system_reg[REGISTER_DISPLAY]);
|
|
}
|
|
|
|
// Return GRAM Output Disable bit. Bit 5 of system_reg, 0 = Output Enabled, 1 = Output Disabled
|
|
//
|
|
int sharpmz_get_gram_disable_mode(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DISPLAY] >> 5) & 0x00000001 );
|
|
}
|
|
|
|
// Return string showing GRAM Output Disable mode.
|
|
//
|
|
const char *sharpmz_get_gram_disable_mode_string(void)
|
|
{
|
|
short gramDisableMode = ((config.system_reg[REGISTER_DISPLAY] >> 5) & 0x00000001 );
|
|
|
|
return(SHARPMZ_GRAMDISABLE_MODE[ gramDisableMode ]);
|
|
}
|
|
|
|
// Set GRAM Output Disable mode bit to given value.
|
|
//
|
|
void sharpmz_set_gram_disable_mode(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DISPLAY] &= ~(1 << 5);
|
|
config.system_reg[REGISTER_DISPLAY] |= (on == 1 ? 1 << 5 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DISPLAY, config.system_reg[REGISTER_DISPLAY]);
|
|
}
|
|
|
|
// Return PCG mode status bit. Bit 7 of system_reg, 0 = Off, 1 = On
|
|
//
|
|
int sharpmz_get_pcg_mode(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DISPLAY] >> 7) & 0x00000001 );
|
|
}
|
|
|
|
// Return string showing PCG mode.
|
|
//
|
|
const char *sharpmz_get_pcg_mode_string(void)
|
|
{
|
|
short pcgMode = ((config.system_reg[REGISTER_DISPLAY] >> 7) & 0x00000001 );
|
|
|
|
return(SHARPMZ_PCG_MODE[ pcgMode ]);
|
|
}
|
|
|
|
// Set PCG mode status bit to given value.
|
|
//
|
|
void sharpmz_set_pcg_mode(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DISPLAY] &= ~(1 << 7);
|
|
config.system_reg[REGISTER_DISPLAY] |= (on == 1 ? 1 << 7 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DISPLAY, config.system_reg[REGISTER_DISPLAY]);
|
|
}
|
|
|
|
// Return machine model status bits. Bits 0,1,2 of system_reg.
|
|
//
|
|
int sharpmz_get_machine_model(void)
|
|
{
|
|
return (config.system_reg[REGISTER_MODEL] & 0x07);
|
|
}
|
|
|
|
// Return string showing Machine model.
|
|
//
|
|
const char *sharpmz_get_machine_model_string(short machineModel )
|
|
{
|
|
return(SHARPMZ_MACHINE_MODEL[ machineModel & 0x07 ]);
|
|
}
|
|
|
|
// Return string showing Machine model.
|
|
//
|
|
const char *sharpmz_get_machine_model_string(void)
|
|
{
|
|
short machineModel = (config.system_reg[REGISTER_MODEL]) & 0x07;
|
|
|
|
return(SHARPMZ_MACHINE_MODEL[ machineModel ]);
|
|
}
|
|
|
|
// Method to return the next machine model index in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_machine_model(void)
|
|
{
|
|
static short machineModel = (config.system_reg[REGISTER_MODEL]) & 0x07;
|
|
|
|
// Certain models not yet active.
|
|
if(machineModel == MZ800_IDX || machineModel == MZ80B_IDX || machineModel == MZ2000_IDX) machineModel = MZ80K_IDX;
|
|
return (machineModel++);
|
|
}
|
|
|
|
// Set machine model status bits to given value.
|
|
//
|
|
void sharpmz_set_machine_model(short machineModel, short setStatus)
|
|
{
|
|
// Sanity.
|
|
//
|
|
machineModel &= 0x07;
|
|
|
|
// When setting the model, default other settings to sensible values.
|
|
//
|
|
switch(machineModel)
|
|
{
|
|
// These machines currently underdevelopment, so fall through to MZ80K
|
|
case MZ800_IDX: // MZ800
|
|
case MZ80B_IDX: // MZ80B
|
|
case MZ2000_IDX: // MZ2000
|
|
machineModel = 0;
|
|
|
|
case MZ80K_IDX: // MZ80K
|
|
case MZ80C_IDX: // MZ80C
|
|
case MZ1200_IDX: // MZ1200
|
|
case MZ80A_IDX: // MZ80A
|
|
//sharpmz_set_fasttape(0x00, 1); // No.
|
|
sharpmz_set_display_type(0x00, 0); // Normal display
|
|
//sharpmz_set_pcg_mode(0x00, 1); // ROM
|
|
//sharpmz_set_scandoubler_fx(0x00, 1);// None.
|
|
sharpmz_set_cpu_speed(0x00, 1); // 2MHz MZ80C, 3.5MHz MZ700
|
|
break;
|
|
|
|
case MZ700_IDX: // MZ700
|
|
//sharpmz_set_fasttape(0x00, 1); // No.
|
|
sharpmz_set_display_type(0x02, 0); // Colour display
|
|
//sharpmz_set_pcg_mode(0x00, 1); // ROM sharpmz_set_scandoubler_fx(0x00, 0);// None.
|
|
//sharpmz_set_scandoubler_fx(0x00, 1);// None.
|
|
sharpmz_set_cpu_speed(0x00, 0); // 2MHz MZ80C, 3.5MHz MZ700
|
|
break;
|
|
}
|
|
|
|
// Set the machine model.
|
|
config.system_reg[REGISTER_MODEL] &= ~(0x07);
|
|
config.system_reg[REGISTER_MODEL] |= (machineModel);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_MODEL, config.system_reg[REGISTER_MODEL]);
|
|
}
|
|
|
|
// Return string showing CPU speed for display.
|
|
//
|
|
const char *sharpmz_get_cpu_speed_string(void)
|
|
{
|
|
short cpuSet = (config.system_reg[REGISTER_CPU]) & 0x00000007;
|
|
|
|
return(SHARPMZ_CPU_SPEED[ (sharpmz_get_machine_group() * 8) + cpuSet ]);
|
|
}
|
|
|
|
// Return cpu speed status bits. Bits 0, 1 of system_reg.
|
|
//
|
|
int sharpmz_get_cpu_speed(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_CPU]) & 0x00000007);
|
|
}
|
|
|
|
// Set cpu speed status bits to given value.
|
|
//
|
|
void sharpmz_set_cpu_speed(short cpuSpeed, short setStatus)
|
|
{
|
|
short machineGroup = sharpmz_get_machine_group();
|
|
|
|
// Clear current setting.
|
|
config.system_reg[REGISTER_CPU] &= ~(0x07);
|
|
|
|
if((machineGroup == 0 && cpuSpeed > 5) || (machineGroup == 1 && cpuSpeed > 5) || (machineGroup == 2 && cpuSpeed > 4)) cpuSpeed = 0;
|
|
config.system_reg[REGISTER_CPU] |= (cpuSpeed & 0x07);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_CPU, config.system_reg[REGISTER_CPU]);
|
|
}
|
|
|
|
// Return audio source status bit. Bit 0 of system_reg, 0 = sound, 1 = tape
|
|
//
|
|
int sharpmz_get_audio_source(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_AUDIO]) & 0x00000001);
|
|
}
|
|
|
|
// Return string showing Audio source.
|
|
//
|
|
const char *sharpmz_get_audio_source_string(void)
|
|
{
|
|
short audioSource = ((config.system_reg[REGISTER_AUDIO]) & 0x00000001);
|
|
|
|
return(SHARPMZ_AUDIO_SOURCE[ audioSource ]);
|
|
}
|
|
|
|
// Set audio source status bit to given value.
|
|
//
|
|
void sharpmz_set_audio_source(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_AUDIO] &= ~(1);
|
|
config.system_reg[REGISTER_AUDIO] |= (on == 1 ? 1 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_AUDIO, config.system_reg[REGISTER_AUDIO]);
|
|
}
|
|
|
|
// Return audio volume setting. The value is inverse, ie. it is an attenuation, 15 is highest, 0 is off.
|
|
//
|
|
int sharpmz_get_audio_volume(void)
|
|
{
|
|
return ((config.volume) & 0x0f);
|
|
}
|
|
|
|
// Return string showing Audio volume setting - this is inversed.
|
|
//
|
|
const char *sharpmz_get_audio_volume_string(void)
|
|
{
|
|
return(SHARPMZ_AUDIO_VOLUME[ config.volume & 0x0f ]);
|
|
}
|
|
|
|
// Set audio volume level. 15 = high attenuation, 0 = no attenuation.
|
|
//
|
|
void sharpmz_set_audio_volume(short volume, short setStatus)
|
|
{
|
|
config.volume &= 0x10;
|
|
config.volume |= volume & 0x0f;
|
|
|
|
if(setStatus)
|
|
spi_uio_cmd8(UIO_AUDVOL, config.volume);
|
|
}
|
|
|
|
// Return audio mute setting.
|
|
//
|
|
int sharpmz_get_audio_mute(void)
|
|
{
|
|
return ((config.volume & 0x10) >> 4);
|
|
}
|
|
|
|
// Return string showing Audio mute setting.
|
|
//
|
|
const char *sharpmz_get_audio_mute_string(void)
|
|
{
|
|
return(SHARPMZ_AUDIO_MUTE[ (config.volume & 0x10) >> 4 ]);
|
|
}
|
|
|
|
// Set audio mute level.
|
|
//
|
|
void sharpmz_set_audio_mute(short mute, short setStatus)
|
|
{
|
|
config.volume &= 0x0f;
|
|
config.volume |= mute << 4;
|
|
|
|
if(setStatus)
|
|
spi_uio_cmd8(UIO_AUDVOL, config.volume);
|
|
}
|
|
|
|
// Return debug enable status bit. Bit 7 of system_reg, 0 = Off, 1 = On
|
|
//
|
|
int sharpmz_get_debug_enable(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DEBUG] >> 7) & 0x00000001);
|
|
}
|
|
|
|
// Return string showing Debug Enable mode.
|
|
//
|
|
const char *sharpmz_get_debug_enable_string(void)
|
|
{
|
|
short debugEnable = ((config.system_reg[REGISTER_DEBUG] >> 7) & 0x00000001);
|
|
|
|
return(SHARPMZ_DEBUG_ENABLE[ debugEnable ]);
|
|
}
|
|
|
|
// Set debug enable status bit to given value.
|
|
//
|
|
void sharpmz_set_debug_enable(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DEBUG] &= ~(1 << 7);
|
|
config.system_reg[REGISTER_DEBUG] |= (on == 1 ? 1 << 7 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG, config.system_reg[REGISTER_DEBUG]);
|
|
}
|
|
|
|
// Return debug leds status bit. Bit 6 of system_reg, 0 = Off, 1 = On
|
|
//
|
|
int sharpmz_get_debug_leds(void)
|
|
{
|
|
return ((config.system_reg[REGISTER_DEBUG] >> 6) & 0x00000001);
|
|
}
|
|
|
|
// Return string showing Debug Leds.
|
|
//
|
|
const char *sharpmz_get_debug_leds_string(void)
|
|
{
|
|
short debugLeds = ((config.system_reg[REGISTER_DEBUG] >> 6) & 0x00000001);
|
|
|
|
return(SHARPMZ_DEBUG_LEDS[ debugLeds ]);
|
|
}
|
|
|
|
// Set debug leds status bit to given value.
|
|
//
|
|
void sharpmz_set_debug_leds(short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_DEBUG] &= ~(1 << 6);
|
|
config.system_reg[REGISTER_DEBUG] |= (on == 1 ? 1 << 6 : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG, config.system_reg[REGISTER_DEBUG]);
|
|
}
|
|
|
|
// Method to return the next debug bank index in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_debug_leds_bank(void)
|
|
{
|
|
static short debugLedsBank = (config.system_reg[REGISTER_DEBUG] & 0x00000007);
|
|
|
|
// Certain models not yet active.
|
|
if(strcmp(SHARPMZ_DEBUG_LEDS_BANK[ debugLedsBank ], "") == 0) debugLedsBank = 0;
|
|
|
|
return (debugLedsBank++);
|
|
}
|
|
|
|
// Return string showing debug led bank.
|
|
//
|
|
const char *sharpmz_get_debug_leds_bank_string(void)
|
|
{
|
|
short debugLedsBank = (config.system_reg[REGISTER_DEBUG] & 0x00000007);
|
|
|
|
return(SHARPMZ_DEBUG_LEDS_BANK[ debugLedsBank ]);
|
|
}
|
|
|
|
// Set debug LEDS bank index.
|
|
//
|
|
void sharpmz_set_debug_leds_bank(short debugLedsBank, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(debugLedsBank > 7) debugLedsBank = 0;
|
|
|
|
config.system_reg[REGISTER_DEBUG] &= ~(0x07);
|
|
config.system_reg[REGISTER_DEBUG] |= (debugLedsBank & 0x07);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG, config.system_reg[REGISTER_DEBUG]);
|
|
}
|
|
|
|
// Method to return the next debug sub-bank index in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_debug_leds_subbank(unsigned char reset)
|
|
{
|
|
static short debugLedsSubBank = ((config.system_reg[REGISTER_DEBUG] >> 3) & 0x00000007);
|
|
short debugLedsBank = (config.system_reg[REGISTER_DEBUG] & 0x00000007);
|
|
|
|
// Limit choice according to number of subbanks and subbanks setup.
|
|
if(reset || debugLedsSubBank > 7) debugLedsSubBank = 0;
|
|
if(strcmp(SHARPMZ_DEBUG_LEDS_SUBBANK[ (debugLedsBank * 8) + debugLedsSubBank ], "") == 0) debugLedsSubBank = 0;
|
|
return (debugLedsSubBank++);
|
|
}
|
|
|
|
// Return string showing debug led sub-bank.
|
|
//
|
|
const char *sharpmz_get_debug_leds_subbank_string(void)
|
|
{
|
|
short debugLedsBank = (config.system_reg[REGISTER_DEBUG] & 0x00000007);
|
|
short debugLedsSubBank = ((config.system_reg[REGISTER_DEBUG] >> 3) & 0x00000007);
|
|
|
|
return(SHARPMZ_DEBUG_LEDS_SUBBANK[ (debugLedsBank * 8) + debugLedsSubBank ]);
|
|
}
|
|
|
|
// Set debug LEDS sub-bank index.
|
|
//
|
|
void sharpmz_set_debug_leds_subbank(short debugLedsSubBank, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(debugLedsSubBank > 7) debugLedsSubBank = 0;
|
|
|
|
config.system_reg[REGISTER_DEBUG] &= ~(0x07 << 3);
|
|
config.system_reg[REGISTER_DEBUG] |= ((debugLedsSubBank & 0x07) << 3);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG, config.system_reg[REGISTER_DEBUG]);
|
|
}
|
|
|
|
// Method to return the next debug cpu frequency index in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_debug_cpufreq(void)
|
|
{
|
|
static short debugCPUFrequency = ((config.system_reg[REGISTER_DEBUG2] >> 4) & 0x0000000f);
|
|
|
|
// Sanity check.
|
|
if(debugCPUFrequency > 15) debugCPUFrequency = 0;
|
|
|
|
return (debugCPUFrequency++);
|
|
}
|
|
|
|
// Return string showing debug cpu frequency.
|
|
//
|
|
const char *sharpmz_get_debug_cpufreq_string(void)
|
|
{
|
|
short debugCPUFrequency = ((config.system_reg[REGISTER_DEBUG2] >> 4) & 0x0000000f);
|
|
|
|
return(SHARPMZ_DEBUG_CPUFREQ[ debugCPUFrequency ]);
|
|
}
|
|
|
|
// Set debug cpu frequency index.
|
|
//
|
|
void sharpmz_set_debug_cpufreq(short debugCPUFrequency, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(debugCPUFrequency > 15) debugCPUFrequency = 0;
|
|
|
|
config.system_reg[REGISTER_DEBUG2] &= ~(0x0f << 4);
|
|
config.system_reg[REGISTER_DEBUG2] |= ((debugCPUFrequency & 0x0f) << 4);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG2, config.system_reg[REGISTER_DEBUG2]);
|
|
}
|
|
|
|
// Method to return the next debug sample frequency index in a loop sequence.
|
|
//
|
|
short sharpmz_get_next_debug_leds_smpfreq(void)
|
|
{
|
|
static short debugLedsSampleFrequency = (config.system_reg[REGISTER_DEBUG2] & 0x0000000f);
|
|
|
|
// Sanity check.
|
|
if(debugLedsSampleFrequency > 15) debugLedsSampleFrequency = 0;
|
|
|
|
return (debugLedsSampleFrequency++);
|
|
}
|
|
|
|
// Return string showing debug led sample frequency.
|
|
//
|
|
const char *sharpmz_get_debug_leds_smpfreq_string(void)
|
|
{
|
|
short debugLedsSampleFrequency = (config.system_reg[REGISTER_DEBUG2] & 0x0000000f);
|
|
|
|
return(SHARPMZ_DEBUG_LEDS_SMPFREQ[ debugLedsSampleFrequency ]);
|
|
}
|
|
|
|
// Set debug LEDS sample frequency index.
|
|
//
|
|
void sharpmz_set_debug_leds_smpfreq(short debugLedsSampleFrequency, short setStatus)
|
|
{
|
|
// Sanity check.
|
|
if(debugLedsSampleFrequency > 15) debugLedsSampleFrequency = 0;
|
|
|
|
config.system_reg[REGISTER_DEBUG2] &= ~(0x0f);
|
|
config.system_reg[REGISTER_DEBUG2] |= (debugLedsSampleFrequency & 0x0f);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_DEBUG2, config.system_reg[REGISTER_DEBUG2]);
|
|
}
|
|
|
|
// Return string showing auto save enabled mode.
|
|
//
|
|
const char *sharpmz_get_auto_save_enabled_string(void)
|
|
{
|
|
return(SHARPMZ_AUTO_SAVE_ENABLED[ config.autoSave ]);
|
|
}
|
|
|
|
// Method to return the enabled state of auto save.
|
|
//
|
|
unsigned char sharpmz_get_auto_save_enabled(void)
|
|
{
|
|
return(config.autoSave);
|
|
}
|
|
|
|
// Method to set the auto save flag to determine if automatic saving of incoming tape data is enabled.
|
|
//
|
|
void sharpmz_set_auto_save_enabled(unsigned char on)
|
|
{
|
|
config.autoSave = on;
|
|
}
|
|
|
|
// Method to return the enabled state of a user rom for given machine.
|
|
//
|
|
short sharpmz_get_user_rom_enabled(short machineModel)
|
|
{
|
|
return ((config.system_reg[REGISTER_USERROM] >> machineModel) & 0x00000001);
|
|
}
|
|
|
|
// Return string showing user rom enabled status.
|
|
//
|
|
const char *sharpmz_get_user_rom_enabled_string(short machineModel)
|
|
{
|
|
short userRomEnabled = ((config.system_reg[REGISTER_USERROM] >> machineModel) & 0x00000001);
|
|
|
|
return(SHARPMZ_USERROM_ENABLED[ userRomEnabled ]);
|
|
}
|
|
|
|
// Method to set the enabled state of a user rom for a given machine.
|
|
//
|
|
void sharpmz_set_user_rom_enabled(short machineModel, short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_USERROM] &= ~(1 << machineModel);
|
|
config.system_reg[REGISTER_USERROM] |= (on == 1 ? 1 << machineModel : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_USERROM, config.system_reg[REGISTER_USERROM]);
|
|
}
|
|
|
|
// Method to return the enabled state of a fdc rom for given machine.
|
|
//
|
|
short sharpmz_get_fdc_rom_enabled(short machineModel)
|
|
{
|
|
return ((config.system_reg[REGISTER_FDCROM] >> machineModel) & 0x00000001);
|
|
}
|
|
|
|
// Return string showing fdc rom enabled status.
|
|
//
|
|
const char *sharpmz_get_fdc_rom_enabled_string(short machineModel)
|
|
{
|
|
short fdcRomEnabled = ((config.system_reg[REGISTER_FDCROM] >> machineModel) & 0x00000001);
|
|
|
|
return(SHARPMZ_FDCROM_ENABLED[ fdcRomEnabled ]);
|
|
}
|
|
|
|
// Method to set the enabled state of a fdc rom for a given machine.
|
|
//
|
|
void sharpmz_set_fdc_rom_enabled(short machineModel, short on, short setStatus)
|
|
{
|
|
config.system_reg[REGISTER_FDCROM] &= ~(1 << machineModel);
|
|
config.system_reg[REGISTER_FDCROM] |= (on == 1 ? 1 << machineModel : 0);
|
|
|
|
if(setStatus)
|
|
sharpmz_set_config_register(REGISTER_FDCROM, config.system_reg[REGISTER_FDCROM]);
|
|
}
|
|
|
|
// Method to return the enabled state of a rom for loading.
|
|
//
|
|
short sharpmz_get_custom_rom_enabled(short machineModel, short romType)
|
|
{
|
|
short romEnabled = 0;
|
|
|
|
machineModel &= 0x07;
|
|
romType &= 0x07;
|
|
switch(romType)
|
|
{
|
|
case MROM_IDX:
|
|
romEnabled = config.romMonitor[machineModel][MONITOR].romEnabled;
|
|
break;
|
|
|
|
case MROM_80C_IDX:
|
|
romEnabled = config.romMonitor[machineModel][MONITOR_80C].romEnabled;
|
|
break;
|
|
|
|
case CGROM_IDX:
|
|
romEnabled = config.romCG[machineModel].romEnabled;
|
|
break;
|
|
|
|
case KEYMAP_IDX:
|
|
romEnabled = config.romKeyMap[machineModel].romEnabled;
|
|
break;
|
|
|
|
case USERROM_IDX:
|
|
romEnabled = config.romUser[machineModel].romEnabled;
|
|
break;
|
|
|
|
case FDCROM_IDX:
|
|
romEnabled = config.romFDC[machineModel].romEnabled;
|
|
break;
|
|
|
|
default:
|
|
sharpmz_debugf("Unknown get enabled romType: %d\n", romType);
|
|
break;
|
|
}
|
|
return(romEnabled);
|
|
}
|
|
|
|
// Return string showing rom enabled mode.
|
|
//
|
|
const char *sharpmz_get_custom_rom_enabled_string(short romEnabled)
|
|
{
|
|
return(SHARPMZ_ROM_ENABLED[ romEnabled ]);
|
|
}
|
|
|
|
// Method to set the enabled state of a rom for loading.
|
|
//
|
|
void sharpmz_set_custom_rom_enabled(short machineModel, short romType, short on)
|
|
{
|
|
machineModel &= 0x07;
|
|
romType &= 0x07;
|
|
switch(romType)
|
|
{
|
|
case MROM_IDX:
|
|
config.romMonitor[machineModel][MONITOR].romEnabled = (on == 1);
|
|
break;
|
|
|
|
case MROM_80C_IDX:
|
|
config.romMonitor[machineModel][MONITOR_80C].romEnabled = (on == 1);
|
|
break;
|
|
|
|
case CGROM_IDX:
|
|
config.romCG[machineModel].romEnabled = (on == 1);
|
|
break;
|
|
|
|
case KEYMAP_IDX:
|
|
config.romKeyMap[machineModel].romEnabled = (on == 1);
|
|
break;
|
|
|
|
case USERROM_IDX:
|
|
config.romUser[machineModel].romEnabled = (on == 1);
|
|
break;
|
|
|
|
case FDCROM_IDX:
|
|
config.romFDC[machineModel].romEnabled = (on == 1);
|
|
break;
|
|
|
|
default:
|
|
sharpmz_debugf("Unknown set enabled romType: %d\n", romType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Method to return the filename of a rom.
|
|
//
|
|
char *sharpmz_get_rom_file(short machineModel, short romType)
|
|
{
|
|
machineModel &= 0x07;
|
|
romType &= 0x07;
|
|
switch(romType)
|
|
{
|
|
case MROM_IDX:
|
|
return(config.romMonitor[machineModel][MONITOR].romFileName);
|
|
|
|
case MROM_80C_IDX:
|
|
return(config.romMonitor[machineModel][MONITOR_80C].romFileName);
|
|
|
|
case CGROM_IDX:
|
|
return(config.romCG[machineModel].romFileName);
|
|
|
|
case KEYMAP_IDX:
|
|
return(config.romKeyMap[machineModel].romFileName);
|
|
|
|
case USERROM_IDX:
|
|
return(config.romUser[machineModel].romFileName);
|
|
|
|
case FDCROM_IDX:
|
|
return(config.romFDC[machineModel].romFileName);
|
|
|
|
default:
|
|
sharpmz_debugf("Unknown get filename romType: %d\n", romType);
|
|
break;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
// Method to set the filename of a rom.
|
|
//
|
|
void sharpmz_set_rom_file(short machineModel, short romType, char *filename)
|
|
{
|
|
machineModel &= 0x07;
|
|
romType &= 0x03;
|
|
switch(romType)
|
|
{
|
|
case MROM_IDX:
|
|
strcpy(config.romMonitor[machineModel][MONITOR].romFileName, filename);
|
|
sharpmz_debugf("Copy MROM:%s, %s\n", filename,config.romMonitor[machineModel][MONITOR].romFileName );
|
|
break;
|
|
|
|
case MROM_80C_IDX:
|
|
strcpy(config.romMonitor[machineModel][MONITOR_80C].romFileName, filename);
|
|
sharpmz_debugf("Copy MROM (80x25):%s, %s\n", filename,config.romMonitor[machineModel][MONITOR_80C].romFileName );
|
|
break;
|
|
|
|
case CGROM_IDX:
|
|
strcpy(config.romCG[machineModel].romFileName, filename);
|
|
sharpmz_debugf("Copy CGROM:%s, %s\n", filename,config.romCG[machineModel].romFileName );
|
|
break;
|
|
|
|
case KEYMAP_IDX:
|
|
strcpy(config.romKeyMap[machineModel].romFileName, filename);
|
|
sharpmz_debugf("Copy KEYROM:%s, %s\n", filename,config.romKeyMap[machineModel].romFileName );
|
|
break;
|
|
|
|
case USERROM_IDX:
|
|
strcpy(config.romUser[machineModel].romFileName, filename);
|
|
sharpmz_debugf("Copy USERROM:%s, %s\n", filename,config.romUser[machineModel].romFileName );
|
|
break;
|
|
|
|
case FDCROM_IDX:
|
|
strcpy(config.romFDC[machineModel].romFileName, filename);
|
|
sharpmz_debugf("Copy FDCROM:%s, %s\n", filename,config.romFDC[machineModel].romFileName );
|
|
break;
|
|
|
|
default:
|
|
sharpmz_debugf("Unknown set filename romType: %d, filename:%s\n", romType, filename);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Return string showing last Tape type read.
|
|
//
|
|
const char *sharpmz_get_tape_type_string(void)
|
|
{
|
|
return(SHARPMZ_TAPE_TYPE[ tapeHeader.dataType ]);
|
|
}
|
|
|
|
// Method to get the header of the last tape loaded.
|
|
//
|
|
sharpmz_tape_header_t *sharpmz_get_tape_header(void)
|
|
{
|
|
return(&tapeHeader);
|
|
}
|
|
|
|
// Local version of File Read so that we can read exact number of bytes required
|
|
// and return parameter specifies number of bytes actually read.
|
|
//
|
|
int sharpmz_file_read(fileTYPE *file, void *pBuffer, int nSize)
|
|
{
|
|
if (!FileSeek(file, file->offset, SEEK_SET))
|
|
{
|
|
sharpmz_debugf("file_read error(seek).\n");
|
|
return 0;
|
|
}
|
|
|
|
int ret = FileReadAdv(file, pBuffer, nSize);
|
|
if (ret < 0)
|
|
{
|
|
sharpmz_debugf("file_read error(%d).\n", ret);
|
|
return 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Method to program a config register in the emulator.
|
|
//
|
|
void sharpmz_set_config_register(short addr, unsigned char value)
|
|
{
|
|
EnableFpga();
|
|
spi8(SHARPMZ_CONFIG_TX);
|
|
spi8(addr); // Address of register to change.
|
|
spi8(value); // Value to set in the register.
|
|
sharpmz_debugf("Register Set(%02x) -> %02x\n", addr, value);
|
|
DisableFpga();
|
|
|
|
for(int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_debugf("%02x => %02x, ", i, sharpmz_read_config_register(i));
|
|
}
|
|
sharpmz_debugf("\n");
|
|
//sharpmz_read_config_register(addr);
|
|
}
|
|
|
|
// Method to read a config register in the emulator.
|
|
//
|
|
unsigned char sharpmz_read_config_register(short addr)
|
|
{
|
|
unsigned char value;
|
|
|
|
EnableFpga();
|
|
spi8(SHARPMZ_CONFIG_RX);
|
|
spi8(addr); // Address of register to change.
|
|
spi8(0x00);
|
|
value = spi_b(0x00); // Padding to give a cycle to allow data to be read.
|
|
//sharpmz_debugf("Register Read(%02x)=%02x\n", addr, value);
|
|
DisableFpga();
|
|
|
|
// Return the value stored in the config register.
|
|
return(value);
|
|
}
|
|
|
|
// Method to send a file to the emulator.
|
|
//
|
|
void sharpmz_send_file(romData_t &image, char *dirPrefix)
|
|
{
|
|
char sendFile[1024];
|
|
unsigned int actualReadSize;
|
|
unsigned long time = GetTimer(0);
|
|
unsigned short i;
|
|
fileTYPE file = {};
|
|
|
|
// If a prefix is given (ie. core directory), prepend it before use.
|
|
//
|
|
if(dirPrefix)
|
|
{
|
|
strcpy(sendFile, dirPrefix);
|
|
strcat(sendFile, "/");
|
|
strcat(sendFile, image.romFileName);
|
|
} else
|
|
{
|
|
strcpy(sendFile, SHARPMZ_CORE_NAME);
|
|
strcat(sendFile, "/");
|
|
strcat(sendFile, image.romFileName);
|
|
}
|
|
|
|
sharpmz_debugf("Sending file:%s", sendFile);
|
|
|
|
// Try and open the given file, exit on failure.
|
|
if (!FileOpen(&file, sendFile)) return;
|
|
|
|
// Prepare transmission of new file.
|
|
EnableFpga();
|
|
spi8(SHARPMZ_FILE_ADDR_TX);
|
|
spi8(0x00);
|
|
spi8(image.loadAddr >> 16); // Indicate we are uploading rom images into the correct ROM section of the memory.
|
|
spi8((image.loadAddr >> 8) & 0xff); // MSB of the rom image.
|
|
spi8(image.loadAddr&0xff); // LSB of the rom image.
|
|
sharpmz_debugf("Load Address:%04x, %04x, %04x\n", image.loadAddr, image.loadAddr >> 8, image.loadSize);
|
|
|
|
// Limit size to that governed in the config. If the rom is larger than the defined size, waste additional data,
|
|
// if less then finish early. Prevents large images from corrupting other machine roms.
|
|
//
|
|
sharpmz_debugf("[");
|
|
for (i = 0; i < image.loadSize; i += actualReadSize)
|
|
{
|
|
if (!(i & 127)) { sharpmz_debugf("*"); }
|
|
|
|
// Work out size of data block to read.
|
|
int readSize = (image.loadSize - i >= 512 ? 512 : image.loadSize - i);
|
|
|
|
// Perform the read.
|
|
DISKLED_ON;
|
|
actualReadSize = sharpmz_file_read(&file, sector_buffer, readSize);
|
|
DISKLED_OFF;
|
|
|
|
// If we encountered an error, then bad file or eof, so exit.
|
|
//
|
|
if(actualReadSize != 0)
|
|
{
|
|
spi_write(sector_buffer, actualReadSize, 0);
|
|
|
|
} else
|
|
{
|
|
// End of file, short file, so just move onto end.
|
|
actualReadSize = image.loadSize -i;
|
|
}
|
|
}
|
|
DisableFpga();
|
|
sharpmz_debugf("]\n");
|
|
|
|
// Tidy up.
|
|
FileClose(&file);
|
|
|
|
// For debug, display time it took to upload.
|
|
time = GetTimer(0) - time;
|
|
sharpmz_debugf("Uploaded in %lu ms", time >> 20);
|
|
|
|
// signal end of transmission
|
|
EnableFpga();
|
|
spi8(SHARPMZ_FILE_TX);
|
|
spi8(SHARPMZ_EOF);
|
|
DisableFpga();
|
|
}
|
|
|
|
// Method to read the emulator memory. Either a specific bank is given or all banks via the parameter bank.
|
|
//
|
|
short sharpmz_read_ram(const char *memDumpFile, short bank)
|
|
{
|
|
unsigned int actualWriteSize;
|
|
fileTYPE file = {};
|
|
|
|
// Open the memory image debug file for writing.
|
|
if (!sharpmz_file_write(&file, memDumpFile))
|
|
{
|
|
sharpmz_debugf("Failed to open ram dump file:%s\n", memDumpFile);
|
|
return(3);
|
|
}
|
|
|
|
// Depending on the bank, or all banks, loop until request is complete.
|
|
//
|
|
for(unsigned int mb=(bank == SHARPMZ_MEMBANK_ALL ? 0 : bank); mb <= (uint)(bank == SHARPMZ_MEMBANK_ALL ? SHARPMZ_MEMBANK_MAXBANKS-1 : bank); mb++)
|
|
{
|
|
// Skip bank 1, as SYSROM spans two physical banks 0 and 1.
|
|
if(mb == 1) mb = SHARPMZ_MEMBANK_SYSRAM;
|
|
|
|
EnableFpga(); // Setup the load address.
|
|
spi8(SHARPMZ_FILE_ADDR_RX);
|
|
spi8(0x00);
|
|
spi8(mb); // Memory bank to read.
|
|
spi8(0x00); // A15-A8
|
|
spi8(0x00); // A7-A0
|
|
//spi8(0x00); // Setup to read addr first byte.
|
|
|
|
// The bank size is stored in the config.
|
|
//
|
|
sharpmz_debugf("[");
|
|
for (unsigned long j = 0; j < MZBANKSIZE[mb] or actualWriteSize == 0; j += actualWriteSize)
|
|
{
|
|
if (!(j & 127)) { sharpmz_debugf("*"); }
|
|
|
|
spi_read(sector_buffer, 512, 0);
|
|
|
|
DISKLED_ON;
|
|
actualWriteSize=FileWriteAdv(&file, sector_buffer, 512);
|
|
DISKLED_OFF;
|
|
}
|
|
sharpmz_debugf("]\n");
|
|
|
|
// Indicate end of upload.
|
|
spi8(SHARPMZ_EOF);
|
|
DisableFpga();
|
|
}
|
|
|
|
// Close file to complete dump.
|
|
FileClose(&file);
|
|
|
|
// Success.
|
|
//
|
|
return(0);
|
|
}
|
|
|
|
// Method to read the header of a tape.
|
|
// Useful for decision making prior to load.
|
|
//
|
|
short sharpmz_read_tape_header(const char *tapeFile)
|
|
{
|
|
unsigned int actualReadSize;
|
|
|
|
//sharpmz_debugf("Sending tape file:%s to emulator ram", tapeFile);
|
|
|
|
// Handle for the MZF file to be processed.
|
|
//
|
|
fileTYPE file = {};
|
|
|
|
// Try and open the tape file, exit if it cannot be opened.
|
|
//
|
|
if (!FileOpen(&file, tapeFile)) return(1);
|
|
|
|
// Read in the tape header, this indicates crucial data such as data type, size, exec address, load address etc.
|
|
//
|
|
actualReadSize = sharpmz_file_read(&file, &tapeHeader, 128);
|
|
if(actualReadSize != 128)
|
|
{
|
|
sharpmz_debugf("Only read:%d bytes of header, aborting.\n", actualReadSize);
|
|
return(1);
|
|
}
|
|
|
|
// Some sanity checks.
|
|
//
|
|
if(tapeHeader.dataType == 0 || tapeHeader.dataType > 5) return(4);
|
|
|
|
// Success.
|
|
return(0);
|
|
}
|
|
|
|
// Method to load a tape (MZF) file directly into RAM.
|
|
// This involves reading the tape header, extracting the size and destination and loading
|
|
// the header and program into emulator ram.
|
|
//
|
|
short sharpmz_load_tape_to_ram(const char *tapeFile, unsigned char dstCMT)
|
|
{
|
|
unsigned int actualReadSize;
|
|
unsigned long time = GetTimer(0);
|
|
//char fileName[17];
|
|
|
|
//sharpmz_debugf("Sending tape file:%s to emulator ram", tapeFile);
|
|
|
|
// Handle for the MZF file to be processed.
|
|
//
|
|
fileTYPE file = {};
|
|
|
|
// Try and open the tape file, exit if it cannot be opened.
|
|
//
|
|
if (!FileOpen(&file, tapeFile)) return(1);
|
|
|
|
// Read in the tape header, this indicates crucial data such as data type, size, exec address, load address etc.
|
|
//
|
|
actualReadSize = sharpmz_file_read(&file, &tapeHeader, 128);
|
|
if(actualReadSize != 128)
|
|
{
|
|
sharpmz_debugf("Only read:%d bytes of header, aborting.\n", actualReadSize);
|
|
return(2);
|
|
}
|
|
|
|
// Some sanity checks.
|
|
//
|
|
if(tapeHeader.dataType == 0 || tapeHeader.dataType > 5) return(4);
|
|
/*
|
|
for(int i=0; i < 17; i++)
|
|
{
|
|
fileName[i] = tapeHeader.fileName[i] == 0x0d ? 0x00 : tapeHeader.fileName[i];
|
|
}
|
|
*/
|
|
|
|
// Debug output to indicate the file loaded and information about the tape image.
|
|
//
|
|
switch(tapeHeader.dataType)
|
|
{
|
|
case 0x01:
|
|
sharpmz_debugf("Binary File(Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s, StackLow=%04x, StackHigh=%04x)\n", tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName, MZ_TAPE_HEADER_STACK_ADDR & 0xff, (MZ_TAPE_HEADER_STACK_ADDR >> 8) & 0xff);
|
|
break;
|
|
|
|
case 0x02:
|
|
sharpmz_debugf("MZ-80 Basic Program(Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s)\n", tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName);
|
|
break;
|
|
|
|
case 0x03:
|
|
sharpmz_debugf("MZ-80 Data File(Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s)\n", tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName);
|
|
break;
|
|
|
|
case 0x04:
|
|
sharpmz_debugf("MZ-700 Data File(Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s)\n", tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName);
|
|
break;
|
|
|
|
case 0x05:
|
|
sharpmz_debugf("MZ-700 Basic Program(Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s)\n", tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName);
|
|
break;
|
|
|
|
default:
|
|
sharpmz_debugf("Unknown tape type(Type=%02x, Load Addr=%04x, Size=%04x, Exec Addr=%04x, FileName=%s)\n", tapeHeader.dataType, tapeHeader.loadAddress, tapeHeader.fileSize, tapeHeader.execAddress, fileName);
|
|
break;
|
|
}
|
|
|
|
// Check the data type, only load machine code.
|
|
//
|
|
if(dstCMT == 0 && tapeHeader.dataType != SHARPMZ_CMT_MC)
|
|
return(3);
|
|
|
|
// Reset Emulator if loading direct to RAM. This clears out memory, resets monitor and places it in a known state.
|
|
//
|
|
if(dstCMT == 0)
|
|
sharpmz_reset(10, 50000);
|
|
|
|
// Load the data from tape to RAM.
|
|
//
|
|
EnableFpga(); // Start the transmission session, clear address and set ioctl_download.
|
|
spi8(SHARPMZ_FILE_ADDR_TX);
|
|
spi8(0x00);
|
|
if(dstCMT == 0) // Load to emulators RAM
|
|
{
|
|
spi8(SHARPMZ_MEMBANK_SYSRAM);
|
|
spi8((tapeHeader.loadAddress >> 8)&0xff);
|
|
spi8(tapeHeader.loadAddress & 0xff); // Location set inside tape header structure.
|
|
} else
|
|
{
|
|
spi8(SHARPMZ_MEMBANK_CMT_DATA);
|
|
spi8(0x00);
|
|
spi8(0x00);
|
|
}
|
|
|
|
sharpmz_debugf("[");
|
|
for (unsigned short i = 0; i < tapeHeader.fileSize; i += actualReadSize)
|
|
{
|
|
if (!(i & 127)) { sharpmz_debugf("*"); }
|
|
|
|
DISKLED_ON;
|
|
actualReadSize = sharpmz_file_read(&file, sector_buffer, 512);
|
|
DISKLED_OFF;
|
|
|
|
// First sector contains the header which has already been written, so just write the remainder.
|
|
//
|
|
if(i == 0)
|
|
{
|
|
actualReadSize -= MZ_TAPE_HEADER_SIZE;
|
|
memmove(sector_buffer, sector_buffer+MZ_TAPE_HEADER_SIZE, actualReadSize);
|
|
}
|
|
//sharpmz_debugf("Bytes to read, actual:%d, index:%d, sizeHeader:%d", actualReadSize, i, tapeHeader.fileSize);
|
|
if(actualReadSize > 0)
|
|
{
|
|
// Write the sector (or part) to the fpga memory.
|
|
spi_write(sector_buffer, actualReadSize, 0);
|
|
}
|
|
}
|
|
sharpmz_debugf("]\n");
|
|
DisableFpga();
|
|
|
|
// signal end of transmission
|
|
EnableFpga();
|
|
spi8(SHARPMZ_FILE_TX);
|
|
spi8(SHARPMZ_EOF);
|
|
DisableFpga();
|
|
|
|
// Now load header - this is done last because the emulator monitor wipes the stack area on reset.
|
|
//
|
|
EnableFpga(); // Start the transmission session, clear address and set ioctl_download.
|
|
spi8(SHARPMZ_FILE_ADDR_TX);
|
|
spi8(0x00); // Tape header position address: Bit 24
|
|
if(dstCMT == 0) // Load to emulators RAM
|
|
{
|
|
spi8(SHARPMZ_MEMBANK_SYSRAM); // Bits 23:16
|
|
spi8((MZ_TAPE_HEADER_STACK_ADDR >> 8) & 0xff); // Bits 15:8
|
|
spi8(MZ_TAPE_HEADER_STACK_ADDR & 0xff); // Bits 7:0
|
|
} else
|
|
{
|
|
spi8(SHARPMZ_MEMBANK_CMT_HDR); // Bits 23:16
|
|
spi8(0x00); // Bits 15:8
|
|
spi8(0x00); // Bits 7:0
|
|
}
|
|
//
|
|
spi_write((unsigned char *)&tapeHeader, MZ_TAPE_HEADER_SIZE, 0);
|
|
//
|
|
DisableFpga();
|
|
EnableFpga(); // Finally indicate end of transmission.
|
|
spi8(SHARPMZ_FILE_TX);
|
|
spi8(SHARPMZ_EOF);
|
|
DisableFpga();
|
|
|
|
time = GetTimer(0) - time;
|
|
sharpmz_debugf("Uploaded in %lu ms", time >> 20);
|
|
|
|
// Debug, show registers.
|
|
for(unsigned int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_debugf("Register (%02x) = %02x", i, sharpmz_read_config_register(i));
|
|
}
|
|
|
|
// Tidy up.
|
|
FileClose(&file);
|
|
|
|
// Dump out the memory if needed (generally for debug purposes).
|
|
if(dstCMT == 0) // Load to emulators RAM
|
|
{
|
|
sharpmz_read_ram((const char *)"memory.dump", SHARPMZ_MEMBANK_SYSRAM);
|
|
} else
|
|
{
|
|
sharpmz_read_ram((const char *)"cmt_header.dump", SHARPMZ_MEMBANK_CMT_HDR);
|
|
sharpmz_read_ram((const char *)"cmt_data.dump", SHARPMZ_MEMBANK_CMT_DATA);
|
|
}
|
|
|
|
// Remove the LF from the header filename, not needed.
|
|
//
|
|
for(int i=0; i < 17; i++)
|
|
{
|
|
if(tapeHeader.fileName[i] == 0x0d) tapeHeader.fileName[i] = 0x00;
|
|
}
|
|
|
|
// Debug, show registers.
|
|
for(unsigned int i=0; i < MAX_REGISTERS; i++)
|
|
{
|
|
sharpmz_debugf("Register (%02x) = %02x", i, sharpmz_read_config_register(i));
|
|
}
|
|
|
|
// Success.
|
|
//
|
|
return(0);
|
|
}
|
|
|
|
// Method to save the contents of the CMT buffer onto a disk based MZF file.
|
|
// The method reads the header, writes it and then reads the data (upto size specified in header) and write it.
|
|
//
|
|
short sharpmz_save_tape_from_cmt(const char *tapeFile)
|
|
{
|
|
short dataSize = 0;
|
|
unsigned short actualWriteSize;
|
|
unsigned short writeSize;
|
|
char fileName[17];
|
|
|
|
// Handle for the MZF file to be written.
|
|
//
|
|
fileTYPE file = {};
|
|
|
|
// Read the header, then data, but limit data size to the 'file size' stored in the header.
|
|
//
|
|
for(unsigned int mb=SHARPMZ_MEMBANK_CMT_HDR; mb <= SHARPMZ_MEMBANK_CMT_DATA; mb++)
|
|
{
|
|
EnableFpga(); // Setup the load address.
|
|
spi8(SHARPMZ_FILE_ADDR_RX);
|
|
spi8(0x00);
|
|
spi8(mb); // Memory bank to read.
|
|
spi8(0x00); // A15-A8
|
|
spi8(0x00); // A7-A0
|
|
spi8(0x00); // Setup to read addr first byte.
|
|
|
|
// The bank size is stored in the config.
|
|
//
|
|
if(mb == SHARPMZ_MEMBANK_CMT_HDR)
|
|
{
|
|
dataSize = MZ_TAPE_HEADER_SIZE;
|
|
} else
|
|
{
|
|
dataSize = tapeHeader.fileSize;
|
|
}
|
|
sharpmz_debugf("mb=%d, tapesize=%04x\n", mb, tapeHeader.fileSize);
|
|
for (; dataSize > 0; dataSize -= actualWriteSize)
|
|
{
|
|
sharpmz_debugf("mb=%d, dataSize=%04x, writeSize=%04x\n", mb, dataSize, writeSize);
|
|
if(mb == SHARPMZ_MEMBANK_CMT_HDR)
|
|
{
|
|
writeSize = MZ_TAPE_HEADER_SIZE;
|
|
} else
|
|
{
|
|
writeSize = dataSize > 512 ? 512 : dataSize;
|
|
}
|
|
spi_read(sector_buffer, writeSize, 0);
|
|
if(mb == SHARPMZ_MEMBANK_CMT_HDR)
|
|
{
|
|
memcpy(&tapeHeader, §or_buffer, MZ_TAPE_HEADER_SIZE);
|
|
|
|
// Now open the file for writing. If no name provided, use the one stored in the header.
|
|
//
|
|
if(tapeFile == 0)
|
|
{
|
|
for(int i=0; i < 17; i++)
|
|
{
|
|
fileName[i] = tapeHeader.fileName[i] == 0x0d ? 0x00 : fileName[i];
|
|
}
|
|
} else
|
|
{
|
|
memcpy(fileName, tapeHeader.fileName, 17);
|
|
}
|
|
|
|
// Open the memory image debug file for writing.
|
|
if (!sharpmz_file_write(&file, fileName))
|
|
{
|
|
sharpmz_debugf("Failed to open tape file:%s\n", fileName);
|
|
return(3);
|
|
}
|
|
}
|
|
DISKLED_ON;
|
|
actualWriteSize=FileWriteAdv(&file, sector_buffer, writeSize);
|
|
DISKLED_OFF;
|
|
}
|
|
|
|
// Indicate end of upload.
|
|
spi8(SHARPMZ_EOF);
|
|
DisableFpga();
|
|
}
|
|
|
|
// Close file to complete dump.
|
|
FileClose(&file);
|
|
|
|
return(0);
|
|
}
|
|
|
|
// Function from menu.cpp located here due to its static definition. Unneeded parts stripped out but otherwise it performs same
|
|
// actions.
|
|
//
|
|
void sharpmz_select_file(const char* pFileExt, unsigned char Options, char *fs_pFileExt, char chdir, char *SelectedPath)
|
|
{
|
|
sharpmz_debugf("pFileExt = %s\n", pFileExt);
|
|
(void)chdir;
|
|
|
|
if (strncasecmp(SHARPMZ_CORE_NAME, SelectedPath, strlen(SHARPMZ_CORE_NAME))) strcpy(SelectedPath, SHARPMZ_CORE_NAME);
|
|
|
|
ScanDirectory(SelectedPath, SCANF_INIT, pFileExt, Options);
|
|
if (!flist_nDirEntries())
|
|
{
|
|
SelectedPath[0] = 0;
|
|
ScanDirectory(SelectedPath, SCANF_INIT, pFileExt, Options);
|
|
}
|
|
|
|
AdjustDirectory(SelectedPath);
|
|
strcpy(fs_pFileExt, pFileExt);
|
|
}
|
|
|
|
// Method to return the default UI state.
|
|
//
|
|
int sharpmz_default_ui_state(void)
|
|
{
|
|
return(MENU_SHARPMZ_MAIN1);
|
|
}
|
|
|
|
// User interface for the SharpMZ Series emulator. This functionality has been located here to minimise changes on common
|
|
// code base and to limit common code case size.
|
|
// The same general programming structure is maintained to enable easier changes.
|
|
//
|
|
void sharpmz_ui(int idleState, int idle2State, int systemState, int selectFile,
|
|
uint32_t *parentstate, uint32_t *menustate, uint32_t *menusub, uint32_t *menusub_last,
|
|
uint32_t *menumask, char *selectedPath, const char **helptext, char *helptext_custom,
|
|
uint32_t *fs_ExtLen, uint32_t *fs_Options, uint32_t *fs_MenuSelect, uint32_t *fs_MenuCancel,
|
|
char *fs_pFileExt,
|
|
unsigned char menu, unsigned char select, unsigned char up, unsigned char down,
|
|
unsigned char left, unsigned char right, unsigned char plus, unsigned char minus)
|
|
{
|
|
// Locals - original variables are generally all lower case, variables specific to this method are capitalised on change of word.
|
|
//
|
|
static short romType;
|
|
static short machineModel = sharpmz_get_next_machine_model();
|
|
static short debugCPUFrequency = sharpmz_get_next_debug_cpufreq();
|
|
static short debugLedsBank = sharpmz_get_next_debug_leds_bank();
|
|
static short debugLedsSampleFrequency = sharpmz_get_next_debug_leds_smpfreq();
|
|
static short memoryBank = sharpmz_get_next_memory_bank();
|
|
static short fileDumped = 0;
|
|
static short scrollPos = 0;
|
|
static short volumeDir = 0;
|
|
int menuItem;
|
|
uint32_t subItem;
|
|
short romEnabled;
|
|
short itemCount;
|
|
char sBuf[40];
|
|
char *fileName;
|
|
|
|
(void)plus;
|
|
(void)minus;
|
|
|
|
// Idle2 state (MENU_NONE2) is our main hook, when the HandleUI state machine reaches this state, if the menu key is pressed,
|
|
// we takeover control in this method.
|
|
//
|
|
if(*menustate == (uint32_t)idle2State && menu)
|
|
{
|
|
OsdSetSize(16);
|
|
*menusub = 0;
|
|
OsdClear();
|
|
OsdEnable(DISABLE_KEYBOARD);
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
}
|
|
|
|
// The menustate originates in the HandleUI method, if a value is not recognised in the main switch statement in HandleUI then
|
|
// it is ignored. This method utilises this fact and operates on a set of states outside those used in HandleUI.
|
|
//
|
|
switch(*menustate)
|
|
{
|
|
/******************************************************************/
|
|
/* SharpMZ core menu */
|
|
/******************************************************************/
|
|
|
|
case MENU_SHARPMZ_MAIN1:
|
|
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle(user_io_get_core_name(), 0);
|
|
|
|
OsdWrite(menuItem++, " Main Menu", 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
OsdWrite(menuItem++, " Tape Storage \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
// Not yet implemented.
|
|
//OsdWrite(menuItem++, " Floppy Storage \x16", *menusub == subItem++, 0);
|
|
//*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " Machine \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " Display \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " Debug \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " System \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
for (; menuItem < 10; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem++, " Reset", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
OsdWrite(menuItem++, " Reload config", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
OsdWrite(menuItem++, " Save config", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
OsdWrite(menuItem++, " Reset config", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
// Set menu states, parent is the root menu, next is the processing menu 2.
|
|
//
|
|
*parentstate = MENU_SHARPMZ_MAIN1;
|
|
*menustate = MENU_SHARPMZ_MAIN2;
|
|
|
|
// set helptext with core display on top of basic info
|
|
sprintf(helptext_custom, " ");
|
|
strcat(helptext_custom, OsdCoreName());
|
|
strcat(helptext_custom, " ");
|
|
strcat(helptext_custom, SHARPMZ_HELPTEXT[0]);
|
|
*helptext = helptext_custom;
|
|
break;
|
|
|
|
case MENU_SHARPMZ_MAIN2:
|
|
// menu key closes menu
|
|
if (menu)
|
|
*menustate = idleState;
|
|
|
|
if (select || right)
|
|
{
|
|
switch (*menusub)
|
|
{
|
|
case 0: // Tape Storage
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
//case 1: // Floppy Storage
|
|
// *menustate = MENU_SHARPMZ_FLOPPY_STORAGE1;
|
|
// *menusub_last = *menusub;
|
|
// *menusub = 0;
|
|
// if(right) select = true;
|
|
// break;
|
|
|
|
case 1: // Machine
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
case 2: // Display
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
case 3: // Debug
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
case 4: // System
|
|
*menustate = systemState;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
case 5: // Reset Machine
|
|
if(select)
|
|
{
|
|
sharpmz_init();
|
|
*menustate = idleState;
|
|
}
|
|
break;
|
|
|
|
case 6: // Reload Settings
|
|
if(select)
|
|
{
|
|
sharpmz_reload_config(1);
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
}
|
|
break;
|
|
|
|
case 7: // Save Settings
|
|
if(select)
|
|
{
|
|
sharpmz_save_config();
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
}
|
|
break;
|
|
|
|
case 8: // Reset Settings
|
|
if(select)
|
|
{
|
|
sharpmz_reset_config(1);
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
}
|
|
break;
|
|
|
|
case 9: // Exit
|
|
*menustate = idleState;
|
|
if(right) select = true;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE1:
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Tape Storage", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
OsdWrite(menuItem++, " Load direct to RAM: *.MZF", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " Queue Tape: *.MZF", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, " Clear Queue ", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
// List out the current tape queue.
|
|
itemCount = 0;
|
|
while((fileName = sharpmz_get_next_filename(0)) != 0)
|
|
{
|
|
sprintf(sBuf, " %d> %s", itemCount++, fileName);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
OsdWrite(menuItem++, " Save Tape: *.MZF", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Auto Save Tape: ");
|
|
strcat(sBuf, sharpmz_get_auto_save_enabled_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
strcpy(sBuf, " Tape Buttons: ");
|
|
strcat(sBuf, sharpmz_get_tape_buttons_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Fast Tape Load: ");
|
|
strcat(sBuf, sharpmz_get_fasttape_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE2;
|
|
break;
|
|
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
*menusub_last = *menusub;
|
|
switch(*menusub)
|
|
{
|
|
// Load direct to RAM? This involves parsing the MZF header, copying the header (128 bytes) to 0x10F0 in the Z80 memory range
|
|
// then loading the remainder into the location specified (position 20) of size (position 18).
|
|
//
|
|
// Load from Tape? This involves sending the whole file to the emulator CMT buffer, it then plays the file into the
|
|
// emulator as pseudo PWM tape.
|
|
//
|
|
case 0:
|
|
case 1:
|
|
*fs_Options = SCANO_DIR;
|
|
sharpmz_select_file("MZFmzfMZTmzt", *fs_Options, fs_pFileExt, 1, selectedPath);
|
|
//sharpmz_select_file("MZFmzf", *fs_Options, fs_pFileExt, 1, selectedPath);
|
|
*fs_ExtLen = strlen(fs_pFileExt);
|
|
*fs_MenuSelect = (*menusub == 0 ? MENU_SHARPMZ_TAPE_STORAGE_LOAD_TAPE_TO_RAM : MENU_SHARPMZ_TAPE_STORAGE_QUEUE_TAPE_TO_CMT);
|
|
*fs_MenuCancel = MENU_SHARPMZ_MAIN1;
|
|
*menustate = selectFile;
|
|
break;
|
|
|
|
case 2:
|
|
sharpmz_clear_filelist();
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
case 3:
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE_SAVE_TAPE_FROM_CMT;
|
|
break;
|
|
|
|
case 4:
|
|
sharpmz_set_auto_save_enabled(sharpmz_get_auto_save_enabled() == 0 ? 1 : 0);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
case 5:
|
|
sharpmz_set_tape_buttons(sharpmz_get_tape_buttons()+1, 1);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
case 6:
|
|
sharpmz_set_fasttape(sharpmz_get_fasttape()+1, 1);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
case 7:
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_LOAD_TAPE_TO_RAM:
|
|
sharpmz_debugf("File selected to send to RAM: %s, for menu option:%04x\n", selectedPath, *menumask);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
if(selectedPath)
|
|
{
|
|
int fail=sharpmz_load_tape_to_ram(selectedPath, 0);
|
|
sharpmz_tape_header_t *tapeHeader = sharpmz_get_tape_header();
|
|
|
|
if(!fail)
|
|
OsdSetTitle("Tape Details", OSD_ARROW_LEFT);
|
|
else
|
|
OsdSetTitle(" Tape Error", OSD_ARROW_LEFT);
|
|
|
|
*menumask = 0x01; // Exit.
|
|
*parentstate = *menustate;
|
|
menuItem = 0;
|
|
|
|
if(!fail)
|
|
OsdWrite(menuItem++, " Tape Details", 0, 0);
|
|
else
|
|
OsdWrite(menuItem++, " Tape Error", 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
sprintf(sBuf, " File Size: %04x", tapeHeader->fileSize);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
strcpy(sBuf, " File Type: ");
|
|
strcat(sBuf, sharpmz_get_tape_type_string());
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
strcpy(sBuf, " File Name: ");
|
|
strcat(sBuf, tapeHeader->fileName);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
sprintf(sBuf, " Load Addr: %04x", tapeHeader->loadAddress);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
sprintf(sBuf, " Exec Addr: %04x", tapeHeader->execAddress);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
if(!fail)
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
else
|
|
{
|
|
switch(fail)
|
|
{
|
|
case 1:
|
|
strcpy(sBuf, " Unable to open file!");
|
|
break;
|
|
case 2:
|
|
strcpy(sBuf, " Unable to read header!");
|
|
break;
|
|
case 3:
|
|
strcpy(sBuf, " Not a m/code Program!");
|
|
break;
|
|
case 4:
|
|
strcpy(sBuf, " Not a valid tape!");
|
|
break;
|
|
}
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
}
|
|
for (; menuItem < OsdGetSize()-1; menuItem++) OsdWrite(menuItem, "", 0, 0);
|
|
OsdWrite(menuItem, " exit", true, 0);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE_LOAD_TAPE_TO_RAM2;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_LOAD_TAPE_TO_RAM2:
|
|
if (menu || select || left || up)
|
|
{
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_QUEUE_TAPE_TO_CMT:
|
|
sharpmz_debugf("File added to Queue: %s, for menu option:%04x\n", selectedPath, *menumask);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
if(selectedPath)
|
|
{
|
|
// Read in the header of the queued tape file.
|
|
//
|
|
int fail=sharpmz_read_tape_header(selectedPath);
|
|
sharpmz_tape_header_t *tapeHeader = sharpmz_get_tape_header();
|
|
|
|
// Limit number of items in queue, makes no sense to have too many and we run out of display space.
|
|
//
|
|
if(tapeQueue.elements < 5 && !fail)
|
|
{
|
|
sharpmz_push_filename(selectedPath);
|
|
OsdSetTitle("Tape Queued", OSD_ARROW_LEFT);
|
|
} else
|
|
{
|
|
OsdSetTitle("Queue Error", OSD_ARROW_LEFT);
|
|
}
|
|
|
|
*menumask = 0x01; // Exit.
|
|
*parentstate = *menustate;
|
|
menuItem = 0;
|
|
|
|
if(!fail)
|
|
{
|
|
OsdWrite(menuItem++, " Tape Details", 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
sprintf(sBuf, " File Size: %04x", tapeHeader->fileSize);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
strcpy(sBuf, " File Type: ");
|
|
strcat(sBuf, sharpmz_get_tape_type_string());
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
strcpy(sBuf, " File Name: ");
|
|
strcat(sBuf, tapeHeader->fileName);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
sprintf(sBuf, " Load Addr: %04x", tapeHeader->loadAddress);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
sprintf(sBuf, " Exec Addr: %04x", tapeHeader->execAddress);
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
} else
|
|
{
|
|
OsdWrite(menuItem++, " Queue Error", 0, 0);
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
if(!fail)
|
|
strcpy(sBuf, " Queue limit reached!");
|
|
else
|
|
{
|
|
switch(fail)
|
|
{
|
|
case 1:
|
|
strcpy(sBuf, " Unable to open file!");
|
|
break;
|
|
case 2:
|
|
strcpy(sBuf, " Unable to read header!");
|
|
break;
|
|
case 3:
|
|
strcpy(sBuf, " Not a m/code Program!");
|
|
break;
|
|
case 4:
|
|
strcpy(sBuf, " Not a valid tape!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
OsdWrite(menuItem++, sBuf, 0, 0);
|
|
}
|
|
for (; menuItem < OsdGetSize()-1; menuItem++) OsdWrite(menuItem, "", 0, 0);
|
|
OsdWrite(menuItem, " exit", true, 0);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE_QUEUE_TAPE_TO_CMT2;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_QUEUE_TAPE_TO_CMT2:
|
|
if (menu || select || left || up)
|
|
{
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_SAVE_TAPE_FROM_CMT:
|
|
sharpmz_save_tape_from_cmt((const char *)0);
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
case MENU_SHARPMZ_TAPE_STORAGE_SAVE_TAPE_FROM_CMT2:
|
|
*menustate = MENU_SHARPMZ_TAPE_STORAGE1;
|
|
break;
|
|
|
|
// Floppy Storage
|
|
case MENU_SHARPMZ_FLOPPY_STORAGE1:
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Floppy Storage", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_FLOPPY_STORAGE2;
|
|
break;
|
|
|
|
case MENU_SHARPMZ_FLOPPY_STORAGE2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
*menusub_last = *menusub;
|
|
switch(*menusub)
|
|
{
|
|
case 0:
|
|
break;
|
|
|
|
case 1:
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
// Machine configuration.
|
|
case MENU_SHARPMZ_MACHINE1:
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Machine", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
strcpy(sBuf, " Machine Model: ");
|
|
strcat(sBuf, sharpmz_get_machine_model_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " CPU Speed: ");
|
|
strcat(sBuf, sharpmz_get_cpu_speed_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
strcpy(sBuf, " Audio Source: ");
|
|
strcat(sBuf, sharpmz_get_audio_source_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Audio Volume: ");
|
|
strcat(sBuf, sharpmz_get_audio_volume_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Audio Mute: ");
|
|
strcat(sBuf, sharpmz_get_audio_mute_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
OsdWrite(menuItem++, " Rom Management \x16", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_MACHINE2;
|
|
break;
|
|
|
|
|
|
case MENU_SHARPMZ_MACHINE2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
switch(*menusub)
|
|
{
|
|
case 0: // Machine Model
|
|
//sharpmz_set_machine_model(sharpmz_get_machine_model() + 1, 1);
|
|
sharpmz_set_machine_model(sharpmz_get_machine_model() + 1, 1);
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
break;
|
|
|
|
case 1: // CPU Speed
|
|
sharpmz_set_cpu_speed((sharpmz_get_cpu_speed() + 1) & 0x07, 1);
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
break;
|
|
|
|
case 2: // Audio Source
|
|
sharpmz_set_audio_source(sharpmz_get_audio_source() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
break;
|
|
|
|
case 3: // Audio Volume
|
|
sharpmz_set_audio_volume((sharpmz_get_audio_volume() + (volumeDir ? -1 : +1)) & 0x0f, 1);
|
|
if(sharpmz_get_audio_volume() == 15) volumeDir = 1;
|
|
if(sharpmz_get_audio_volume() == 0) volumeDir = 0;
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
break;
|
|
|
|
case 4: // Audio Mute
|
|
sharpmz_set_audio_mute(sharpmz_get_audio_mute() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
break;
|
|
|
|
case 5: // Roms
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
*menusub_last = *menusub;
|
|
*menusub = 0;
|
|
if(right) select = true;
|
|
break;
|
|
|
|
case 6: // Exit
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = 1; //*menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = 1; //*menusub_last;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_ROMS1:
|
|
|
|
if(*menusub == 0)
|
|
{
|
|
scrollPos = 0;
|
|
}
|
|
if(down && *menusub > 9 && scrollPos < 3) { scrollPos++; (*menusub)--; }
|
|
if(up && *menusub < 10 && scrollPos > 0) { scrollPos--; (*menusub)++; }
|
|
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Rom Management", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
if(scrollPos == 0)
|
|
{
|
|
strcpy(sBuf, " Machine Model: ");
|
|
strcat(sBuf, sharpmz_get_machine_model_string(machineModel));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
if(scrollPos <= 1)
|
|
{
|
|
strcpy(sBuf, " User ROM: ");
|
|
strcat(sBuf, sharpmz_get_user_rom_enabled_string(machineModel));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
if(scrollPos <= 2)
|
|
{
|
|
strcpy(sBuf, " Floppy Disk ROM: ");
|
|
strcat(sBuf, sharpmz_get_fdc_rom_enabled_string(machineModel));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem++, " Enable Custom Rom: ", 0, 0);
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, MROM_IDX);
|
|
strcpy(sBuf, " Monitor (40x25) ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, MROM_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, MROM_80C_IDX);
|
|
strcpy(sBuf, " Monitor (80x25) ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, MROM_80C_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, CGROM_IDX);
|
|
strcpy(sBuf, " Char Generator ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, CGROM_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, KEYMAP_IDX);
|
|
strcpy(sBuf, " Key Mapping ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, KEYMAP_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, USERROM_IDX);
|
|
strcpy(sBuf, " User ROM ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, USERROM_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
romEnabled = sharpmz_get_custom_rom_enabled(machineModel, FDCROM_IDX);
|
|
strcpy(sBuf, " Floppy Disk ");
|
|
strcat(sBuf, sharpmz_get_custom_rom_enabled_string(romEnabled));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(romEnabled)
|
|
{
|
|
strcpy(sBuf, " \x16 ");
|
|
strcat(sBuf, sharpmz_get_rom_file(machineModel, FDCROM_IDX));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_ROMS2;
|
|
break;
|
|
|
|
|
|
case MENU_SHARPMZ_ROMS2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
int selectItem = *menusub + scrollPos;
|
|
|
|
if(selectItem > 3) selectItem += sharpmz_get_custom_rom_enabled(machineModel, MROM_IDX) ? 0 : 1;
|
|
if(selectItem > 5) selectItem += sharpmz_get_custom_rom_enabled(machineModel, MROM_80C_IDX) ? 0 : 1;
|
|
if(selectItem > 7) selectItem += sharpmz_get_custom_rom_enabled(machineModel, CGROM_IDX) ? 0 : 1;
|
|
if(selectItem > 9) selectItem += sharpmz_get_custom_rom_enabled(machineModel, KEYMAP_IDX) ? 0 : 1;
|
|
if(selectItem > 11) selectItem += sharpmz_get_custom_rom_enabled(machineModel, USERROM_IDX) ? 0 : 1;
|
|
if(selectItem > 13) selectItem += sharpmz_get_custom_rom_enabled(machineModel, FDCROM_IDX) ? 0 : 1;
|
|
|
|
switch(selectItem)
|
|
{
|
|
case 0:
|
|
machineModel = sharpmz_get_next_machine_model();
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
break;
|
|
|
|
case 1:
|
|
sharpmz_set_user_rom_enabled(machineModel, sharpmz_get_user_rom_enabled(machineModel) ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
break;
|
|
|
|
case 2:
|
|
sharpmz_set_fdc_rom_enabled(machineModel, sharpmz_get_fdc_rom_enabled(machineModel) ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
break;
|
|
|
|
case 3:
|
|
case 5:
|
|
case 7:
|
|
case 9:
|
|
case 11:
|
|
case 13:
|
|
switch(selectItem)
|
|
{
|
|
case 3:
|
|
romType = MROM_IDX;
|
|
break;
|
|
|
|
case 5:
|
|
romType = MROM_80C_IDX;
|
|
break;
|
|
|
|
case 7:
|
|
romType = CGROM_IDX;
|
|
break;
|
|
|
|
case 9:
|
|
romType = KEYMAP_IDX;
|
|
break;
|
|
|
|
case 11:
|
|
romType = USERROM_IDX;
|
|
break;
|
|
|
|
default:
|
|
romType = FDCROM_IDX;
|
|
break;
|
|
}
|
|
sharpmz_set_custom_rom_enabled(machineModel, romType, sharpmz_get_custom_rom_enabled(machineModel, romType) == 0);
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
break;
|
|
|
|
case 4:
|
|
case 6:
|
|
case 8:
|
|
case 10:
|
|
case 12:
|
|
case 14:
|
|
*fs_Options = SCANO_DIR;
|
|
sharpmz_select_file("ROMBINrombin", *fs_Options, fs_pFileExt, 1, selectedPath);
|
|
*fs_ExtLen = strlen(fs_pFileExt);
|
|
*fs_MenuSelect = MENU_SHARPMZ_ROM_FILE_SELECTED;
|
|
*fs_MenuCancel = MENU_SHARPMZ_ROMS1;
|
|
*menustate = selectFile;
|
|
break;
|
|
|
|
case 15:
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
*menusub = *menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MACHINE1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
case MENU_SHARPMZ_ROM_FILE_SELECTED:
|
|
if(!strncasecmp(selectedPath, SHARPMZ_CORE_NAME, 7)) strcpy(selectedPath, (char *) & selectedPath[8]);
|
|
sharpmz_debugf("File selected: %s, model:%d, for option:%04x\n", selectedPath, machineModel, romType);
|
|
sharpmz_set_rom_file(machineModel, romType, selectedPath);
|
|
*menustate = MENU_SHARPMZ_ROMS1;
|
|
break;
|
|
|
|
// DISPLAY Menu
|
|
case MENU_SHARPMZ_DISPLAY1:
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Display", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
strcpy(sBuf, " Display Type: ");
|
|
strcat(sBuf, sharpmz_get_display_type_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Video: ");
|
|
strcat(sBuf, sharpmz_get_vram_disable_mode_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Graphics: ");
|
|
strcat(sBuf, sharpmz_get_gram_disable_mode_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " VRAM CPU Wait: ");
|
|
strcat(sBuf, sharpmz_get_vram_wait_mode_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " PCG Mode: ");
|
|
strcat(sBuf, sharpmz_get_pcg_mode_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Aspect Ratio: ");
|
|
strcat(sBuf, sharpmz_get_aspect_ratio_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Scandoubler: ");
|
|
strcat(sBuf, sharpmz_get_scandoubler_fx_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_DISPLAY2;
|
|
break;
|
|
|
|
case MENU_SHARPMZ_DISPLAY2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
switch(*menusub)
|
|
{
|
|
case 0:
|
|
sharpmz_set_display_type((sharpmz_get_display_type() + 1) & 0x07, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 1:
|
|
sharpmz_set_vram_disable_mode(sharpmz_get_vram_disable_mode() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 2:
|
|
sharpmz_set_gram_disable_mode(sharpmz_get_gram_disable_mode() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 3:
|
|
sharpmz_set_vram_wait_mode(sharpmz_get_vram_wait_mode() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 4:
|
|
sharpmz_set_pcg_mode(sharpmz_get_pcg_mode() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 5:
|
|
sharpmz_set_aspect_ratio(sharpmz_get_aspect_ratio() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 6:
|
|
sharpmz_set_scandoubler_fx((sharpmz_get_scandoubler_fx() + 1) & 0x07, 1);
|
|
*menustate = MENU_SHARPMZ_DISPLAY1;
|
|
break;
|
|
|
|
case 7:
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
// Debug options.
|
|
case MENU_SHARPMZ_DEBUG1:
|
|
menuItem = 0;
|
|
subItem = 0;
|
|
*menumask = 0;
|
|
|
|
OsdSetTitle("Debug", OSD_ARROW_LEFT);
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
|
|
strcpy(sBuf, " Select Memory Bank: ");
|
|
strcat(sBuf, sharpmz_get_memory_bank_string(memoryBank));
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
if(fileDumped == 1)
|
|
{
|
|
strcpy(sBuf, " File ");
|
|
strcat(sBuf, sharpmz_get_memory_bank_file(memoryBank));
|
|
strcat(sBuf, " written!");
|
|
fileDumped = 0;
|
|
} else
|
|
{
|
|
strcpy(sBuf, " Dump To \x16 ");
|
|
strcat(sBuf, sharpmz_get_memory_bank_file(memoryBank));
|
|
}
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
OsdWrite(menuItem++, "", 0, 0);
|
|
strcpy(sBuf, " Debug Mode: ");
|
|
strcat(sBuf, sharpmz_get_debug_enable_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
// Display the debug menu only when enabled.
|
|
//
|
|
if(sharpmz_get_debug_enable())
|
|
{
|
|
strcpy(sBuf, " CPU Frequency: ");
|
|
strcat(sBuf, sharpmz_get_debug_cpufreq_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Debug LEDS: ");
|
|
strcat(sBuf, sharpmz_get_debug_leds_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
// Display the LED menu only when enabled.
|
|
//
|
|
if(sharpmz_get_debug_leds())
|
|
{
|
|
strcpy(sBuf, " Sample Freq: ");
|
|
strcat(sBuf, sharpmz_get_debug_leds_smpfreq_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Signal Block: ");
|
|
strcat(sBuf, sharpmz_get_debug_leds_bank_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
strcpy(sBuf, " Bank: ");
|
|
strcat(sBuf, sharpmz_get_debug_leds_subbank_string());
|
|
OsdWrite(menuItem++, sBuf, *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
}
|
|
}
|
|
|
|
for (; menuItem < 15; menuItem++)
|
|
{
|
|
OsdWrite(menuItem, "", 0, 0);
|
|
}
|
|
|
|
OsdWrite(menuItem, " exit", *menusub == subItem++, 0);
|
|
*menumask = (*menumask << 1) | 1;
|
|
|
|
*parentstate = *menustate;
|
|
*menustate = MENU_SHARPMZ_DEBUG2;
|
|
break;
|
|
|
|
case MENU_SHARPMZ_DEBUG2:
|
|
if (menu) {
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
if (select)
|
|
{
|
|
*menusub_last = *menusub;
|
|
switch(*menusub)
|
|
{
|
|
case 0: // Select Memory Bank to be dumped.
|
|
memoryBank = sharpmz_get_next_memory_bank();
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 1: // Dump selected Memory Bank
|
|
sharpmz_read_ram(sharpmz_get_memory_bank_file(memoryBank), memoryBank);
|
|
fileDumped = 1;
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 2: // Debug Enable
|
|
sharpmz_set_debug_enable(sharpmz_get_debug_enable() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 3: // CPU Frequency
|
|
debugCPUFrequency = sharpmz_get_next_debug_cpufreq();
|
|
sharpmz_set_debug_cpufreq(debugCPUFrequency, 1);
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 4: // Debug LEDS
|
|
sharpmz_set_debug_leds(sharpmz_get_debug_leds() ? 0 : 1, 1);
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 5: // Sample Frequency
|
|
debugLedsSampleFrequency = sharpmz_get_next_debug_leds_smpfreq();
|
|
sharpmz_set_debug_leds_smpfreq(debugLedsSampleFrequency, 1);
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 6: // Signal Block
|
|
debugLedsBank = sharpmz_get_next_debug_leds_bank();
|
|
sharpmz_set_debug_leds_bank(debugLedsBank, 1);
|
|
sharpmz_set_debug_leds_subbank(0, 1); // Always switch to auto if bank changed.
|
|
sharpmz_get_next_debug_leds_subbank(1); // And reset the next loop.
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 7: // Signal Bank
|
|
sharpmz_set_debug_leds_subbank(sharpmz_get_next_debug_leds_subbank(0), 1);
|
|
*menustate = MENU_SHARPMZ_DEBUG1;
|
|
break;
|
|
|
|
case 8: // Exit
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
break;
|
|
}
|
|
}
|
|
if (left)
|
|
{
|
|
*menustate = MENU_SHARPMZ_MAIN1;
|
|
*menusub = *menusub_last;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|