Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixforissue407 #408

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion targets/mega65/configdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static const struct xemutools_configdef_switch_st switch_options[] = {
{ "fastboot", "Try to use sleepless emulation mode during booting", &configdb.fastboot },
{ "matrixstart", "Start with matrix-mode activated", &configdb.matrixstart },
{ "matrixdisable", "Disable the matrix hotkey", &configdb.matrixdisable },
{ "ramcheckread", "Enabled warnings on reading unwritten memory (first 126K only)", &configdb.ramcheckread },
{ NULL }
};

Expand Down Expand Up @@ -152,7 +153,7 @@ static const void *do_not_save_opts[] = {
&configdb.matrixstart,
&configdb.dumpmem, &configdb.dumpscreen, &configdb.screenshot_and_exit,
&configdb.testing, &configdb.hyperdebug, &configdb.hyperdebugfreezer, &configdb.usestubrom, &configdb.useinitrom, &configdb.useutilmenu,
&configdb.cartbin8000, &configdb.winpos,
&configdb.cartbin8000, &configdb.winpos, &configdb.ramcheckread,
NULL
};

Expand Down
1 change: 1 addition & 0 deletions targets/mega65/configdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct configdb_st {
int matrixstart;
int matrixdisable;
char *winpos;
int ramcheckread;
};

extern struct configdb_st configdb;
Expand Down
116 changes: 108 additions & 8 deletions targets/mega65/dma65.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,13 @@ static unsigned int list_entry_pos = 0;
// channel.addr is a fixed-point value, with the lower 8 bits being the fractional part
#define DMA_ADDRESSING(channel) (((channel.addr >> 8) & 0xFFFFF) + channel.base)

struct ldm_st {
Uint32 x_col, y_col, slope, slope_accu;
Uint8 slope_type;
};

// source and target DMA "channels":
static struct {
static struct dma_channel_st {
int addr; // address of the current operation, it's a fixed-point math value
int base; // base address for "addr", always a "pure" number! It also contains the "megabyte selection", pre-shifted by << 20
int step; // step value, zero(HOLD)/negative/positive, this is a fixed point arithmetic value!!
Expand All @@ -79,6 +84,7 @@ static struct {
Uint8 mbyte; // megabyte slice selected during option read
int is_modulo; // modulo mode, if it's non-zero
int also_io; // channel access I/O instead of memory, if it's non-zero
struct ldm_st ldm; // LDM = Line Drawing Mode
} source, target;

static struct {
Expand Down Expand Up @@ -165,17 +171,51 @@ static Uint8 dma_read_list_next_byte ( void )
return data;
}


static XEMU_INLINE void address_stepping ( struct dma_channel_st *const channel )
{
if (XEMU_LIKELY(!(channel->ldm.slope_type & 0x80))) {
// normal, non-LDM (line drawning mode) method
channel->addr += channel->step;
return;
}
// otherwise, we must deal with LDM. The following code is based
// on ideas found in a sample C implementation written by btoschi. THANKS!!
// WARNING: in Xemu, I use a single variable for "addr" and lower 8 bit is the fractional part!!
if (channel->ldm.slope_type & 0x40) {
channel->addr += 0x800U; // +8 -> we always step in Y
if (channel->ldm.slope_accu > 0xFFFFU) {
channel->ldm.slope_accu &= 0xFFFFU;
if (channel->ldm.slope_type & 0x20)
channel->addr -= ((channel->addr & 0x700) == 0) ? channel->ldm.x_col + 0x100 : 0x100;
else
channel->addr += ((channel->addr & 0x700) == 0) ? channel->ldm.x_col + 0x100 : 0x100;
}
} else {
channel->addr += ((channel->addr & 0x700) == 0x700) ? channel->ldm.x_col + 0x100 : 0x100;
channel->ldm.slope_accu += channel->ldm.slope;
if (channel->ldm.slope_accu > 0xFFFFU) {
channel->ldm.slope_accu &= 0xFFFFU;
channel->addr += (channel->ldm.slope_type & 0x20) ? -0x800 : 0x800;
}
}
}


static XEMU_INLINE void copy_next ( void )
{
dma_write_target(dma_read_source());
source.addr += source.step;
target.addr += target.step;
//source.addr += source.step;
//target.addr += target.step;
address_stepping(&source);
address_stepping(&target);
}

static XEMU_INLINE void fill_next ( void )
{
dma_write_target(filler_byte);
target.addr += target.step;
//target.addr += target.step;
address_stepping(&target);
}

static XEMU_INLINE void swap_next ( void )
Expand All @@ -184,8 +224,10 @@ static XEMU_INLINE void swap_next ( void )
Uint8 da = dma_read_target();
dma_write_source(da);
dma_write_target(sa);
source.addr += source.step;
target.addr += target.step;
//source.addr += source.step;
//target.addr += target.step;
address_stepping(&source);
address_stepping(&target);
}

static XEMU_INLINE void mix_next ( void )
Expand All @@ -203,8 +245,10 @@ static XEMU_INLINE void mix_next ( void )
((~sa) & ( da) & minterms[1]) |
((~sa) & (~da) & minterms[0]) ;
dma_write_target(da);
source.addr += source.step;
target.addr += target.step;
//source.addr += source.step;
//target.addr += target.step;
address_stepping(&source);
address_stepping(&target);
}


Expand Down Expand Up @@ -291,6 +335,8 @@ void dma_write_reg ( int addr, Uint8 data )
source.mbyte = 0; // source MB
target.mbyte = 0; // target MB
length_byte3 = 0; // length byte for >=64K DMA sessions
source.ldm.slope_type = 0; // source: line drawing mode, slope type, do not enable line drawing mode by default
target.ldm.slope_type = 0; // target: -- "" --
if (enhanced_mode)
DEBUGDMA("DMA: initiation of ENCHANCED MODE DMA!!!!\n");
else
Expand Down Expand Up @@ -375,9 +421,63 @@ int dma_update ( void )
case 0x86: // byte value to be treated as "transparent" (ie: skip writing that data), if enabled
transparency = (transparency & 0x100) | (unsigned int)optval;
break;
case 0x87: // DMA line drawing mode TARGET - X col (LSB)
target.ldm.x_col = (target.ldm.x_col & 0xFF0000U) + (optval << 8); // Xemu integer + 8 bit fractional part arithmetic!
break;
case 0x88: // DMA line drawing mode TARGET - X col (MSB)
target.ldm.x_col = (target.ldm.x_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
break;
case 0x89: // DMA line drawing mode TARGET - Row Y col (LSB)
target.ldm.y_col = (target.ldm.y_col & 0xFF00U) + optval;
break;
case 0x8A: // DMA line drawing mode TARGET - Row Y col (MSB)
target.ldm.y_col = (target.ldm.y_col & 0x00FFU) + (optval << 8);
break;
case 0x8B: // DMA line drawing mode TARGET - Slope (LSB)
target.ldm.slope = (target.ldm.slope & 0xFF00U) + optval;
break;
case 0x8C: // DMA line drawing mode TARGET - Slope (MSB)
target.ldm.slope = (target.ldm.slope & 0x00FFU) + (optval << 8);
break;
case 0x8D: // DMA line drawing mode TARGET - Slope init value (LSB)
target.ldm.slope_accu = (target.ldm.slope_accu & 0xFF00U) + optval;
break;
case 0x8E: // DMA line drawing mode TARGET - Slope init value (MSB)
target.ldm.slope_accu = (target.ldm.slope_accu & 0x00FFU) + (optval << 8);
break;
case 0x8F: // DMA line drawing mode TARGET - Slope type
target.ldm.slope_type = optval;
break;
case 0x90: // extra high byte of DMA length (bits 23-16) to allow to have >64K DMA
length_byte3 = optval;
break;
case 0x97: // DMA line drawing mode SOURCE - X col (LSB)
source.ldm.x_col = (source.ldm.x_col & 0xFF0000U) + (optval << 8); // Xemu integer + 8 bit fractional part arithmetic!
break;
case 0x98: // DMA line drawing mode SOURCE - X col (MSB)
source.ldm.x_col = (source.ldm.x_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
break;
case 0x99: // DMA line drawing mode SOURCE - Row Y col (LSB)
source.ldm.y_col = (source.ldm.y_col & 0xFF00U) + optval;
break;
case 0x9A: // DMA line drawing mode SOURCE - Row Y col (MSB)
source.ldm.y_col = (source.ldm.y_col & 0x00FFU) + (optval << 8);
break;
case 0x9B: // DMA line drawing mode SOURCE - Slope (LSB)
source.ldm.slope = (source.ldm.slope & 0xFF00U) + optval;
break;
case 0x9C: // DMA line drawing mode SOURCE - Slope (MSB)
source.ldm.slope = (source.ldm.slope & 0x00FFU) + (optval << 8);
break;
case 0x9D: // DMA line drawing mode SOURCE - Slope init value (LSB)
source.ldm.slope_accu = (source.ldm.slope_accu & 0xFF00U) + optval;
break;
case 0x9E: // DMA line drawing mode SOURCE - Slope init value (MSB)
source.ldm.slope_accu = (source.ldm.slope_accu & 0x00FFU) + (optval << 8);
break;
case 0x9F: // DMA line drawing mode SOURCE - Slope type
source.ldm.slope_type = optval;
break;
default:
// maybe later we should keep this quiet ...
if ((opt & 0x80))
Expand Down
2 changes: 2 additions & 0 deletions targets/mega65/hypervisor.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ void hypervisor_start_machine ( void )
extract_version_string(hyppo_version_string, sizeof hyppo_version_string);
DEBUGPRINT("HYPERVISOR: HYPPO version \"%s\" (%s) starting with TRAP reset (#$%02X)" NL, hyppo_version_string, hickup_is_overriden ? "OVERRIDEN" : "built-in", TRAP_RESET);
hypervisor_enter(TRAP_RESET);
memory_reset_unwritten_debug_stat();
}


Expand Down Expand Up @@ -299,6 +300,7 @@ static inline void first_leave ( void )
hdos_notify_system_start_end();
xemu_sleepless_temporary_mode(0); // turn off temporary sleepless mode which may have been enabled before
vic_frame_counter_since_boot = 0;
//memory_reset_unwritten_debug_stat(); // FIXME/TODO: commented out since it generates a **tons** of warnings then with the "unwritten mem read" debug mode (-ramcheckread emu option)
DEBUGPRINT("HYPERVISOR: first return after RESET, end of processing workarounds." NL);
}

Expand Down
58 changes: 58 additions & 0 deletions targets/mega65/memory_mapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

// 512K is the max "main" RAM. Currently only 384K is used by M65. We want to make sure, the _total_ size is power of 2, so we can protect accesses with simple bit masks as a last-resort-protection
Uint8 main_ram[512 << 10];
static Uint8 main_ram_written[0x1F800U];
// 32K of colour RAM. VIC-IV can see this as for colour information only. The first 2K can be seen at the last 2K of
// the chip-RAM. Also, the first 1 or 2K can be seen in the C64-style I/O area too, at $D800
Uint8 colour_ram[0x8000];
Expand Down Expand Up @@ -162,12 +163,38 @@ static Uint32 policy4k[0x10]; // memory policy with MAP taken account (the real
static Uint8 zero_page_reader ( const Uint32 addr32 );
static void zero_page_writer ( const Uint32 addr32, const Uint8 data );


static void checked_reader_warning ( const Uint32 addr32 )
{
DEBUGPRINT("MEM: DEBUG: main RAM at linear address $%X has been read without prior write; PC=$%04X [$%X]" NL, addr32, cpu65.pc, memory_cpu_addr_to_linear(cpu65.pc, NULL));
}


static Uint8 zero_page_checked_reader ( const Uint32 addr32 ) {
if (!main_ram_written[addr32])
checked_reader_warning(addr32);
return zero_page_reader(addr32);
}
static void zero_page_checked_writer ( const Uint32 addr32, const Uint8 data ) {
main_ram_written[addr32] = 1;
zero_page_writer(addr32, data);
}

static Uint8 main_ram_reader ( const Uint32 addr32 ) {
return main_ram[addr32];
}
static void main_ram_writer ( const Uint32 addr32, const Uint8 data ) {
main_ram[addr32] = data;
}
static Uint8 main_ram_checked_reader ( const Uint32 addr32 ) {
if (!main_ram_written[addr32])
checked_reader_warning(addr32);
return main_ram[addr32];
}
static void main_ram_checked_writer ( const Uint32 addr32, const Uint8 data ) {
main_ram_written[addr32] = 1;
main_ram[addr32] = data;
}
static void shared_main_ram_writer ( const Uint32 addr32, const Uint8 data ) {
main_ram[addr32] = data;
colour_ram[addr32 - 0x1F800U] = data;
Expand Down Expand Up @@ -348,6 +375,30 @@ static struct mem_map_st mem_map[] = {

static XEMU_INLINE void slot_assignment_postprocessing ( const Uint32 slot )
{
if (XEMU_UNLIKELY(configdb.ramcheckread && mem_slot_rd_addr32[slot] < 0x1F800U)) {
if (mem_slot_rd_func[slot] == main_ram_reader) {
#ifdef MEM_USE_DATA_POINTERS
mem_slot_rd_data[slot] = NULL;
#endif
mem_slot_rd_func[slot] = main_ram_checked_reader;
} else if (mem_slot_rd_func[slot] == zero_page_reader) {
#ifdef MEM_USE_DATA_POINTERS
mem_slot_rd_data[slot] = NULL;
#endif
mem_slot_rd_func[slot] = zero_page_checked_reader;
}
if (mem_slot_wr_func[slot] == main_ram_writer) {
#ifdef MEM_USE_DATA_POINTERS
mem_slot_wr_data[slot] = NULL;
#endif
mem_slot_wr_func[slot] = main_ram_checked_writer;
} else if (mem_slot_wr_func[slot] == zero_page_writer) {
#ifdef MEM_USE_DATA_POINTERS
mem_slot_wr_data[slot] = NULL;
#endif
mem_slot_wr_func[slot] = zero_page_checked_writer;
}
}
mem_slot_rd_func_real[slot] = mem_slot_rd_func[slot];
mem_slot_wr_func_real[slot] = mem_slot_wr_func[slot];
#ifdef MEM_WATCH_SUPPORT
Expand Down Expand Up @@ -934,6 +985,7 @@ void memory_init (void )
// Initiailize memory content with something ...
// NOTE: make sure the first 2K of colour_ram is the **SAME** as the 2K part of main_ram at offset $1F800
memset(main_ram, 0x00, sizeof main_ram);
memory_reset_unwritten_debug_stat();
memset(colour_ram, 0x00, sizeof colour_ram);
memset(attic_ram, 0xFF, sizeof attic_ram);
DEBUGPRINT("MEM: memory decoder initialized, %uK fast, %uK attic, %uK colour, %uK font RAM" NL,
Expand All @@ -945,6 +997,12 @@ void memory_init (void )
}


void memory_reset_unwritten_debug_stat ( void )
{
memset(main_ram_written, 0x00, sizeof main_ram_written);
}


// Warning: this overwrites ref_slot!
static XEMU_INLINE Uint32 cpu_get_flat_addressing_mode_address ( const Uint8 index )
{
Expand Down
1 change: 1 addition & 0 deletions targets/mega65/memory_mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define XEMU_MEGA65_MEMORY_MAPPER_H_INCLUDED

extern void memory_init ( void );
extern void memory_reset_unwritten_debug_stat ( void );
extern void memory_set_rom_protection ( const bool protect );
extern void memory_reconfigure (
const Uint8 d030_value, const Uint8 new_io_mode, const Uint8 new_cpu_port0, const Uint8 new_cpu_port1,
Expand Down
2 changes: 2 additions & 0 deletions targets/mega65/vic4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,8 @@ static XEMU_INLINE void vic4_render_char_raster ( void )
char_fetch_offset = -char_fetch_offset;
if (SXA_VERTICAL_FLIP(color_data))
enable_bg_paint = 0;
else
enable_bg_paint = 1;
if (SXA_ATTR_BOLD(color_data) && SXA_ATTR_REVERSE(color_data) && !REG_VICIII_ATTRIBS)
used_palette = altpalette; // use the alternate palette from now in the scanline
else
Expand Down