6322 lines
200 KiB
JavaScript
6322 lines
200 KiB
JavaScript
/**************************************************************************
|
|
* SAE - Scripted Amiga Emulator
|
|
*
|
|
* https://github.com/naTmeg/ScriptedAmigaEmulator
|
|
*
|
|
* ©2012 Rupert Hausberger
|
|
* Commercial use is prohibited.
|
|
*
|
|
***************************************************************************
|
|
* Notes:
|
|
* - Ported from WinUAE 2.5.0
|
|
* - AGA support is commented out.
|
|
*
|
|
**************************************************************************/
|
|
|
|
function Playfield() {
|
|
function Decision() {
|
|
this.plfleft = 0;
|
|
this.plfright = 0;
|
|
this.plflinelen = 0;
|
|
this.diwfirstword = 0;
|
|
this.diwlastword = 0;
|
|
this.ctable = 0;
|
|
this.bplcon0 = 0;
|
|
this.bplcon2 = 0;
|
|
this.bplcon3 = 0;
|
|
/*#ifdef AGA
|
|
this.bplcon4 = 0;
|
|
#endif*/
|
|
this.nr_planes = 0;
|
|
this.bplres = 0;
|
|
this.ehb_seen = false;
|
|
this.ham_seen = false;
|
|
this.ham_at_start = false;
|
|
|
|
this.clr = function () {
|
|
this.plfleft = 0;
|
|
this.plfright = 0;
|
|
this.plflinelen = 0;
|
|
this.diwfirstword = 0;
|
|
this.diwlastword = 0;
|
|
this.ctable = 0;
|
|
this.bplcon0 = 0;
|
|
this.bplcon2 = 0;
|
|
this.bplcon3 = 0;
|
|
/*#ifdef AGA
|
|
this.bplcon4 = 0;
|
|
#endif*/
|
|
this.nr_planes = 0;
|
|
this.bplres = 0;
|
|
this.ehb_seen = false;
|
|
this.ham_seen = false;
|
|
this.ham_at_start = false;
|
|
};
|
|
|
|
this.set = function(src) {
|
|
this.plfleft = src.plfleft;
|
|
this.plfright = src.plfright;
|
|
this.plflinelen = src.plflinelen;
|
|
this.diwfirstword = src.diwfirstword;
|
|
this.diwlastword = src.diwlastword;
|
|
this.ctable = src.ctable;
|
|
this.bplcon0 = src.bplcon0;
|
|
this.bplcon2 = src.bplcon2;
|
|
this.bplcon3 = src.bplcon3;
|
|
/*#ifdef AGA
|
|
this.bplcon4 = src.bplcon4;
|
|
#endif*/
|
|
this.nr_planes = src.nr_planes;
|
|
this.bplres = src.bplres;
|
|
this.ehb_seen = src.ehb_seen;
|
|
this.ham_seen = src.ham_seen;
|
|
this.ham_at_start = src.ham_at_start;
|
|
}
|
|
}
|
|
|
|
function ColorEntry() {
|
|
this.color_regs_ecs = new Uint16Array(32);
|
|
//#ifndef AGA
|
|
this.acolors = new Uint32Array(32);
|
|
/*#else
|
|
this.acolors = new Uint32Array(256);
|
|
this.color_regs_aga = new Uint32Array(256);
|
|
#endif*/
|
|
this.borderblank = false;
|
|
}
|
|
|
|
function ColorChange() {
|
|
this.linepos = 0;
|
|
this.regno = 0;
|
|
this.value = 0;
|
|
|
|
this.set = function (v) {
|
|
this.linepos = v.linepos;
|
|
this.regno = v.regno;
|
|
this.value = v.value;
|
|
};
|
|
this.cmp = function(v) {
|
|
return (this.linepos == v.linepos && this.regno == v.regno && this.value == v.value ? 0 : 1);
|
|
}
|
|
}
|
|
|
|
function DrawInfo() {
|
|
this.first_sprite_entry = 0;
|
|
this.last_sprite_entry = 0;
|
|
this.first_color_change = 0;
|
|
this.last_color_change = 0;
|
|
this.nr_color_changes = 0;
|
|
this.nr_sprites = 0;
|
|
}
|
|
|
|
function VidBuffer() {
|
|
this.rowbytes = 0; /* Bytes per row in the memory pointed at by bufmem. */
|
|
this.pixbytes = 0; /* Bytes per pixel. */
|
|
/* size of this buffer */
|
|
this.width_allocated = 0;
|
|
this.height_allocated = 0;
|
|
/* size of max visible image */
|
|
this.outwidth = 0;
|
|
this.outheight = 0;
|
|
/* nominal size of image for centering */
|
|
this.inwidth = 0;
|
|
this.inheight = 0;
|
|
/* same but doublescan multiplier included */
|
|
this.inwidth2 = 0;
|
|
this.inheight2 = 0;
|
|
/* extra width, chipset hpos extra in right border */
|
|
this.extrawidth = 0;
|
|
|
|
//this.xoffset = 0; /* superhires pixels from left edge */
|
|
//this.yoffset = 0; /* lines from top edge */
|
|
this.inxoffset = 0; /* positive if sync positioning */
|
|
//this.inyoffset = 0;
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
/* drawing */
|
|
|
|
//const dblpfofs = [0, 2, 4, 8, 16, 32, 64, 128]; //DELETE
|
|
|
|
var dblpf_ms1 = new Uint8Array(256);
|
|
var dblpf_ms2 = new Uint8Array(256);
|
|
var dblpf_ms = new Uint8Array(256);
|
|
var dblpf_ind1 = new Uint8Array(256);
|
|
var dblpf_ind2 = new Uint8Array(256);
|
|
var dblpf_2nd1 = new Uint8Array(256);
|
|
var dblpf_2nd2 = new Uint8Array(256);
|
|
|
|
var linestate = new Uint8Array((MAXVPOS + 2) * 2 + 1); //[(MAXVPOS + 2) * 2 + 1];
|
|
for (var i = 0; i < linestate.length; i++)
|
|
linestate[i] = 0;
|
|
|
|
var line_data = []; //[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
|
|
for (var i = 0; i < (MAXVPOS + 2) * 2; i++) {
|
|
line_data[i] = [];
|
|
for (var j = 0; j < MAX_PLANES; j++) {
|
|
line_data[i][j] = new Uint32Array(MAX_WORDS_PER_LINE * 2);
|
|
for (var k = 0; k < MAX_WORDS_PER_LINE * 2; k++)
|
|
line_data[i][j][k] = 0;
|
|
}
|
|
}
|
|
|
|
var line_decisions = [];
|
|
for (var i = 0; i < 2 * (MAXVPOS + 2) + 1; i++)
|
|
line_decisions[i] = new Decision();
|
|
var color_tables = [];
|
|
for (var i = 0; i < 2; i++) {
|
|
color_tables[i] = [];
|
|
for (var j = 0; j < COLOR_TABLE_SIZE; j++)
|
|
color_tables[i][j] = new ColorEntry();
|
|
}
|
|
var color_changes = [];
|
|
for (var i = 0; i < 2; i++) {
|
|
color_changes[i] = [];
|
|
for (var j = 0; j < MAX_REG_CHANGE; j++)
|
|
color_changes[i][j] = new ColorChange();
|
|
}
|
|
var line_drawinfo = [];
|
|
for (var i = 0; i < 2; i++) {
|
|
line_drawinfo[i] = [];
|
|
for (var j = 0; j < 2 * (MAXVPOS + 2) + 1; j++)
|
|
line_drawinfo[i][j] = new DrawInfo();
|
|
}
|
|
|
|
var gfxvidinfo = {
|
|
maxblocklines:0,
|
|
drawbuffer: new VidBuffer(),
|
|
gfx_resolution_reserved: 0, // reserved space for currprefs.hresolution
|
|
gfx_vresolution_reserved: 0, // reserved space for currprefs.hresolution
|
|
xchange: 0, /* how many superhires pixels in one pixel in buffer */
|
|
ychange: 0 /* how many interlaced lines in one line in buffer */
|
|
};
|
|
|
|
var xlinebuffer = new Uint32Array(MAX_PIXELS_PER_LINE);
|
|
for (var i = 0; i < xlinebuffer.length; i++) xlinebuffer[i] = 0;
|
|
|
|
var ham_linebuf = new Uint32Array(MAX_PIXELS_PER_LINE << 1);
|
|
for (var i = 0; i < ham_linebuf.length; i++) ham_linebuf[i] = 0;
|
|
|
|
var apixels = new Uint8Array(MAX_PIXELS_PER_LINE << 1);
|
|
for (var i = 0; i < apixels.length; i++) apixels[i] = 0;
|
|
|
|
var colors_for_drawing = new ColorEntry();
|
|
var current_colors = new ColorEntry();
|
|
|
|
var xcolors = new Uint32Array(4096);
|
|
for (var i = 0; i < xcolors.length; i++) xcolors[i] = 0;
|
|
|
|
var thisline_decision = new Decision();
|
|
var thisline_changed = 0;
|
|
|
|
var amiga2aspect_line_map = null;
|
|
var native2amiga_line_map = null;
|
|
|
|
var curr_sprite_entries = null;
|
|
var prev_sprite_entries = null;
|
|
var curr_color_changes = null;
|
|
var prev_color_changes = null;
|
|
var curr_drawinfo = null;
|
|
var prev_drawinfo = null;
|
|
var curr_color_tables = null;
|
|
var prev_color_tables = null;
|
|
var current_change_set = 0;
|
|
|
|
var autoscale_bordercolors = 0;
|
|
var frame_redraw_necessary = 0;
|
|
|
|
var first_drawn_line = 0;
|
|
var last_drawn_line = 0;
|
|
var first_block_line = 0;
|
|
var last_block_line = 0;
|
|
var thisframe_first_drawn_line = 0;
|
|
var thisframe_last_drawn_line = 0;
|
|
|
|
var drawing_color_matches = -1;
|
|
var linedbl = 0, linedbld = 0;
|
|
var min_diwstart = 0;
|
|
var max_diwstop = 0;
|
|
var min_ypos_for_screen = 0;
|
|
var max_ypos_thisframe = 0;
|
|
|
|
var visible_left_border = 0;
|
|
var visible_right_border = 0;
|
|
var visible_left_start = 0;
|
|
var visible_right_stop = MAX_STOP;
|
|
var visible_top_start = 0;
|
|
var visible_bottom_stop = MAX_STOP;
|
|
var thisframe_y_adjust = 0;
|
|
var thisframe_y_adjust_real = 0;
|
|
var max_drawn_amiga_line = 0;
|
|
var linetoscr_x_adjust_bytes = 0;
|
|
var last_max_ypos = 0;
|
|
var extra_y_adjust = 0;
|
|
var center_reset = true;
|
|
this.framecnt = 0;
|
|
var last_redraw_point = 0;
|
|
var lores_shift = 0;
|
|
|
|
var dp_for_drawing = null;
|
|
var dip_for_drawing = null;
|
|
var hposblank = 0;
|
|
//var bplxor = 0;
|
|
|
|
var playfield_start = 0, playfield_end = 0;
|
|
var real_playfield_start = 0, real_playfield_end = 0;
|
|
var linetoscr_diw_start = 0, linetoscr_diw_end = 0;
|
|
var native_ddf_left = 0, native_ddf_right = 0;
|
|
|
|
var unpainted = 0; /* How many pixels in window coordinates which are to the left of the left border. */
|
|
var pixels_offset = 0;
|
|
var src_pixel = 0, ham_src_pixel = 0;
|
|
var ham_decode_pixel = 0;
|
|
var ham_lastcolor = 0;
|
|
|
|
var next_color_change = 0;
|
|
var next_color_entry = 0;
|
|
var remembered_color_entry = -1;
|
|
var color_src_match = -1;
|
|
var color_dest_match = -1;
|
|
var color_compare_result = 0;
|
|
|
|
var res_shift = 0;
|
|
var bplres = 0;
|
|
var bplplanecnt = 0;
|
|
var bplham = false;
|
|
var bplehb = false;
|
|
var issprites = 0;
|
|
var ecsshres = false;
|
|
var plf1pri = 0;
|
|
var plf2pri = 0;
|
|
var plf_sprite_mask = 0;
|
|
var bpldualpf = false;
|
|
var bpldualpfpri = false;
|
|
|
|
/*---------------------------------*/
|
|
/* sprites */
|
|
|
|
function Sprite() {
|
|
this.pt = 0;
|
|
this.xpos = 0;
|
|
this.vstart = 0;
|
|
this.vstop = 0;
|
|
this.dblscan = 0; /* AGA SSCAN2 */
|
|
this.armed = 0;
|
|
this.dmastate = 0;
|
|
this.dmacycle = 0;
|
|
this.ptxhpos = 0;
|
|
|
|
this.clr = function() {
|
|
this.pt = 0;
|
|
this.xpos = 0;
|
|
this.vstart = 0;
|
|
this.vstop = 0;
|
|
//this.dblscan = 0;
|
|
this.armed = 0;
|
|
this.dmastate = 0;
|
|
this.dmacycle = 0;
|
|
this.ptxhpos = 0;
|
|
}
|
|
}
|
|
|
|
function SpriteEntry() {
|
|
this.pos = 0;
|
|
this.max = 0;
|
|
this.first_pixel = 0;
|
|
this.has_attached = false;
|
|
}
|
|
|
|
function SpritePixelsBuf() {
|
|
this.attach = 0;
|
|
this.stdata = 0;
|
|
this.data = 0;
|
|
|
|
this.clr = function() {
|
|
this.attach = 0;
|
|
this.stdata = 0;
|
|
this.data = 0;
|
|
}
|
|
}
|
|
|
|
var sprinit = false;
|
|
var sprtaba = new Uint32Array(256);
|
|
var sprtabb = new Uint32Array(256);
|
|
var sprite_ab_merge = new Uint32Array(256);
|
|
var sprclx = new Uint32Array(16);
|
|
var clxmask = new Uint32Array(16);
|
|
|
|
var sprite_offs = new Uint8Array(256);
|
|
var clxtab = new Uint32Array(256);
|
|
|
|
var spr = [];
|
|
for (var i = 0; i < MAX_SPRITES; i++)
|
|
spr[i] = new Sprite();
|
|
|
|
/*union sps_union {
|
|
uae_u8 bytes[MAX_SPR_PIXELS * 2];
|
|
uae_u32 words[MAX_SPR_PIXELS * 2 / 4];
|
|
};*/
|
|
var spixstate = new Uint8Array(MAX_SPR_PIXELS << 1);
|
|
var spixels = new Uint16Array(MAX_SPR_PIXELS << 1);
|
|
for (var i = 0; i < MAX_SPR_PIXELS << 1; i++)
|
|
spixstate[i] = spixels[i] = 0;
|
|
|
|
var sprite_entries = []; //[2][MAX_SPR_PIXELS / 16];
|
|
for (var i = 0; i < 2; i++) {
|
|
sprite_entries[i] = [];
|
|
for (var j = 0; j < MAX_SPR_PIXELS >> 4; j++)
|
|
sprite_entries[i][j] = new SpriteEntry();
|
|
}
|
|
|
|
var spritepixels = [];
|
|
for (var i = 0; i < MAX_PIXELS_PER_LINE; i++)
|
|
spritepixels[i] = new SpritePixelsBuf();
|
|
|
|
var sprctl = new Uint16Array(MAX_SPRITES);
|
|
var sprpos = new Uint16Array(MAX_SPRITES);
|
|
for (var i = 0; i < MAX_SPRITES; i++)
|
|
sprctl[i] = sprpos[i] = 0;
|
|
|
|
/*#ifdef AGA
|
|
//[MAX_SPRITES][4]
|
|
var sprdata = [];
|
|
var sprdatb = [];
|
|
for (var i = 0; i < MAX_SPRITES; i++) {
|
|
sprdata[i] = new Uint16Array(4);
|
|
sprdatb[i] = new Uint16Array(4);
|
|
for (var j = 0; j < 4; j++) {
|
|
sprdata[i][j] = 0;
|
|
sprdatb[i][j] = 0;
|
|
}
|
|
}
|
|
#else*/
|
|
//[MAX_SPRITES][1]
|
|
var sprdata = [];
|
|
var sprdatb = [];
|
|
for (var i = 0; i < MAX_SPRITES; i++) {
|
|
sprdata[i] = new Uint16Array(1);
|
|
sprdatb[i] = new Uint16Array(1);
|
|
sprdata[i][0] = 0;
|
|
sprdatb[i][0] = 0;
|
|
}
|
|
//#endif
|
|
|
|
var clxcon = 0;
|
|
var clxcon_bpl_enable = 0;
|
|
var clxcon_bpl_match = 0;
|
|
var clxcon2 = 0;
|
|
var clxdat = 0;
|
|
|
|
var sprres = 0;
|
|
var nr_armed = 0;
|
|
|
|
var sprite_buffer_res = 0;
|
|
var sprite_vblank_endline = VBLANK_SPRITE_PAL;
|
|
var sprite_minx = 0;
|
|
var sprite_maxx = 0;
|
|
var sprite_width = 0;
|
|
var sprite_first_x = 0;
|
|
var sprite_last_x = 0;
|
|
|
|
var sprite_0 = 0;
|
|
var sprite_0_width = 0;
|
|
var sprite_0_height = 0;
|
|
var sprite_0_doubled = 0;
|
|
var sprite_0_colors = [0,0,0,0];
|
|
|
|
var next_sprite_entry = 0;
|
|
var next_sprite_forced = 1;
|
|
var prev_next_sprite_entry = 0;
|
|
var last_sprite_point = 0;
|
|
//var magic_sprite_mask = 0xff;
|
|
|
|
/*---------------------------------*/
|
|
/* playfield */
|
|
|
|
var bplcon0 = 0;
|
|
var bplcon1 = 0;
|
|
var bplcon2 = 0;
|
|
var bplcon3 = 0;
|
|
var bplcon4 = 0;
|
|
|
|
var bpl1mod = 0;
|
|
var bpl2mod = 0;
|
|
|
|
var bplxdat = [0,0,0,0,0,0,0,0];
|
|
var bplpt = [0,0,0,0,0,0,0,0];
|
|
var bplptx = [0,0,0,0,0,0,0,0];
|
|
|
|
var diwstrt = 0;
|
|
var diwstop = 0;
|
|
var ddfstrt = 0;
|
|
var ddfstrt_old_hpos = -1;
|
|
var ddfstop = 0;
|
|
var ddf_change = 0;
|
|
var diwhigh = 0;
|
|
var diwhigh_written = false;
|
|
|
|
var hdiwstate = 0;
|
|
|
|
var beamcon0 = 0;
|
|
var new_beamcon0 = 0;
|
|
|
|
this.vpos = 0;
|
|
this.vpos_count = 0;
|
|
this.vpos_count_diff = 0;
|
|
this.hpos = function () {
|
|
return Math.floor((AMIGA.events.currcycle - AMIGA.events.eventtab[EV_HSYNC].oldcycles) * CYCLE_UNIT_INV);
|
|
};
|
|
var vpos_previous = 0;
|
|
var hpos_previous = 0;
|
|
|
|
this.maxvpos = MAXVPOS;
|
|
this.maxvpos_nom = MAXVPOS;
|
|
this.maxvpos_total = MAXVPOS;
|
|
this.maxhpos = MAXHPOS;
|
|
this.maxhpos_short = MAXHPOS;
|
|
|
|
this.lof_store = 0;
|
|
this.lof_current = 0;
|
|
this.lof_previous = 0;
|
|
this.lof_changed = 0;
|
|
this.lof_changing = 0;
|
|
this.lol = 0;
|
|
|
|
this.vblank_hz = 0;
|
|
|
|
var aga_mode = 0;
|
|
var direct_rgb = 0;
|
|
|
|
var prevbpl = []; //[2][MAXVPOS][8];
|
|
for (var i = 0; i < 2; i++) {
|
|
prevbpl[i] = [];
|
|
for (var j = 0; j < MAXVPOS; j++) {
|
|
prevbpl[i][j] = new Uint32Array(8);
|
|
for (var k = 0; k < 8; k++) {
|
|
prevbpl[i][j][k] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//var scandoubled_line = 0;
|
|
var doublescan = 0;
|
|
var interlace_seen = 0;
|
|
var interlace_changed = 0;
|
|
var lof_togglecnt_nlace = 0;
|
|
var lof_togglecnt_lace = 0;
|
|
var nlace_cnt = 0;
|
|
|
|
var minfirstline = 0;
|
|
var equ_vblank_endline = 0;
|
|
var equ_vblank_toggle = false;
|
|
|
|
this.vtotal = MAXVPOS_PAL;
|
|
this.htotal = MAXHPOS_PAL;
|
|
this.hsstop = 0;
|
|
this.hbstrt = 0;
|
|
this.hbstop = 0;
|
|
this.vsstop = 0;
|
|
this.vbstrt = 0;
|
|
this.vbstop = 0;
|
|
this.hsstrt = 0;
|
|
this.vsstrt = 0;
|
|
this.hcenter = 0;
|
|
var hsyncstartpos = 0;
|
|
var hsyncendpos = 0;
|
|
|
|
var diwstate = 0;
|
|
var ddfstate = 0;
|
|
var diw_change = 2;
|
|
var diw_hstrt = 0;
|
|
var diw_hstop = 0;
|
|
var diw_hcounter = 0;
|
|
var last_hdiw = 0;
|
|
|
|
var diwfirstword = 0;
|
|
var diwlastword = 0;
|
|
var plffirstline = 0;
|
|
var plflastline = 0;
|
|
|
|
var plfstrt = 0;
|
|
var plfstrt_sprite = 0;
|
|
var plfstrt_start = 0;
|
|
var plfstop = 0;
|
|
|
|
var plf_state = 0;
|
|
|
|
var nextline_how = 0;
|
|
var next_lineno = 0;
|
|
var prev_lineno = -1;
|
|
|
|
var first_bpl_vpos = 0;
|
|
var first_planes_vpos = 0;
|
|
var last_planes_vpos = 0;
|
|
var firstword_bplcon1 = 0;
|
|
var diwfirstword_total = 0;
|
|
var diwlastword_total = 0;
|
|
var ddffirstword_total = 0;
|
|
var ddflastword_total = 0;
|
|
var plffirstline_total = 0;
|
|
var plflastline_total = 0;
|
|
|
|
/*var lightpen_active = 0;
|
|
var lightpen_triggered = 0;
|
|
var lightpen_cx = 0;
|
|
var lightpen_cy = 0;
|
|
var lightpen_y1 = -1;
|
|
var lightpen_y2 = -1;
|
|
var vpos_lpen = 0;
|
|
var hpos_lpen = 0;*/
|
|
|
|
var bplcon0_d = 0;
|
|
var bplcon0_dd = 0;
|
|
var bplcon1_hpos = 0;
|
|
var bplcon1t = 0;
|
|
var bplcon1t2 = 0;
|
|
|
|
var badmode = 0;
|
|
var bplcon0_res = 0;
|
|
var bplcon0_planes = 0;
|
|
var bplcon0_planes_limit = 0;
|
|
|
|
var fmode = 0;
|
|
var fetchmode = 0;
|
|
var fetchunit = 0;
|
|
var fetchunit_mask = 0;
|
|
const fetchunits = [ 8,8,8,0, 16,8,8,0, 32,16,8,0 ];
|
|
var fetchstart = 0;
|
|
var fetchstart_shift = 0;
|
|
var fetchstart_mask = 0;
|
|
const fetchstarts = [ 3,2,1,0, 4,3,2,0, 5,4,3,0 ];
|
|
var fm_maxplane = 0;
|
|
var fm_maxplane_shift = 0;
|
|
const fm_maxplanes = [ 3,2,1,0, 3,3,2,0, 3,3,3,0 ];
|
|
var real_bitplane_number = []; //[3][3][9];
|
|
|
|
var fetch_state = 0;
|
|
var fetch_cycle = 0;
|
|
var fetch_modulo_cycle = 0;
|
|
|
|
const cycle_sequences = [[2,1,2,1,2,1,2,1], [4,2,3,1,4,2,3,1], [8,4,6,2,7,3,5,1]];
|
|
var cycle_diagram_shift = 0;
|
|
var cycle_diagram_table = null; //[3][3][9][32];
|
|
var cycle_diagram_free_cycles = []; //[3][3][9];
|
|
var cycle_diagram_total_cycles = []; //[3][3][9];
|
|
var curr_diagram = [];
|
|
|
|
var estimated_last_fetch_cycle = 0;
|
|
|
|
var bpldmasetuphpos = -1;
|
|
var bpldmasetupphase = 0;
|
|
|
|
var bpl1dat_written = false;
|
|
var bpl1dat_written_at_least_once = false;
|
|
var bpl1dat_early = false;
|
|
var plfleft_real = -1;
|
|
|
|
var out_nbits = 0;
|
|
var out_offs = 0;
|
|
var outword = new Uint32Array(MAX_PLANES);
|
|
var todisplay = []; //[MAX_PLANES][4];
|
|
for (var i = 0; i < MAX_PLANES; i++) {
|
|
todisplay[i] = new Uint32Array(4);
|
|
for (var j = 0; j < 4; j++)
|
|
todisplay[i][j] = 0;
|
|
}
|
|
var fetched = new Uint32Array(MAX_PLANES);
|
|
for (var i = 0; i < MAX_PLANES; i++)
|
|
fetched[i] = 0;
|
|
/*#ifdef AGA
|
|
var fetched_aga0 = new Uint32Array(MAX_PLANES);
|
|
var fetched_aga1 = new Uint32Array(MAX_PLANES);
|
|
#endif*/
|
|
|
|
var toscr_res = 0;
|
|
var toscr_nr_planes = 0;
|
|
var toscr_nr_planes2 = 0;
|
|
var toscr_delay1 = 0;
|
|
var toscr_delay2 = 0;
|
|
var toscr_nbits = 0;
|
|
|
|
//var fetchwidth = 0;
|
|
var delayoffset = 0;
|
|
|
|
var last_decide_line_hpos = -1;
|
|
var last_ddf_pix_hpos = -1;
|
|
var last_sprite_hpos = -1;
|
|
var last_fetch_hpos = -1;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* common */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/*function RES_SHIFT(res) {
|
|
return res == RES_LORES ? 8 : (res == RES_HIRES ? 4 : 2);
|
|
}*/
|
|
function GET_RES_DENISE(con0) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) con0 &= ~0x40; // SUPERHIRES
|
|
return (con0 & 0x8000) ? RES_HIRES : ((con0 & 0x40) ? RES_SUPERHIRES : RES_LORES);
|
|
}
|
|
function GET_RES_AGNUS(con0) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) con0 &= ~0x40; // SUPERHIRES
|
|
return (con0 & 0x8000) ? RES_HIRES : ((con0 & 0x40) ? RES_SUPERHIRES : RES_LORES);
|
|
}
|
|
function GET_SPRITEWIDTH(fmode) {
|
|
return (((fmode >> 2) & 3) == 3 ? 64 : ((fmode >> 2) & 3) == 0 ? 16 : 32);
|
|
}
|
|
function GET_PLANES(con0) {
|
|
if ((con0 & 0x0010) && (con0 & 0x7000)) return 0; // >8 planes = 0 planes
|
|
if (con0 & 0x0010) return 8; // AGA 8-planes bit
|
|
return (con0 >> 12) & 7; // normal planes bits
|
|
}
|
|
function GET_PLANES_LIMIT(con0) {
|
|
var res = GET_RES_AGNUS(con0);
|
|
var planes = GET_PLANES(con0);
|
|
return real_bitplane_number[fetchmode][res][planes];
|
|
}
|
|
|
|
this.nodraw = function () {
|
|
return this.framecnt != 0;
|
|
};
|
|
|
|
this.doflickerfix = function () {
|
|
return AMIGA.config.video.vresolution && doublescan < 0 && this.vpos < MAXVPOS;
|
|
};
|
|
|
|
this.current_maxvpos = function () {
|
|
return this.maxvpos + (this.lof_store ? 1 : 0);
|
|
};
|
|
|
|
this.is_custom_vsync = function () {
|
|
var vp = this.vpos + 1;
|
|
var vpc = this.vpos_count + 1;
|
|
/* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */
|
|
if (vp >= this.maxvpos_total)
|
|
vp = 0;
|
|
/* vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely */
|
|
return vp == this.maxvpos + this.lof_store || vp == this.maxvpos + this.lof_store + 1 || vpc >= MAXVPOS;
|
|
};
|
|
|
|
this.is_linetoggle = function () {
|
|
if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
return true; //NTSC and !LOLDIS -> LOL toggles every line
|
|
else if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) && AMIGA.config.video.ntsc)
|
|
return true; //hardwired NTSC Agnus
|
|
return false;
|
|
};
|
|
|
|
this.is_last_line = function () {
|
|
return this.vpos + 1 == this.maxvpos + this.lof_store;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* drawing */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
function setup_drawing_tables() {
|
|
for (var i = 0; i < 256; i++) {
|
|
var plane1 = ((i >> 0) & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
|
|
var plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
|
|
|
|
dblpf_2nd1[i] = plane1 == 0 && plane2 != 0;
|
|
dblpf_2nd2[i] = plane2 != 0;
|
|
|
|
/*#ifdef AGA
|
|
dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1;
|
|
dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2;
|
|
#endif*/
|
|
dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0;
|
|
dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8;
|
|
dblpf_ms[i] = i == 0 ? 16 : 8;
|
|
|
|
if (plane2 > 0)
|
|
plane2 += 8;
|
|
dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
|
|
dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
|
|
}
|
|
}
|
|
|
|
this.recreate_aspect_maps = function () {
|
|
var i, h = gfxvidinfo.drawbuffer.height_allocated;
|
|
if (h == 0)
|
|
return;
|
|
|
|
linedbld = linedbl = AMIGA.config.video.vresolution;
|
|
if (doublescan > 0 && interlace_seen <= 0) {
|
|
linedbl = 0;
|
|
linedbld = 1;
|
|
}
|
|
|
|
amiga2aspect_line_map = new Int32Array((MAXVPOS + 1) * 2 + 1);
|
|
native2amiga_line_map = new Int32Array(h);
|
|
|
|
var maxl = (MAXVPOS + 1) << linedbld;
|
|
min_ypos_for_screen = minfirstline << linedbl;
|
|
max_drawn_amiga_line = -1;
|
|
for (i = 0; i < maxl; i++) {
|
|
var v = i - min_ypos_for_screen;
|
|
if (v >= h && max_drawn_amiga_line < 0)
|
|
max_drawn_amiga_line = i - min_ypos_for_screen;
|
|
if (i < min_ypos_for_screen || v >= h)
|
|
v = -1;
|
|
amiga2aspect_line_map[i] = v;
|
|
}
|
|
if (max_drawn_amiga_line < 0)
|
|
max_drawn_amiga_line = maxl - min_ypos_for_screen;
|
|
max_drawn_amiga_line >>>= linedbl;
|
|
|
|
if (AMIGA.config.video.ycenter) {
|
|
extra_y_adjust = (h - (this.maxvpos_nom << linedbl)) >> 1;
|
|
if (extra_y_adjust < 0)
|
|
extra_y_adjust = 0;
|
|
}
|
|
|
|
for (i = 0; i < h; i++)
|
|
native2amiga_line_map[i] = -1;
|
|
|
|
for (i = maxl - 1; i >= min_ypos_for_screen; i--) {
|
|
if (amiga2aspect_line_map[i] == -1)
|
|
continue;
|
|
for (var j = amiga2aspect_line_map[i]; j < h && native2amiga_line_map[j] == -1; j++)
|
|
native2amiga_line_map[j] = i >> linedbl;
|
|
}
|
|
|
|
gfxvidinfo.xchange = 1 << (RES_MAX - AMIGA.config.video.hresolution);
|
|
gfxvidinfo.ychange = linedbl ? 1 : 2;
|
|
|
|
visible_left_start = 0;
|
|
visible_right_stop = MAX_STOP;
|
|
visible_top_start = 0;
|
|
visible_bottom_stop = MAX_STOP;
|
|
//console.log('recreate_aspect_maps', amiga2aspect_line_map, native2amiga_line_map);
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
function xlinecheck(id, start, end) {
|
|
var xstart = start * gfxvidinfo.drawbuffer.pixbytes;
|
|
var xend = end * gfxvidinfo.drawbuffer.pixbytes;
|
|
var end1 = gfxvidinfo.drawbuffer.rowbytes * gfxvidinfo.drawbuffer.height;
|
|
var min = Math.floor(linetoscr_x_adjust_bytes / gfxvidinfo.drawbuffer.pixbytes);
|
|
var ok = 1;
|
|
|
|
if (xend > end1 || xstart >= end1)
|
|
ok = 0;
|
|
if ((xstart % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes)
|
|
ok = 0;
|
|
if ((xend % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes)
|
|
ok = 0;
|
|
if (xstart >= xend)
|
|
ok = 0;
|
|
if (xend - xstart > gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes)
|
|
ok = 0;
|
|
|
|
if (!ok) {
|
|
console.log(id, start, end, min);
|
|
BUG.info('xlinecheck() ERROR %d-%d (%dx%dx%d %d)',
|
|
start - min, end - min, gfxvidinfo.drawbuffer.width, gfxvidinfo.drawbuffer.height,
|
|
gfxvidinfo.drawbuffer.pixbytes, gfxvidinfo.drawbuffer.rowbytes);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
|
|
function max_diwlastword() {
|
|
return (0x1d4 - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift;
|
|
}
|
|
|
|
function xshift(x, shift) {
|
|
return shift < 0 ? x >> (-shift) : x << shift;
|
|
}
|
|
|
|
function coord_hw_to_window_x(x) {
|
|
return (x - DISPLAY_LEFT_SHIFT) << lores_shift;
|
|
}
|
|
function coord_window_to_hw_x(x) {
|
|
return (x >> lores_shift) + DISPLAY_LEFT_SHIFT;
|
|
}
|
|
|
|
function coord_diw_to_window_x(x) {
|
|
return (x - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift;
|
|
}
|
|
function coord_window_to_diw_x(x) {
|
|
return (x >> lores_shift) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET;
|
|
}
|
|
|
|
/*function coord_native_to_amiga_x(x) {
|
|
return xshift(x + visible_left_border, 1 - lores_shift) + 2 * DISPLAY_LEFT_SHIFT - 2 * DIW_DDF_OFFSET;
|
|
}
|
|
function coord_native_to_amiga_y(y) {
|
|
return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
|
|
}*/
|
|
|
|
function res_shift_from_window(x) {
|
|
return res_shift >= 0 ? x >> res_shift : x << -res_shift;
|
|
}
|
|
/*function res_shift_from_amiga(x) {
|
|
return res_shift >= 0 ? x >> res_shift : x << -res_shift;
|
|
}*/
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.render_screen = function (immediate) {
|
|
if (AMIGA.config.video.enabled)
|
|
AMIGA.video.render();
|
|
return true;
|
|
};
|
|
this.show_screen = function () {
|
|
if (AMIGA.config.video.enabled)
|
|
AMIGA.video.show(); //flip
|
|
return true;
|
|
};
|
|
|
|
/*function flush_line(vb, lineno) {
|
|
AMIGA.video.drawline(lineno, xlinebuffer, linetoscr_x_adjust_bytes >> 2);
|
|
}
|
|
function flush_block(vb, first_line, last_line) {
|
|
console.log('flush_block() called', first_line, last_line);
|
|
}
|
|
function flush_screen(vb, first_line, last_line) {
|
|
console.log('flush_screen() called', first_line, last_line);
|
|
}
|
|
this.do_flush_line = function(vb, lineno) {
|
|
if (lineno < first_drawn_line)
|
|
first_drawn_line = lineno;
|
|
if (lineno > last_drawn_line)
|
|
last_drawn_line = lineno;
|
|
|
|
if (gfxvidinfo.maxblocklines == 0)
|
|
flush_line(vb, lineno);
|
|
else {
|
|
if ((last_block_line + 2) < lineno) {
|
|
if (first_block_line != NO_BLOCK)
|
|
flush_block(vb, first_block_line, last_block_line);
|
|
first_block_line = lineno;
|
|
}
|
|
last_block_line = lineno;
|
|
if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
|
|
flush_block(vb, first_block_line, last_block_line);
|
|
first_block_line = last_block_line = NO_BLOCK;
|
|
}
|
|
}
|
|
}*/
|
|
|
|
this.do_flush_line = function (vb, lineno) {
|
|
if (lineno < first_drawn_line)
|
|
first_drawn_line = lineno;
|
|
if (lineno > last_drawn_line)
|
|
last_drawn_line = lineno;
|
|
|
|
AMIGA.video.drawline(lineno, xlinebuffer, linetoscr_x_adjust_bytes >> 2);
|
|
};
|
|
|
|
/*this.do_flush_screen = function(vb, start, stop) {
|
|
if (gfxvidinfo.maxblocklines != 0 && first_block_line != NO_BLOCK)
|
|
flush_block(vb, first_block_line, last_block_line);
|
|
if (start <= stop)
|
|
flush_screen(vb, start, stop);
|
|
}*/
|
|
|
|
/*---------------------------------*/
|
|
|
|
function is_ehb(con0, con2) {
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA)
|
|
return ((con0 & 0x7010) == 0x6000);
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)
|
|
return ((con0 & 0xFC00) == 0x6000 || (con0 & 0xFC00) == 0x7000);
|
|
|
|
return ((con0 & 0xFC00) == 0x6000 || (con0 & 0xFC00) == 0x7000);// && !currprefs.cs_denisenoehb;
|
|
}
|
|
|
|
function is_ham(con0) {
|
|
var p = GET_PLANES(con0);
|
|
if (!(con0 & 0x800))
|
|
return false;
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
// AGA only has 6 or 8 plane HAM
|
|
if (p == 6 || p == 8)
|
|
return true;
|
|
} else {
|
|
// OCS/ECS also supports 5 plane HAM
|
|
if (GET_RES_DENISE(con0) > 0)
|
|
return 0;
|
|
if (p >= 5)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*function get_sprite_mask() {
|
|
var hi = new Uint64(0x00000000,0xFFFF0000);
|
|
hi.lshift(4 * plf2pri);
|
|
var lo = new Uint64(0x00000000,0x0000FFFF);
|
|
lo.lshift(4 * plf1pri);
|
|
hi.or(lo);
|
|
return hi;
|
|
}*/
|
|
|
|
this.pfield_expand_dp_bplcon = function () {
|
|
bplres = dp_for_drawing.bplres;
|
|
bplplanecnt = dp_for_drawing.nr_planes;
|
|
bplham = dp_for_drawing.ham_seen;
|
|
bplehb = dp_for_drawing.ehb_seen;
|
|
if ((AMIGA.config.chipset.mask & CSMASK_AGA) && (dp_for_drawing.bplcon2 & 0x0200))
|
|
bplehb = 0;
|
|
issprites = dip_for_drawing.nr_sprites;
|
|
ecsshres = bplres == RES_SUPERHIRES && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && !(AMIGA.config.chipset.mask & CSMASK_AGA);
|
|
|
|
plf1pri = dp_for_drawing.bplcon2 & 7;
|
|
plf2pri = (dp_for_drawing.bplcon2 >> 3) & 7;
|
|
plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri);
|
|
plf_sprite_mask |= (0x0000FFFF << (4 * plf1pri)) & 0xFFFF;
|
|
plf_sprite_mask >>>= 0;
|
|
//plf_sprite_mask = get_sprite_mask();
|
|
|
|
bpldualpf = (dp_for_drawing.bplcon0 & 0x400) == 0x400;
|
|
bpldualpfpri = (dp_for_drawing.bplcon2 & 0x40) == 0x40;
|
|
|
|
/*#ifdef AGA
|
|
bpldualpf2of = (dp_for_drawing.bplcon3 >> 10) & 7;
|
|
sbasecol[0] = ((dp_for_drawing.bplcon4 >> 4) & 15) << 4;
|
|
sbasecol[1] = ((dp_for_drawing.bplcon4 >> 0) & 15) << 4;
|
|
brdsprt = !brdblank && (AMIGA.config.chipset.mask & CSMASK_AGA) && (dp_for_drawing.bplcon0 & 1) && (dp_for_drawing.bplcon3 & 0x02);
|
|
bplxor = dp_for_drawing.bplcon4 >> 8;
|
|
#endif*/
|
|
};
|
|
|
|
this.pfield_expand_dp_bplconx = function (regno, v) {
|
|
if (regno == 0xffff) {
|
|
//hposblank = 1; //FIXME
|
|
return;
|
|
}
|
|
regno -= 0x1000;
|
|
switch (regno) {
|
|
case 0x100:
|
|
dp_for_drawing.bplcon0 = v;
|
|
dp_for_drawing.bplres = GET_RES_DENISE(v);
|
|
dp_for_drawing.nr_planes = GET_PLANES(v);
|
|
dp_for_drawing.ham_seen = is_ham(v);
|
|
break;
|
|
case 0x104:
|
|
dp_for_drawing.bplcon2 = v;
|
|
break;
|
|
case 0x106:
|
|
dp_for_drawing.bplcon3 = v;
|
|
break;
|
|
/*#ifdef AGA
|
|
case 0x10c:
|
|
dp_for_drawing.bplcon4 = v;
|
|
break;
|
|
#endif*/
|
|
}
|
|
this.pfield_expand_dp_bplcon();
|
|
res_shift = lores_shift - bplres;
|
|
};
|
|
|
|
this.center_image = function () {
|
|
var prev_x_adjust = visible_left_border;
|
|
var prev_y_adjust = thisframe_y_adjust;
|
|
var tmp;
|
|
|
|
var w = gfxvidinfo.drawbuffer.inwidth;
|
|
if (AMIGA.config.video.xcenter && max_diwstop > 0) {
|
|
if (max_diwstop - min_diwstart < w && AMIGA.config.video.xcenter == 2)
|
|
/* Try to center. */
|
|
visible_left_border = ((max_diwstop - min_diwstart - w) >> 1) + min_diwstart;
|
|
else
|
|
visible_left_border = max_diwstop - w - ((max_diwstop - min_diwstart - w) >> 1);
|
|
visible_left_border &= ~((xshift(1, lores_shift)) - 1);
|
|
|
|
/* Would the old value be good enough? If so, leave it as it is if we want to be clever. */
|
|
if (AMIGA.config.video.xcenter == 2) {
|
|
if (center_reset || (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart && min_diwstart - visible_left_border <= 32))
|
|
visible_left_border = prev_x_adjust;
|
|
}
|
|
} else if (gfxvidinfo.drawbuffer.extrawidth) {
|
|
visible_left_border = max_diwlastword() - w;
|
|
if (gfxvidinfo.drawbuffer.extrawidth > 0)
|
|
visible_left_border += gfxvidinfo.drawbuffer.extrawidth << AMIGA.config.video.hresolution;
|
|
} else {
|
|
if (gfxvidinfo.drawbuffer.inxoffset < 0) {
|
|
visible_left_border = 0;
|
|
} else {
|
|
visible_left_border = gfxvidinfo.drawbuffer.inxoffset - DISPLAY_LEFT_SHIFT;
|
|
}
|
|
}
|
|
|
|
if (visible_left_border > max_diwlastword() - 32)
|
|
visible_left_border = max_diwlastword() - 32;
|
|
if (visible_left_border < 0)
|
|
visible_left_border = 0;
|
|
visible_left_border &= ~((xshift(1, lores_shift)) - 1);
|
|
|
|
linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.drawbuffer.pixbytes;
|
|
|
|
visible_right_border = visible_left_border + w;
|
|
if (visible_right_border > max_diwlastword())
|
|
visible_right_border = max_diwlastword();
|
|
|
|
thisframe_y_adjust = minfirstline;
|
|
if (AMIGA.config.video.ycenter && thisframe_first_drawn_line >= 0) {
|
|
if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && AMIGA.config.video.ycenter == 2)
|
|
thisframe_y_adjust = ((thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) >> 1) + thisframe_first_drawn_line;
|
|
else
|
|
thisframe_y_adjust = thisframe_first_drawn_line + (((thisframe_last_drawn_line - thisframe_first_drawn_line) - max_drawn_amiga_line) >> 1);
|
|
|
|
if (AMIGA.config.video.ycenter == 2) {
|
|
if (center_reset || (thisframe_y_adjust != prev_y_adjust
|
|
&& prev_y_adjust <= thisframe_first_drawn_line
|
|
&& prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line))
|
|
thisframe_y_adjust = prev_y_adjust;
|
|
}
|
|
}
|
|
if (thisframe_y_adjust + max_drawn_amiga_line > this.maxvpos_nom)
|
|
thisframe_y_adjust = this.maxvpos_nom - max_drawn_amiga_line;
|
|
if (thisframe_y_adjust < minfirstline)
|
|
thisframe_y_adjust = minfirstline;
|
|
|
|
thisframe_y_adjust_real = thisframe_y_adjust << linedbl;
|
|
tmp = (this.maxvpos_nom - thisframe_y_adjust + 1) << linedbl;
|
|
if (tmp != max_ypos_thisframe) {
|
|
last_max_ypos = tmp;
|
|
if (last_max_ypos < 0)
|
|
last_max_ypos = 0;
|
|
}
|
|
max_ypos_thisframe = tmp;
|
|
|
|
if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust)
|
|
frame_redraw_necessary |= (interlace_seen > 0 && linedbl) ? 2 : 1;
|
|
|
|
max_diwstop = 0;
|
|
min_diwstart = MAX_STOP;
|
|
|
|
gfxvidinfo.drawbuffer.xoffset = (DISPLAY_LEFT_SHIFT << RES_MAX) + (visible_left_border << (RES_MAX - AMIGA.config.video.hresolution));
|
|
gfxvidinfo.drawbuffer.yoffset = thisframe_y_adjust << VRES_MAX;
|
|
|
|
center_reset = false;
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
const COLOR_MATCH_ACOLORS = 1;
|
|
const COLOR_MATCH_FULL = 2;
|
|
var color_match_type = 0;
|
|
|
|
this.adjust_drawing_colors = function (ctable, need_full) {
|
|
if (FAST_COLORS) {
|
|
if (need_full)
|
|
color_reg_cpy(colors_for_drawing, current_colors);
|
|
else
|
|
color_reg_cpy_acolors(colors_for_drawing, current_colors);
|
|
return;
|
|
}
|
|
if (drawing_color_matches != ctable) {
|
|
if (need_full) {
|
|
color_reg_cpy(colors_for_drawing, curr_color_tables[ctable]);
|
|
color_match_type = COLOR_MATCH_FULL;
|
|
} else {
|
|
//memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, sizeof colors_for_drawing.acolors);
|
|
//for (var i = 0; i < colors_for_drawing.acolors.length; i++) colors_for_drawing.acolors[i] = curr_color_tables[ctable].acolors[i]; colors_for_drawing.borderblank = curr_color_tables[ctable].borderblank;
|
|
color_reg_cpy_acolors(colors_for_drawing, curr_color_tables[ctable]);
|
|
color_match_type = COLOR_MATCH_ACOLORS;
|
|
}
|
|
drawing_color_matches = ctable;
|
|
}
|
|
else if (need_full && color_match_type != COLOR_MATCH_FULL) {
|
|
color_reg_cpy(colors_for_drawing, curr_color_tables[ctable]);
|
|
color_match_type = COLOR_MATCH_FULL;
|
|
}
|
|
};
|
|
|
|
this.do_color_changes = function (worker_border, worker_pfield, vp) {
|
|
var lastpos = visible_left_border;
|
|
var endpos = visible_left_border + gfxvidinfo.drawbuffer.inwidth;
|
|
|
|
for (var i = dip_for_drawing.first_color_change; i <= dip_for_drawing.last_color_change; i++) {
|
|
var regno = curr_color_changes[i].regno;
|
|
var value = curr_color_changes[i].value;
|
|
var nextpos, nextpos_in_range;
|
|
|
|
if (i == dip_for_drawing.last_color_change)
|
|
nextpos = endpos;
|
|
else
|
|
nextpos = coord_hw_to_window_x(curr_color_changes[i].linepos);
|
|
|
|
nextpos_in_range = nextpos;
|
|
if (nextpos > endpos)
|
|
nextpos_in_range = endpos;
|
|
|
|
if (nextpos_in_range > lastpos) {
|
|
if (lastpos < playfield_start) {
|
|
var t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
|
|
worker_border(lastpos, t, false);
|
|
lastpos = t;
|
|
}
|
|
}
|
|
if (nextpos_in_range > lastpos) {
|
|
if (lastpos >= playfield_start && lastpos < playfield_end) {
|
|
var t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
|
|
worker_pfield(lastpos, t, false);
|
|
// blank start and end that shouldn't be visible
|
|
if (lastpos < visible_left_start)
|
|
worker_border(lastpos, visible_left_start, true);
|
|
if (t > visible_right_stop)
|
|
worker_border(visible_right_stop, endpos, true);
|
|
lastpos = t;
|
|
}
|
|
}
|
|
if (nextpos_in_range > lastpos) {
|
|
if (lastpos >= playfield_end)
|
|
worker_border(lastpos, nextpos_in_range, false);
|
|
lastpos = nextpos_in_range;
|
|
}
|
|
|
|
if (regno >= 0x1000)
|
|
this.pfield_expand_dp_bplconx(regno, value);
|
|
else if (regno >= 0) {
|
|
if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK))
|
|
colors_for_drawing.borderblank = (value & 1) != 0;
|
|
else {
|
|
color_reg_set(colors_for_drawing, regno, value);
|
|
colors_for_drawing.acolors[regno] = getxcolor(value);
|
|
}
|
|
}
|
|
if (lastpos >= endpos)
|
|
break;
|
|
}
|
|
if (vp < visible_top_start || vp >= visible_bottom_stop) {
|
|
// outside of visible area
|
|
// Just overwrite with black. Above code needs to run because of custom registers,
|
|
// not worth the trouble for separate code path just for max 10 lines or so
|
|
worker_border(visible_left_border, visible_left_border + gfxvidinfo.drawbuffer.inwidth, true);
|
|
}
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
function getbgc(blank) {
|
|
/*#if 0
|
|
if (blank)
|
|
return xcolors[0x088];
|
|
else if (hposblank == 1)
|
|
return xcolors[0xf00];
|
|
else if (hposblank == 2)
|
|
return xcolors[0x0f0];
|
|
else if (hposblank == 3)
|
|
return xcolors[0x00f];
|
|
else if (brdblank)
|
|
return xcolors[0x880];
|
|
//return colors_for_drawing.acolors[0];
|
|
return xcolors[0xf0f];
|
|
#endif*/
|
|
return (blank || hposblank || colors_for_drawing.borderblank) ? 0 : colors_for_drawing.acolors[0];
|
|
}
|
|
|
|
function fill_line_16(buf, start, stop, blank) {
|
|
console.log('fill_line_16() NI', start, stop, blank);
|
|
/*uae_u16 *b = (uae_u16 *)buf;
|
|
var rem = 0;
|
|
var col = getbgc(blank);
|
|
|
|
if (((long)&b[start]) & 1)
|
|
b[start++] = (uae_u16) col;
|
|
|
|
if (start >= stop)
|
|
return;
|
|
|
|
if (((long)&b[stop]) & 1) {
|
|
rem++;
|
|
stop--;
|
|
}
|
|
for (var i = start; i < stop; i += 2) {
|
|
uae_u32 *b2 = (uae_u32 *)&b[i];
|
|
*b2 = col;
|
|
}
|
|
if (rem)
|
|
b[stop] = (uae_u16)col;*/
|
|
}
|
|
function fill_line_32(buf, start, stop, blank) {
|
|
var col = getbgc(blank);
|
|
for (var i = start; i < stop; i++)
|
|
buf[i] = col;
|
|
}
|
|
|
|
function pfield_do_fill_line2(start, stop, blank) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: fill_line_16(xlinebuffer, start, stop, blank); break;
|
|
case 4: fill_line_32(xlinebuffer, start, stop, blank); break;
|
|
}
|
|
}
|
|
function pfield_do_fill_line(start, stop, blank) {
|
|
//console.log('pfield_do_fill_line()', start, stop, blank);
|
|
//xlinecheck('pfield_do_fill_line', start, stop);
|
|
if (!blank) {
|
|
if (start < visible_left_start) {
|
|
pfield_do_fill_line2(start, visible_left_start, true);
|
|
start = visible_left_start;
|
|
}
|
|
if (stop > visible_right_stop) {
|
|
pfield_do_fill_line2(start, visible_right_stop, false);
|
|
blank = true;
|
|
start = visible_right_stop;
|
|
}
|
|
}
|
|
pfield_do_fill_line2(start, stop, blank);
|
|
}
|
|
|
|
function fill_line2(startpos, len) {
|
|
//console.log('fill_line2', startpos, len);
|
|
/*var shift = 0;
|
|
if (gfxvidinfo.drawbuffer.pixbytes == 2) shift = 1;
|
|
if (gfxvidinfo.drawbuffer.pixbytes == 4) shift = 2;*/
|
|
|
|
var nints = len;// >> (2 - shift);
|
|
var nrem = nints & 7;
|
|
nints &= ~7;
|
|
//int *start = (int *)(((uae_u8*)xlinebuffer) + (startpos << shift));
|
|
var start = startpos;// << shift >> 2;
|
|
var val = getbgc(false);
|
|
|
|
/*for (; nints > 0; nints -= 8, start += 8) {
|
|
*start = val;
|
|
*(start+1) = val;
|
|
*(start+2) = val;
|
|
*(start+3) = val;
|
|
*(start+4) = val;
|
|
*(start+5) = val;
|
|
*(start+6) = val;
|
|
*(start+7) = val;
|
|
}
|
|
switch (nrem) {
|
|
case 7: *start++ = val;
|
|
case 6: *start++ = val;
|
|
case 5: *start++ = val;
|
|
case 4: *start++ = val;
|
|
case 3: *start++ = val;
|
|
case 2: *start++ = val;
|
|
case 1: *start = val;
|
|
}*/
|
|
|
|
for (; nints > 0; nints -= 8, start += 8) {
|
|
xlinebuffer[start ] = val;
|
|
xlinebuffer[start + 1] = val;
|
|
xlinebuffer[start + 2] = val;
|
|
xlinebuffer[start + 3] = val;
|
|
xlinebuffer[start + 4] = val;
|
|
xlinebuffer[start + 5] = val;
|
|
xlinebuffer[start + 6] = val;
|
|
xlinebuffer[start + 7] = val;
|
|
}
|
|
switch (nrem) {
|
|
case 7: xlinebuffer[start++] = val;
|
|
case 6: xlinebuffer[start++] = val;
|
|
case 5: xlinebuffer[start++] = val;
|
|
case 4: xlinebuffer[start++] = val;
|
|
case 3: xlinebuffer[start++] = val;
|
|
case 2: xlinebuffer[start++] = val;
|
|
case 1: xlinebuffer[start] = val;
|
|
}
|
|
}
|
|
function fill_line() {
|
|
var hs = coord_hw_to_window_x(hsyncstartpos * 2);
|
|
if (hs >= gfxvidinfo.drawbuffer.inwidth || hposblank) {
|
|
//hposblank = 3; //FIXME
|
|
fill_line2(visible_left_border, gfxvidinfo.drawbuffer.inwidth);
|
|
} else {
|
|
fill_line2(visible_left_border, hs);
|
|
//hposblank = 2; //FIXME
|
|
fill_line2(visible_left_border + hs, gfxvidinfo.drawbuffer.inwidth);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.pfield_init_linetoscr = function () {
|
|
var ddf_left = dp_for_drawing.plfleft * 2 + DIW_DDF_OFFSET;
|
|
var ddf_right = dp_for_drawing.plfright * 2 + DIW_DDF_OFFSET;
|
|
|
|
native_ddf_left = coord_hw_to_window_x(ddf_left);
|
|
native_ddf_right = coord_hw_to_window_x(ddf_right);
|
|
|
|
linetoscr_diw_start = dp_for_drawing.diwfirstword;
|
|
linetoscr_diw_end = dp_for_drawing.diwlastword;
|
|
|
|
res_shift = lores_shift - bplres;
|
|
|
|
if (dip_for_drawing.nr_sprites == 0) {
|
|
if (linetoscr_diw_start < native_ddf_left)
|
|
linetoscr_diw_start = native_ddf_left;
|
|
if (linetoscr_diw_end > native_ddf_right)
|
|
linetoscr_diw_end = native_ddf_right;
|
|
}
|
|
if (linetoscr_diw_end < linetoscr_diw_start)
|
|
linetoscr_diw_end = linetoscr_diw_start;
|
|
|
|
playfield_start = linetoscr_diw_start;
|
|
playfield_end = linetoscr_diw_end;
|
|
|
|
unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
|
|
ham_src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window(playfield_start - native_ddf_left);
|
|
unpainted = res_shift_from_window(unpainted);
|
|
|
|
if (playfield_start < visible_left_border)
|
|
playfield_start = visible_left_border;
|
|
if (playfield_start > visible_right_border)
|
|
playfield_start = visible_right_border;
|
|
if (playfield_end < visible_left_border)
|
|
playfield_end = visible_left_border;
|
|
if (playfield_end > visible_right_border)
|
|
playfield_end = visible_right_border;
|
|
|
|
real_playfield_end = playfield_end;
|
|
real_playfield_start = playfield_start;
|
|
|
|
/*#ifdef AGA
|
|
if (brdsprt && dip_for_drawing.nr_sprites) {
|
|
var min = visible_right_border, max = visible_left_border, i;
|
|
for (i = 0; i < dip_for_drawing.nr_sprites; i++) {
|
|
var x;
|
|
x = curr_sprite_entries[dip_for_drawing.first_sprite_entry + i].pos;
|
|
if (x < min)
|
|
min = x;
|
|
x = curr_sprite_entries[dip_for_drawing.first_sprite_entry + i].max;
|
|
if (x > max)
|
|
max = x;
|
|
}
|
|
min = coord_hw_to_window_x (min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
|
|
max = coord_hw_to_window_x (max >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
|
|
if (min < playfield_start)
|
|
playfield_start = min;
|
|
if (playfield_start < visible_left_border)
|
|
playfield_start = visible_left_border;
|
|
if (max > playfield_end)
|
|
playfield_end = max;
|
|
if (playfield_end > visible_right_border)
|
|
playfield_end = visible_right_border;
|
|
}
|
|
#endif*/
|
|
|
|
if (sprite_first_x < sprite_last_x) {
|
|
if (sprite_first_x < 0)
|
|
sprite_first_x = 0;
|
|
if (sprite_last_x >= MAX_PIXELS_PER_LINE - 1)
|
|
sprite_last_x = MAX_PIXELS_PER_LINE - 2;
|
|
if (sprite_first_x < sprite_last_x) {
|
|
//memset (spritepixels + sprite_first_x, 0, sizeof (struct SpritePixelsBuf) * (sprite_last_x - sprite_first_x + 1));
|
|
for (var i = sprite_first_x; i <= sprite_last_x; i++) {
|
|
spritepixels[i].clr();
|
|
}
|
|
}
|
|
}
|
|
sprite_last_x = 0;
|
|
sprite_first_x = MAX_PIXELS_PER_LINE - 1;
|
|
|
|
ddf_left -= DISPLAY_LEFT_SHIFT;
|
|
pixels_offset = MAX_PIXELS_PER_LINE - (ddf_left << bplres);
|
|
//ddf_left <<= bplres;
|
|
src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window(playfield_start - native_ddf_left);
|
|
|
|
if (dip_for_drawing.nr_sprites == 0)
|
|
return;
|
|
|
|
/* Must clear parts of apixels. */
|
|
if (linetoscr_diw_start < native_ddf_left) {
|
|
var size = res_shift_from_window(native_ddf_left - linetoscr_diw_start);
|
|
linetoscr_diw_start = native_ddf_left;
|
|
//memset (apixels + MAX_PIXELS_PER_LINE - size, 0, size);
|
|
for (var i = 0; i < size; i++) {
|
|
apixels[MAX_PIXELS_PER_LINE - size + i] = 0;
|
|
}
|
|
}
|
|
if (linetoscr_diw_end > native_ddf_right) {
|
|
var pos = res_shift_from_window(native_ddf_right - native_ddf_left);
|
|
var size = res_shift_from_window(linetoscr_diw_end - native_ddf_right);
|
|
linetoscr_diw_start = native_ddf_left;
|
|
//memset (apixels + MAX_PIXELS_PER_LINE + pos, 0, size);
|
|
for (var i = 0; i < size; i++) {
|
|
apixels[MAX_PIXELS_PER_LINE + pos + i] = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
function dummy_worker(start, stop, blank) { }
|
|
|
|
|
|
function linetoscr_32(spix, dpix, stoppos) {
|
|
//uae_u32 *buf = (uae_u32 *) xlinebuffer;
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
|
|
return spix;
|
|
}
|
|
|
|
function linetoscr_32_stretch1(spix, dpix, stoppos) {
|
|
//uae_u32 *buf = (uae_u32 *) xlinebuffer;
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
return spix;
|
|
}
|
|
|
|
function linetoscr_32_shrink1(spix, dpix, stoppos) {
|
|
//uae_u32 *buf = (uae_u32 *) xlinebuffer;
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
return spix;
|
|
}
|
|
|
|
|
|
function linetoscr_32_spr(spix, dpix, stoppos) {
|
|
//uae_u32 *buf = (uae_u32 *) xlinebuffer;
|
|
var sprcol;
|
|
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
sprpix_val = dpix_val;
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 1, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
|
|
return spix;
|
|
}
|
|
|
|
function linetoscr_32_stretch1_spr(spix, dpix, stoppos) {
|
|
//uae_u32 *buf = (uae_u32 *) xlinebuffer;
|
|
var sprcol;
|
|
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
sprpix_val = dpix_val;
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 1, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix++;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
return spix;
|
|
}
|
|
|
|
function linetoscr_32_shrink1_spr(spix, dpix, stoppos) {
|
|
//var *buf = (var *) xlinebuffer;
|
|
var sprcol;
|
|
|
|
if (dp_for_drawing.ham_seen) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
dpix_val = xcolors[ham_linebuf[spix]];
|
|
sprpix_val = dpix_val;
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bpldualpf) {
|
|
var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[lookup[spix_val]];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 1, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else if (bplehb) {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
if (spix_val <= 31)
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
else
|
|
dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
} else {
|
|
while (dpix < stoppos) {
|
|
var sprpix_val;
|
|
var spix_val;
|
|
var dpix_val;
|
|
var out_val;
|
|
|
|
spix_val = apixels[spix];
|
|
sprpix_val = spix_val;
|
|
dpix_val = colors_for_drawing.acolors[spix_val];
|
|
spix += 2;
|
|
out_val = dpix_val;
|
|
if (spritepixels[dpix].data) {
|
|
sprcol = render_sprites (dpix, 0, sprpix_val, 0);
|
|
if (sprcol) {
|
|
out_val = colors_for_drawing.acolors[sprcol];
|
|
}
|
|
}
|
|
xlinebuffer[dpix++] = out_val;
|
|
}
|
|
}
|
|
|
|
return spix;
|
|
}
|
|
|
|
|
|
//apixels -> xlinebuffer
|
|
function pfield_do_linetoscr(start, stop, blank) {
|
|
//console.log('pfield_do_linetoscr()', start, stop, stop - start);
|
|
//xlinecheck('pfield_do_linetoscr', start, stop);
|
|
|
|
/*#ifdef AGA
|
|
if (issprites && (AMIGA.config.chipset.mask & CSMASK_AGA)) {
|
|
if (res_shift == 0) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 2) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch2_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch2_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch1_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch1_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == -1) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1f_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1f_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
} else if (res_shift == -2) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2f_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2f_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2_aga_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2_aga_spr (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
}
|
|
} else if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
if (res_shift == 0) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 2) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch2_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch2_aga (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == -1) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1f_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1f_aga (src_pixel, start, stop); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
} else if (res_shift == -2) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2f_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2f_aga (src_pixel, start, stop); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2_aga (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2_aga (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
#endif*/
|
|
|
|
/*#ifdef ECS_DENISE
|
|
if (ecsshres) {
|
|
if (res_shift == 0) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_sh (src_pixel, start, stop, issprites); break;
|
|
case 4: src_pixel = linetoscr_32_sh (src_pixel, start, stop, issprites); break;
|
|
}
|
|
} else if (res_shift == -1) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1f_sh (src_pixel, start, stop, issprites); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1f_sh (src_pixel, start, stop, issprites); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1_sh (src_pixel, start, stop, issprites); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1_sh (src_pixel, start, stop, issprites); break;
|
|
}
|
|
}
|
|
} else if (res_shift == -2) {
|
|
if (currprefs.gfx_lores_mode) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2f_sh (src_pixel, start, stop, issprites); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2f_sh (src_pixel, start, stop, issprites); break;
|
|
}
|
|
} else {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink2_sh (src_pixel, start, stop, issprites); break;
|
|
case 4: src_pixel = linetoscr_32_shrink2_sh (src_pixel, start, stop, issprites); break;
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
#endif*/
|
|
|
|
if (issprites) {
|
|
if (res_shift == 0) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 2) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch2_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch2_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch1_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch1_spr (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == -1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1_spr (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1_spr (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
} else {
|
|
if (res_shift == 0) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 2) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch2 (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch2 (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == 1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break;
|
|
}
|
|
} else if (res_shift == -1) {
|
|
switch (gfxvidinfo.drawbuffer.pixbytes) {
|
|
case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break;
|
|
case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function init_ham_decoding() {
|
|
var unpainted_amiga = unpainted;
|
|
|
|
ham_decode_pixel = ham_src_pixel;
|
|
ham_lastcolor = color_reg_get(colors_for_drawing, 0);
|
|
|
|
if (!bplham) {
|
|
if (unpainted_amiga > 0) {
|
|
var pv = apixels[ham_decode_pixel + unpainted_amiga - 1];
|
|
/*#ifdef AGA
|
|
if (currprefs.chipset_mask & CSMASK_AGA)
|
|
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
|
|
else
|
|
#endif*/
|
|
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
|
|
}
|
|
/*#ifdef AGA
|
|
} else if (currprefs.chipset_mask & CSMASK_AGA) {
|
|
if (bplplanecnt >= 7) { // AGA mode HAM8
|
|
while (unpainted_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel++] ^ bplxor;
|
|
switch (pv & 0x3) {
|
|
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
|
|
case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
|
|
case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
|
|
case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
|
|
}
|
|
}
|
|
} else { // AGA mode HAM6
|
|
while (unpainted_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel++] ^ bplxor;
|
|
switch (pv & 0x30) {
|
|
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
|
|
case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
|
|
case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
|
|
case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
|
|
}
|
|
}
|
|
}
|
|
#endif*/
|
|
} else {
|
|
/* OCS/ECS mode HAM6 */
|
|
while (unpainted_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel++];
|
|
switch (pv & 0x30) {
|
|
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
|
|
case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
|
|
case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
|
|
case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function decode_ham(pix, stoppos, blank) {
|
|
var todraw_amiga = res_shift_from_window(stoppos - pix);
|
|
|
|
if (!bplham) {
|
|
while (todraw_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel];
|
|
/*#ifdef AGA
|
|
if (currprefs.chipset_mask & CSMASK_AGA)
|
|
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
|
|
else
|
|
#endif*/
|
|
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
|
|
|
|
ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
|
|
}
|
|
/*#ifdef AGA
|
|
} else if (currprefs.chipset_mask & CSMASK_AGA) {
|
|
if (bplplanecnt >= 7) { // AGA mode HAM8
|
|
while (todraw_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel] ^ bplxor;
|
|
switch (pv & 0x3) {
|
|
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
|
|
case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
|
|
case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
|
|
case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
|
|
}
|
|
ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
|
|
}
|
|
} else { // AGA mode HAM6
|
|
while (todraw_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel] ^ bplxor;
|
|
switch (pv & 0x30) {
|
|
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
|
|
case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
|
|
case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
|
|
case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
|
|
}
|
|
ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
|
|
}
|
|
}
|
|
#endif*/
|
|
} else {
|
|
/* OCS/ECS mode HAM6 */
|
|
while (todraw_amiga-- > 0) {
|
|
var pv = apixels[ham_decode_pixel];
|
|
switch (pv & 0x30) {
|
|
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
|
|
case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
|
|
case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
|
|
case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
|
|
}
|
|
ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
|
|
}
|
|
}
|
|
}
|
|
|
|
function weird_bitplane_fix() {
|
|
for (var i = playfield_start >> lores_shift; i < playfield_end >> lores_shift; i++) {
|
|
if (apixels[pixels_offset + i] > 16) apixels[pixels_offset + i] = 16;
|
|
}
|
|
}
|
|
|
|
//line_data -> apixels
|
|
this.pfield_doline_1 = function (lineno, wordcount, planes) {
|
|
var pixels = MAX_PIXELS_PER_LINE;
|
|
var tmp, d0, d1, d2, d3, d4, d5, d6, d7;
|
|
var offs = 0;
|
|
|
|
while (wordcount-- > 0) {
|
|
d0 = d1 = d2 = d3 = d4 = d5 = d6 = d7 = 0;
|
|
|
|
switch (planes) {
|
|
/*#ifdef AGA
|
|
case 8: d0 = line_data[lineno][7][offs];
|
|
case 7: d1 = line_data[lineno][6][offs];
|
|
#endif*/
|
|
case 6:
|
|
d2 = line_data[lineno][5][offs];
|
|
case 5:
|
|
d3 = line_data[lineno][4][offs];
|
|
case 4:
|
|
d4 = line_data[lineno][3][offs];
|
|
case 3:
|
|
d5 = line_data[lineno][2][offs];
|
|
case 2:
|
|
d6 = line_data[lineno][1][offs];
|
|
case 1:
|
|
d7 = line_data[lineno][0][offs];
|
|
}
|
|
offs++;
|
|
|
|
tmp = (d0 ^ (d1 >>> 1)) & 0x55555555;
|
|
d0 ^= tmp;
|
|
d1 ^= (tmp << 1);
|
|
tmp = (d2 ^ (d3 >>> 1)) & 0x55555555;
|
|
d2 ^= tmp;
|
|
d3 ^= (tmp << 1);
|
|
tmp = (d4 ^ (d5 >>> 1)) & 0x55555555;
|
|
d4 ^= tmp;
|
|
d5 ^= (tmp << 1);
|
|
tmp = (d6 ^ (d7 >>> 1)) & 0x55555555;
|
|
d6 ^= tmp;
|
|
d7 ^= (tmp << 1);
|
|
|
|
tmp = (d0 ^ (d2 >>> 2)) & 0x33333333;
|
|
d0 ^= tmp;
|
|
d2 ^= (tmp << 2);
|
|
tmp = (d1 ^ (d3 >>> 2)) & 0x33333333;
|
|
d1 ^= tmp;
|
|
d3 ^= (tmp << 2);
|
|
tmp = (d4 ^ (d6 >>> 2)) & 0x33333333;
|
|
d4 ^= tmp;
|
|
d6 ^= (tmp << 2);
|
|
tmp = (d5 ^ (d7 >>> 2)) & 0x33333333;
|
|
d5 ^= tmp;
|
|
d7 ^= (tmp << 2);
|
|
|
|
tmp = (d0 ^ (d4 >>> 4)) & 0x0f0f0f0f;
|
|
d0 ^= tmp;
|
|
d4 ^= (tmp << 4);
|
|
tmp = (d1 ^ (d5 >>> 4)) & 0x0f0f0f0f;
|
|
d1 ^= tmp;
|
|
d5 ^= (tmp << 4);
|
|
tmp = (d2 ^ (d6 >>> 4)) & 0x0f0f0f0f;
|
|
d2 ^= tmp;
|
|
d6 ^= (tmp << 4);
|
|
tmp = (d3 ^ (d7 >>> 4)) & 0x0f0f0f0f;
|
|
d3 ^= tmp;
|
|
d7 ^= (tmp << 4);
|
|
|
|
tmp = (d0 ^ (d1 >>> 8)) & 0x00ff00ff;
|
|
d0 ^= tmp;
|
|
d1 ^= (tmp << 8);
|
|
tmp = (d2 ^ (d3 >>> 8)) & 0x00ff00ff;
|
|
d2 ^= tmp;
|
|
d3 ^= (tmp << 8);
|
|
tmp = (d4 ^ (d5 >>> 8)) & 0x00ff00ff;
|
|
d4 ^= tmp;
|
|
d5 ^= (tmp << 8);
|
|
tmp = (d6 ^ (d7 >>> 8)) & 0x00ff00ff;
|
|
d6 ^= tmp;
|
|
d7 ^= (tmp << 8);
|
|
|
|
tmp = (d0 ^ (d2 >>> 16)) & 0x0000ffff;
|
|
d0 ^= tmp;
|
|
d2 ^= (tmp << 16);
|
|
tmp = (d1 ^ (d3 >>> 16)) & 0x0000ffff;
|
|
d1 ^= tmp;
|
|
d3 ^= (tmp << 16);
|
|
tmp = (d4 ^ (d6 >>> 16)) & 0x0000ffff;
|
|
d4 ^= tmp;
|
|
d6 ^= (tmp << 16);
|
|
tmp = (d5 ^ (d7 >>> 16)) & 0x0000ffff;
|
|
d5 ^= tmp;
|
|
d7 ^= (tmp << 16);
|
|
|
|
apixels[pixels ] = (d0 >>> 24) & 0xff;
|
|
apixels[pixels + 1] = (d0 >>> 16) & 0xff;
|
|
apixels[pixels + 2] = (d0 >>> 8) & 0xff;
|
|
apixels[pixels + 3] = d0 & 0xff;
|
|
apixels[pixels + 4] = (d4 >>> 24) & 0xff;
|
|
apixels[pixels + 5] = (d4 >>> 16) & 0xff;
|
|
apixels[pixels + 6] = (d4 >>> 8) & 0xff;
|
|
apixels[pixels + 7] = d4 & 0xff;
|
|
apixels[pixels + 8] = (d1 >>> 24) & 0xff;
|
|
apixels[pixels + 9] = (d1 >>> 16) & 0xff;
|
|
apixels[pixels + 10] = (d1 >>> 8) & 0xff;
|
|
apixels[pixels + 11] = d1 & 0xff;
|
|
apixels[pixels + 12] = (d5 >>> 24) & 0xff;
|
|
apixels[pixels + 13] = (d5 >>> 16) & 0xff;
|
|
apixels[pixels + 14] = (d5 >>> 8) & 0xff;
|
|
apixels[pixels + 15] = d5 & 0xff;
|
|
apixels[pixels + 16] = (d2 >>> 24) & 0xff;
|
|
apixels[pixels + 17] = (d2 >>> 16) & 0xff;
|
|
apixels[pixels + 18] = (d2 >>> 8) & 0xff;
|
|
apixels[pixels + 19] = d2 & 0xff;
|
|
apixels[pixels + 20] = (d6 >>> 24) & 0xff;
|
|
apixels[pixels + 21] = (d6 >>> 16) & 0xff;
|
|
apixels[pixels + 22] = (d6 >>> 8) & 0xff;
|
|
apixels[pixels + 23] = d6 & 0xff;
|
|
apixels[pixels + 24] = (d3 >>> 24) & 0xff;
|
|
apixels[pixels + 25] = (d3 >>> 16) & 0xff;
|
|
apixels[pixels + 26] = (d3 >>> 8) & 0xff;
|
|
apixels[pixels + 27] = d3 & 0xff;
|
|
apixels[pixels + 28] = (d7 >>> 24) & 0xff;
|
|
apixels[pixels + 29] = (d7 >>> 16) & 0xff;
|
|
apixels[pixels + 30] = (d7 >>> 8) & 0xff;
|
|
apixels[pixels + 31] = d7 & 0xff;
|
|
pixels += 32;
|
|
|
|
/*apixels[pixels++] = (d0 >>> 24);
|
|
apixels[pixels++] = (d0 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d0 >>> 8) & 0xff;
|
|
apixels[pixels++] = d0 & 0xff;
|
|
apixels[pixels++] = (d4 >>> 24);
|
|
apixels[pixels++] = (d4 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d4 >>> 8) & 0xff;
|
|
apixels[pixels++] = d4 & 0xff;
|
|
apixels[pixels++] = (d1 >>> 24);
|
|
apixels[pixels++] = (d1 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d1 >>> 8) & 0xff;
|
|
apixels[pixels++] = d1 & 0xff;
|
|
apixels[pixels++] = (d5 >>> 24);
|
|
apixels[pixels++] = (d5 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d5 >>> 8) & 0xff;
|
|
apixels[pixels++] = d5 & 0xff;
|
|
apixels[pixels++] = (d2 >>> 24);
|
|
apixels[pixels++] = (d2 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d2 >>> 8) & 0xff;
|
|
apixels[pixels++] = d2 & 0xff;
|
|
apixels[pixels++] = (d6 >>> 24);
|
|
apixels[pixels++] = (d6 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d6 >>> 8) & 0xff;
|
|
apixels[pixels++] = d6 & 0xff;
|
|
apixels[pixels++] = (d3 >>> 24);
|
|
apixels[pixels++] = (d3 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d3 >>> 8) & 0xff;
|
|
apixels[pixels++] = d3 & 0xff;
|
|
apixels[pixels++] = (d7 >>> 24);
|
|
apixels[pixels++] = (d7 >>> 16) & 0xff;
|
|
apixels[pixels++] = (d7 >>> 8) & 0xff;
|
|
apixels[pixels++] = d7 & 0xff;*/
|
|
}
|
|
};
|
|
|
|
this.pfield_doline = function (lineno) {
|
|
if (bplplanecnt)
|
|
this.pfield_doline_1(lineno, dp_for_drawing.plflinelen, bplplanecnt);
|
|
else {
|
|
for (var i = 0; i < dp_for_drawing.plflinelen * 32; i++) apixels[i] = 0; //memset (data, 0, dp_for_drawing.plflinelen * 32);
|
|
}
|
|
};
|
|
|
|
this.pfield_draw_line = function (vb, lineno, gfx_ypos, follow_ypos) {
|
|
if (!AMIGA.config.video.enabled) return;
|
|
//console.log('pfield_draw_line', lineno, gfx_ypos, follow_ypos);
|
|
var border = 0;
|
|
var do_double = 0;
|
|
|
|
dp_for_drawing = line_decisions[lineno];
|
|
dip_for_drawing = curr_drawinfo[lineno];
|
|
|
|
switch (linestate[lineno]) {
|
|
case LINE_REMEMBERED_AS_PREVIOUS:
|
|
BUG.info('pfield_draw_line() Shouldn\'t get here... this is a bug.');
|
|
return;
|
|
case LINE_BLACK:
|
|
linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
|
|
border = 2;
|
|
break;
|
|
case LINE_REMEMBERED_AS_BLACK:
|
|
return;
|
|
case LINE_AS_PREVIOUS:
|
|
//dp_for_drawing--;
|
|
//dip_for_drawing--;
|
|
dp_for_drawing = line_decisions[lineno - 1];
|
|
dip_for_drawing = curr_drawinfo[lineno - 1];
|
|
linestate[lineno] = LINE_DONE_AS_PREVIOUS;
|
|
if (dp_for_drawing.plfleft < 0)
|
|
border = 1;
|
|
break;
|
|
case LINE_DONE_AS_PREVIOUS:
|
|
/* fall through */
|
|
case LINE_DONE:
|
|
return;
|
|
case LINE_DECIDED_DOUBLE:
|
|
if (follow_ypos >= 0) {
|
|
do_double = 1;
|
|
linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
|
|
}
|
|
/* fall through */
|
|
default:
|
|
if (dp_for_drawing.plfleft < 0)
|
|
border = 1;
|
|
linestate[lineno] = LINE_DONE;
|
|
break;
|
|
}
|
|
|
|
if (border == 0) {
|
|
this.pfield_expand_dp_bplcon();
|
|
this.pfield_init_linetoscr();
|
|
this.pfield_doline(lineno);
|
|
|
|
this.adjust_drawing_colors(dp_for_drawing.ctable, dp_for_drawing.ham_seen || bplehb || ecsshres);
|
|
|
|
if (dp_for_drawing.ham_seen) {
|
|
init_ham_decoding();
|
|
if (dip_for_drawing.nr_color_changes == 0)
|
|
decode_ham(visible_left_border, visible_right_border, false);
|
|
else {
|
|
this.do_color_changes(dummy_worker, decode_ham, lineno);
|
|
this.adjust_drawing_colors(dp_for_drawing.ctable, dp_for_drawing.ham_seen || bplehb);
|
|
}
|
|
bplham = dp_for_drawing.ham_at_start;
|
|
}
|
|
if (plf2pri > 5 && bplplanecnt == 5 && !(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
weird_bitplane_fix();
|
|
|
|
if (dip_for_drawing.nr_sprites) {
|
|
/*#ifdef AGA
|
|
if (brdsprt)
|
|
this.clear_bitplane_border_aga();
|
|
#endif*/
|
|
for (var i = 0; i < dip_for_drawing.nr_sprites; i++)
|
|
draw_sprites(curr_sprite_entries[dip_for_drawing.first_sprite_entry + i]);
|
|
}
|
|
this.do_color_changes(pfield_do_fill_line, pfield_do_linetoscr, lineno);
|
|
|
|
this.do_flush_line(vb, gfx_ypos);
|
|
if (do_double)
|
|
this.do_flush_line(vb, follow_ypos);
|
|
} else if (border == 1) {
|
|
var dosprites = 0;
|
|
|
|
this.adjust_drawing_colors(dp_for_drawing.ctable, false);
|
|
|
|
/*#ifdef AGA
|
|
if (brdsprt && dip_for_drawing->nr_sprites > 0) {
|
|
dosprites = 1;
|
|
this.pfield_expand_dp_bplcon();
|
|
pfield_init_linetoscr ();
|
|
memset (apixels + MAX_PIXELS_PER_LINE, colors_for_drawing.borderblank ? 0 : colors_for_drawing.acolors[0], MAX_PIXELS_PER_LINE);
|
|
}
|
|
#endif*/
|
|
if (!dosprites && dip_for_drawing.nr_color_changes == 0) {
|
|
fill_line();
|
|
this.do_flush_line(vb, gfx_ypos);
|
|
if (do_double)
|
|
this.do_flush_line(vb, follow_ypos);
|
|
return;
|
|
}
|
|
if (dosprites) {
|
|
for (var i = 0; i < dip_for_drawing.nr_sprites; i++)
|
|
this.draw_sprites(curr_sprite_entries[dip_for_drawing.first_sprite_entry + i]);
|
|
for (var i = 0; i < apixels.length; i++) apixels[i] = 0; //memset (apixels, 0, sizeof apixels);
|
|
//var oxor = bplxor;
|
|
//bplxor = 0;
|
|
this.do_color_changes(pfield_do_fill_line, pfield_do_linetoscr, lineno);
|
|
//bplxor = oxor;
|
|
} else {
|
|
playfield_start = visible_right_border;
|
|
playfield_end = visible_right_border;
|
|
this.do_color_changes(pfield_do_fill_line, pfield_do_fill_line, lineno);
|
|
}
|
|
this.do_flush_line(vb, gfx_ypos);
|
|
if (do_double)
|
|
this.do_flush_line(vb, follow_ypos);
|
|
} else {
|
|
//var tmp = hposblank;
|
|
//hposblank = brdblank;
|
|
//hposblank = colors_for_drawing.borderblank;
|
|
fill_line();
|
|
this.do_flush_line(vb, gfx_ypos);
|
|
//hposblank = tmp;
|
|
}
|
|
};
|
|
|
|
this.init_drawing_frame = function () {
|
|
this.init_hardware_for_drawing_frame();
|
|
|
|
/*if (thisframe_first_drawn_line < 0)
|
|
thisframe_first_drawn_line = minfirstline;
|
|
if (thisframe_first_drawn_line > thisframe_last_drawn_line)
|
|
thisframe_last_drawn_line = thisframe_first_drawn_line;*/
|
|
|
|
var maxline = ((this.maxvpos_nom + 1) << linedbl) + 2;
|
|
|
|
if (SMART_UPDATE) {
|
|
for (var i = 0; i < maxline; i++) {
|
|
switch (linestate[i]) {
|
|
case LINE_DONE_AS_PREVIOUS:
|
|
linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
|
|
break;
|
|
case LINE_REMEMBERED_AS_BLACK:
|
|
break;
|
|
default:
|
|
linestate[i] = LINE_UNDECIDED;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < maxline; i++) linestate[i] = LINE_UNDECIDED; //memset(linestate, LINE_UNDECIDED, maxline);
|
|
}
|
|
|
|
last_drawn_line = 0;
|
|
first_drawn_line = 0x7fff;
|
|
|
|
first_block_line = last_block_line = NO_BLOCK;
|
|
if (frame_redraw_necessary)
|
|
frame_redraw_necessary--;
|
|
|
|
this.center_image();
|
|
|
|
thisframe_first_drawn_line = -1;
|
|
thisframe_last_drawn_line = -1;
|
|
|
|
drawing_color_matches = -1;
|
|
};
|
|
|
|
this.finish_drawing_frame = function () {
|
|
var vb = gfxvidinfo.drawbuffer;
|
|
|
|
if (SMART_UPDATE) {
|
|
for (var i = 0; i < max_ypos_thisframe; i++) {
|
|
var i1 = i + min_ypos_for_screen;
|
|
var line = i + thisframe_y_adjust_real;
|
|
|
|
var where2 = amiga2aspect_line_map[i1];
|
|
if (where2 >= vb.inheight)
|
|
break;
|
|
if (where2 < 0)
|
|
continue;
|
|
hposblank = 0;
|
|
this.pfield_draw_line(vb, line, where2, amiga2aspect_line_map[i1 + 1]);
|
|
}
|
|
//if (lightpen_active) lightpen_update(vb);
|
|
|
|
//this.do_flush_screen(vb, first_drawn_line, last_drawn_line);
|
|
}
|
|
/*else {
|
|
if (!interlace_seen)
|
|
this.do_flush_screen(vb, first_drawn_line, last_drawn_line);
|
|
}*/
|
|
};
|
|
|
|
this.hardware_line_completed = function (lineno) {
|
|
if (!SMART_UPDATE) {
|
|
var i = lineno - thisframe_y_adjust_real;
|
|
if (i >= 0 && i < max_ypos_thisframe) {
|
|
var where = amiga2aspect_line_map[i + min_ypos_for_screen];
|
|
if (where < gfxvidinfo.drawbuffer.outheight && where >= 0)
|
|
this.pfield_draw_line(null, lineno, where, amiga2aspect_line_map[i + min_ypos_for_screen + 1]);
|
|
}
|
|
}
|
|
};
|
|
|
|
this.notice_interlace_seen = function (lace) {
|
|
var changed = false;
|
|
if (lace) {
|
|
if (interlace_seen == 0) {
|
|
changed = true;
|
|
//BUG.info('->lace');
|
|
}
|
|
interlace_seen = AMIGA.config.video.vresolution ? 1 : -1;
|
|
} else {
|
|
if (interlace_seen) {
|
|
changed = true;
|
|
//BUG.info('->non-lace');
|
|
}
|
|
interlace_seen = 0;
|
|
}
|
|
return changed;
|
|
};
|
|
|
|
this.notice_screen_contents_lost = function () {
|
|
frame_redraw_necessary = 2;
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.reset_lores = function () {
|
|
lores_shift = AMIGA.config.video.hresolution;
|
|
if (doublescan > 0) {
|
|
if (lores_shift < 2)
|
|
lores_shift++;
|
|
}
|
|
sprite_buffer_res = AMIGA.config.video.hresolution;
|
|
if (doublescan > 0 && sprite_buffer_res < RES_SUPERHIRES)
|
|
sprite_buffer_res++;
|
|
};
|
|
|
|
this.bpldmainitdelay = function (hpos) {
|
|
var hposa = hpos + (4 + (bplcon0_planes == 8 ? 1 : 0)); //BPLCON_AGNUS_DELAY;
|
|
ddf_change = this.vpos;
|
|
if (hposa < 0x14) {
|
|
this.BPLCON0_Denise(hpos, bplcon0, false);
|
|
this.setup_fmodes(hpos);
|
|
return;
|
|
}
|
|
if (bpldmasetuphpos < 0) {
|
|
bpldmasetupphase = 0;
|
|
bpldmasetuphpos = hpos + BPLCON_DENISE_DELAY;
|
|
}
|
|
};
|
|
|
|
this.update_ddf_change = function () {
|
|
ddf_change = this.vpos;
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.allocsoftbuffer = function (buf, flags, width, height, depth) {
|
|
buf.rowbytes = MAX_PIXELS_PER_LINE >> 3;
|
|
/* for xlinecheck() */
|
|
buf.pixbytes = Math.floor((depth + 7) / 8);
|
|
buf.width_allocated = (width + 7) & ~7;
|
|
buf.height_allocated = height;
|
|
};
|
|
|
|
this.setup_drawing = function () {
|
|
setup_drawing_tables();
|
|
this.allocsoftbuffer(gfxvidinfo.drawbuffer, 0, VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_DEPTH);
|
|
};
|
|
|
|
this.cleanup_drawing = function () {
|
|
};
|
|
|
|
this.reset_drawing = function () {
|
|
var i;
|
|
max_diwstop = 0;
|
|
this.reset_lores();
|
|
for (i = 0; i < linestate.length; i++) linestate[i] = LINE_UNDECIDED;
|
|
this.recreate_aspect_maps();
|
|
last_redraw_point = 0;
|
|
for (i = 0; i < spixels.length; i++) spixels[i] = 0; //memset(spixels, 0, sizeof spixels);
|
|
for (i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset(&spixstate, 0, sizeof spixstate);
|
|
this.init_drawing_frame();
|
|
this.notice_screen_contents_lost();
|
|
//lightpen_y1 = lightpen_y2 = -1;
|
|
center_reset = true;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* sprites */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
function setup_sprite_tables() {
|
|
for (var i = 0; i < 256; i++) {
|
|
sprtaba[i] =
|
|
(((i >> 7) & 1) << 0)
|
|
| (((i >> 6) & 1) << 2)
|
|
| (((i >> 5) & 1) << 4)
|
|
| (((i >> 4) & 1) << 6)
|
|
| (((i >> 3) & 1) << 8)
|
|
| (((i >> 2) & 1) << 10)
|
|
| (((i >> 1) & 1) << 12)
|
|
| (((i >> 0) & 1) << 14);
|
|
sprtabb[i] = sprtaba[i] << 1;
|
|
sprite_ab_merge[i] = ((i & 15) ? 1 : 0) | ((i & 240) ? 2 : 0);
|
|
clxtab[i] =
|
|
((((i & 3) && (i & 12)) << 9) |
|
|
(((i & 3) && (i & 48)) << 10) |
|
|
(((i & 3) && (i & 192)) << 11) |
|
|
(((i & 12) && (i & 48)) << 12) |
|
|
(((i & 12) && (i & 192)) << 13) |
|
|
(((i & 48) && (i & 192)) << 14));
|
|
sprite_offs[i] = (i & 15) ? 0 : 2;
|
|
}
|
|
for (var i = 0; i < 16; i++) {
|
|
clxmask[i] =
|
|
((i & 1) ? 0xF : 0x3)
|
|
| ((i & 2) ? 0xF0 : 0x30)
|
|
| ((i & 4) ? 0xF00 : 0x300)
|
|
| ((i & 8) ? 0xF000 : 0x3000);
|
|
sprclx[i] =
|
|
(((i & 0x3) == 0x3 ? 1 : 0)
|
|
| ((i & 0x5) == 0x5 ? 2 : 0)
|
|
| ((i & 0x9) == 0x9 ? 4 : 0)
|
|
| ((i & 0x6) == 0x6 ? 8 : 0)
|
|
| ((i & 0xA) == 0xA ? 16 : 0)
|
|
| ((i & 0xC) == 0xC ? 32 : 0)) << 9;
|
|
}
|
|
}
|
|
|
|
function render_sprites(pos, dualpf, apixel, aga) {
|
|
if (!DO_SPRITES) return 0; //FIXME
|
|
var spb = spritepixels[pos];
|
|
var v = spb.data;
|
|
var shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
|
|
var maskshift = shift_lookup[apixel];
|
|
var plfmask = (plf_sprite_mask >>> maskshift) >>> maskshift;
|
|
|
|
v &= ~plfmask;
|
|
if (v != 0) { //|| SPRITE_DEBUG) {
|
|
var vlo, vhi, col;
|
|
var v1 = v & 255;
|
|
var offs;
|
|
if (v1 == 0)
|
|
offs = 4 + sprite_offs[v >> 8];
|
|
else
|
|
offs = sprite_offs[v1];
|
|
|
|
v >>= offs * 2;
|
|
v &= 15;
|
|
/*#if SPRITE_DEBUG > 0
|
|
v ^= 8;
|
|
#endif*/
|
|
if (spb.attach && (spb.stdata & (3 << offs))) {
|
|
col = v;
|
|
if (aga)
|
|
col += sbasecol[1];
|
|
else
|
|
col += 16;
|
|
} else {
|
|
vlo = v & 3;
|
|
vhi = (v & (vlo - 1)) >> 2;
|
|
col = (vlo | vhi);
|
|
if (aga) {
|
|
if (vhi > 0)
|
|
col += sbasecol[1];
|
|
else
|
|
col += sbasecol[0];
|
|
} else {
|
|
col += 16;
|
|
}
|
|
col += offs * 2;
|
|
}
|
|
return col;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function draw_sprites_1(e, dualpf, has_attach) {
|
|
//uae_u16 *buf = spixels + e.first_pixel;
|
|
//uae_u8 *stbuf = spixstate.bytes + e.first_pixel;
|
|
//buf -= e.pos;
|
|
//stbuf -= e.pos;
|
|
var pos2 = e.first_pixel - e.pos;
|
|
|
|
var spr_pos = e.pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res);
|
|
|
|
if (spr_pos < sprite_first_x)
|
|
sprite_first_x = spr_pos;
|
|
|
|
for (var pos = e.pos; pos < e.max; pos++, spr_pos++) {
|
|
if (spr_pos >= 0 && spr_pos < MAX_PIXELS_PER_LINE) {
|
|
//spritepixels[spr_pos].data = buf[pos];
|
|
//spritepixels[spr_pos].stdata = stbuf[pos];
|
|
spritepixels[spr_pos].data = spixels[pos2 + pos];
|
|
spritepixels[spr_pos].stdata = spixstate[pos2 + pos];
|
|
spritepixels[spr_pos].attach = has_attach;
|
|
}
|
|
}
|
|
if (spr_pos > sprite_last_x)
|
|
sprite_last_x = spr_pos;
|
|
}
|
|
|
|
function draw_sprites(e) {
|
|
if (!DO_SPRITES) return; //FIXME
|
|
draw_sprites_1(e, bpldualpf, e.has_attached);
|
|
}
|
|
|
|
function ecsshres_func() {
|
|
return bplcon0_res == RES_SUPERHIRES && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && !(AMIGA.config.chipset.mask & CSMASK_AGA);
|
|
}
|
|
|
|
/* handle very rarely needed playfield collision (CLXDAT bit 0) only known game needing this is Rotor */
|
|
this.do_playfield_collisions = function () {
|
|
var ddf_left = thisline_decision.plfleft * 2 << bplcon0_res;
|
|
var hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword);
|
|
var hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword);
|
|
var i, collided, minpos, maxpos;
|
|
/*#ifdef AGA
|
|
var planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6;
|
|
#else*/
|
|
var planes = 6;
|
|
//#endif
|
|
|
|
if (clxcon_bpl_enable == 0) {
|
|
clxdat |= 1;
|
|
return;
|
|
}
|
|
if (clxdat & 1)
|
|
return;
|
|
|
|
collided = 0;
|
|
minpos = thisline_decision.plfleft * 2;
|
|
if (minpos < hw_diwfirst)
|
|
minpos = hw_diwfirst;
|
|
maxpos = thisline_decision.plfright * 2;
|
|
if (maxpos > hw_diwlast)
|
|
maxpos = hw_diwlast;
|
|
for (i = minpos; i < maxpos && !collided; i += 32) {
|
|
var offs = ((i << bplcon0_res) - ddf_left) >> 3;
|
|
var j;
|
|
var total = 0xffffffff;
|
|
for (j = 0; j < planes; j++) {
|
|
var ena = (clxcon_bpl_enable >> j) & 1;
|
|
var match = (clxcon_bpl_match >> j) & 1;
|
|
var t = 0xffffffff;
|
|
if (ena) {
|
|
if (j < thisline_decision.nr_planes) {
|
|
//t = *(uae_u32 *)(line_data[next_lineno] + offs + 2 * j * MAX_WORDS_PER_LINE);
|
|
t = line_data[next_lineno][j][offs];
|
|
t ^= (match & 1) - 1;
|
|
} else {
|
|
t = (match & 1) - 1;
|
|
}
|
|
}
|
|
total &= t;
|
|
}
|
|
if (total) {
|
|
collided = 1;
|
|
/*if (1) { //debug
|
|
for (var k = 0; k < 1; k++) {
|
|
//uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + offs + 2 * k * MAX_WORDS_PER_LINE); *ldata ^= 0x5555555555;
|
|
line_data[next_lineno][k][offs] ^= 0x5555555555;
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
if (collided)
|
|
clxdat |= 1;
|
|
};
|
|
|
|
/* Sprite-to-sprite collisions are taken care of in record_sprite. This one does playfield/sprite collisions. */
|
|
this.do_sprite_collisions = function () {
|
|
var nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
|
|
var first = curr_drawinfo[next_lineno].first_sprite_entry;
|
|
var collision_mask = clxmask[clxcon >> 12];
|
|
var ddf_left = thisline_decision.plfleft * 2 << bplcon0_res;
|
|
var hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword);
|
|
var hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword);
|
|
|
|
if (clxcon_bpl_enable == 0) {
|
|
clxdat |= 0x1fe;
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < nr_sprites; i++) {
|
|
var e = curr_sprite_entries[first + i];
|
|
var minpos = e.pos;
|
|
var maxpos = e.max;
|
|
var minp1 = minpos >> sprite_buffer_res;
|
|
var maxp1 = maxpos >> sprite_buffer_res;
|
|
|
|
if (maxp1 > hw_diwlast)
|
|
maxpos = hw_diwlast << sprite_buffer_res;
|
|
if (maxp1 > thisline_decision.plfright * 2)
|
|
maxpos = thisline_decision.plfright * 2 << sprite_buffer_res;
|
|
if (minp1 < hw_diwfirst)
|
|
minpos = hw_diwfirst << sprite_buffer_res;
|
|
if (minp1 < thisline_decision.plfleft * 2)
|
|
minpos = thisline_decision.plfleft * 2 << sprite_buffer_res;
|
|
|
|
for (var j = minpos; j < maxpos; j++) {
|
|
var sprpix = spixels[e.first_pixel + j - e.pos] & collision_mask;
|
|
|
|
if (sprpix == 0)
|
|
continue;
|
|
|
|
var match = 1;
|
|
var offs = ((j << bplcon0_res) >> sprite_buffer_res) - ddf_left;
|
|
sprpix = (sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2)) << 1;
|
|
|
|
for (var k = 1; k >= 0; k--) {
|
|
/*#ifdef AGA
|
|
var planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6;
|
|
#else*/
|
|
var planes = 6;
|
|
//#endif
|
|
if (bplcon0 & 0x400)
|
|
match = 1;
|
|
for (var l = k; match && l < planes; l += 2) {
|
|
var t = 0;
|
|
if (l < thisline_decision.nr_planes) {
|
|
//uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); var word = ldata[offs >> 5];
|
|
var word = line_data[next_lineno][l][offs >> 5];
|
|
t = (word >>> (31 - (offs & 31))) & 1;
|
|
/*if (1) { //debug: draw collision mask
|
|
for (var m = 0; m < 5; m++) {
|
|
//uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * m * MAX_WORDS_PER_LINE); ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31));
|
|
line_data[next_lineno][m][(offs >> 5) + 0] |= 15 << (31 - (offs & 31));
|
|
}
|
|
}*/
|
|
}
|
|
if (clxcon_bpl_enable & (1 << l)) {
|
|
if (t != ((clxcon_bpl_match >> l) & 1))
|
|
match = 0;
|
|
}
|
|
}
|
|
if (match) {
|
|
/*if (1) { //debug: mark lines where collisions are detected
|
|
for (var l = 0; l < 5; l++) {
|
|
//uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31));
|
|
line_data[next_lineno][l][(offs >> 5) + 0] |= 15 << (31 - (offs & 31));
|
|
}
|
|
}*/
|
|
clxdat |= (sprpix << (k * 4));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*{
|
|
static var olx;
|
|
if (clxdat != olx) BUG.info('%d: %04x', vpos, clxdat);
|
|
olx = clxdat;
|
|
}*/
|
|
};
|
|
|
|
this.record_sprite_1 = function (sprxp, buf, datab, num, dbl, mask, do_collisions, collision_mask) {
|
|
var j = 0;
|
|
|
|
while (datab) {
|
|
var col = 0;
|
|
var coltmp = 0;
|
|
|
|
if ((sprxp >= sprite_minx && sprxp < sprite_maxx) || (bplcon3 & 2))
|
|
col = (datab & 3) << (2 * num);
|
|
|
|
//if (sprxp == sprite_minx || sprxp == sprite_maxx - 1) col ^= Math.floor(Math.random() * 0xffffffff);
|
|
|
|
if ((j & mask) == 0) {
|
|
//var tmp = (*buf) | col; *buf++ = tmp;
|
|
var tmp = spixels[buf] | col;
|
|
spixels[buf++] = tmp;
|
|
if (do_collisions)
|
|
coltmp |= tmp;
|
|
sprxp++;
|
|
}
|
|
if (dbl > 0) {
|
|
//var tmp = (*buf) | col; *buf++ = tmp;
|
|
var tmp = spixels[buf] | col;
|
|
spixels[buf++] = tmp;
|
|
if (do_collisions)
|
|
coltmp |= tmp;
|
|
sprxp++;
|
|
}
|
|
if (dbl > 1) {
|
|
var tmp;
|
|
//tmp = (*buf) | col; *buf++ = tmp;
|
|
tmp = spixels[buf] | col;
|
|
spixels[buf++] = tmp;
|
|
if (do_collisions)
|
|
coltmp |= tmp;
|
|
//tmp = (*buf) | col; *buf++ = tmp;
|
|
tmp = spixels[buf] | col;
|
|
spixels[buf++] = tmp;
|
|
if (do_collisions)
|
|
coltmp |= tmp;
|
|
sprxp++;
|
|
sprxp++;
|
|
}
|
|
j++;
|
|
datab >>>= 2;
|
|
if (do_collisions) {
|
|
coltmp &= collision_mask;
|
|
if (coltmp) {
|
|
var shrunk_tmp = sprite_ab_merge[coltmp & 255] | (sprite_ab_merge[coltmp >> 8] << 2);
|
|
clxdat |= sprclx[shrunk_tmp];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
//this.record_sprite = function(line, num, sprxp, data, datb, ctl) {
|
|
this.record_sprite = function (line, num, sprxp) {
|
|
var e = curr_sprite_entries[next_sprite_entry];
|
|
var word_offs;
|
|
var collision_mask;
|
|
var width, dbl, half;
|
|
var mask = 0;
|
|
var attachment;
|
|
var i;
|
|
|
|
//var data = 0, datb = 0;
|
|
var this_sprite_entry = next_sprite_entry;
|
|
var num2 = 0;
|
|
|
|
half = 0;
|
|
dbl = sprite_buffer_res - sprres;
|
|
if (dbl < 0) {
|
|
half = -dbl;
|
|
dbl = 0;
|
|
mask = 1 << half;
|
|
}
|
|
width = (sprite_width << sprite_buffer_res) >> sprres;
|
|
attachment = sprctl[num | 1] & 0x80;
|
|
|
|
/* Try to coalesce entries if they aren't too far apart */
|
|
//if (!next_sprite_forced && e[-1].max + sprite_width >= sprxp) {
|
|
if (this_sprite_entry > 0 && !next_sprite_forced && curr_sprite_entries[this_sprite_entry - 1].max + sprite_width >= sprxp) {
|
|
//e--;
|
|
e = curr_sprite_entries[this_sprite_entry - 1];
|
|
this_sprite_entry--;
|
|
//console.log('RS',this_sprite_entry);
|
|
} else {
|
|
next_sprite_entry++;
|
|
e.pos = sprxp;
|
|
e.has_attached = 0;
|
|
}
|
|
|
|
if (sprxp < e.pos)
|
|
Fatal(333, 'sprxp < e->pos');
|
|
|
|
e.max = sprxp + width;
|
|
//e[1].first_pixel = e.first_pixel + ((e.max - e.pos + 3) & ~3);
|
|
curr_sprite_entries[this_sprite_entry + 1].first_pixel = e.first_pixel + ((e.max - e.pos + 3) & ~3);
|
|
next_sprite_forced = 0;
|
|
|
|
collision_mask = clxmask[clxcon >> 12];
|
|
word_offs = e.first_pixel + sprxp - e.pos;
|
|
|
|
for (i = 0; i < sprite_width; i += 16) {
|
|
//var da = *data;
|
|
//var db = *datb;
|
|
//var da = sprdata[data][0];
|
|
//var db = sprdatb[datb][0];
|
|
var da = sprdata[num][num2];
|
|
var db = sprdatb[num][num2];
|
|
var datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]) >>> 0;
|
|
var off = (i << dbl) >> half;
|
|
//uae_u16 *buf = spixels + word_offs + off;
|
|
var buf = word_offs + off;
|
|
if (AMIGA.config.chipset.collision_level > 0 && collision_mask)
|
|
this.record_sprite_1(sprxp + off, buf, datab, num, dbl, mask, 1, collision_mask);
|
|
else
|
|
this.record_sprite_1(sprxp + off, buf, datab, num, dbl, mask, 0, collision_mask);
|
|
|
|
//*data++; *datb++;
|
|
num2++;
|
|
}
|
|
|
|
/* We have 8 bits per pixel in spixstate, two for every sprite pair.
|
|
The low order bit records whether the attach bit was set for this pair. */
|
|
if (attachment && !ecsshres_func()) {
|
|
var state = ((0x01010101 << (num & ~1)) >>> 0) & 0xff;
|
|
/*uae_u8 *stb1 = spixstate.bytes + word_offs;
|
|
for (i = 0; i < width; i += 8) {
|
|
stb1[0] |= state;
|
|
stb1[1] |= state;
|
|
stb1[2] |= state;
|
|
stb1[3] |= state;
|
|
stb1[4] |= state;
|
|
stb1[5] |= state;
|
|
stb1[6] |= state;
|
|
stb1[7] |= state;
|
|
stb1 += 8;
|
|
}*/
|
|
var stb1 = word_offs;
|
|
for (i = 0; i < width; i += 8) {
|
|
spixstate[stb1 + 0] |= state;
|
|
spixstate[stb1 + 1] |= state;
|
|
spixstate[stb1 + 2] |= state;
|
|
spixstate[stb1 + 3] |= state;
|
|
spixstate[stb1 + 4] |= state;
|
|
spixstate[stb1 + 5] |= state;
|
|
spixstate[stb1 + 6] |= state;
|
|
spixstate[stb1 + 7] |= state;
|
|
stb1 += 8;
|
|
}
|
|
e.has_attached = 1;
|
|
}
|
|
};
|
|
|
|
function tospritexdiw(diw) {
|
|
return coord_window_to_hw_x(diw - (DIW_DDF_OFFSET << lores_shift)) << sprite_buffer_res;
|
|
}
|
|
function tospritexddf(ddf) {
|
|
return (ddf << 1) << sprite_buffer_res;
|
|
}
|
|
/*function fromspritexdiw(ddf) {
|
|
return coord_hw_to_window_x(ddf >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
|
|
}*/
|
|
|
|
function calcsprite() {
|
|
sprite_maxx = 0x7fff;
|
|
sprite_minx = 0;
|
|
if (thisline_decision.diwlastword >= 0)
|
|
sprite_maxx = tospritexdiw(thisline_decision.diwlastword);
|
|
if (thisline_decision.diwfirstword >= 0)
|
|
sprite_minx = tospritexdiw(thisline_decision.diwfirstword);
|
|
if (thisline_decision.plfleft >= 0) {
|
|
var min = tospritexddf(thisline_decision.plfleft);
|
|
var max = tospritexddf(thisline_decision.plfright);
|
|
if (min > sprite_minx && min < max) /* min < max = full line ddf */
|
|
sprite_minx = min;
|
|
}
|
|
}
|
|
|
|
function add_sprite(count, num, sprxp, posns, nrs) {
|
|
var bestp, j;
|
|
for (bestp = 0; bestp < count; bestp++) {
|
|
if (posns[bestp] > sprxp)
|
|
break;
|
|
if (posns[bestp] == sprxp && nrs[bestp] < num)
|
|
break;
|
|
}
|
|
for (j = count; j > bestp; j--) {
|
|
posns[j] = posns[j - 1];
|
|
nrs[j] = nrs[j - 1];
|
|
}
|
|
posns[j] = sprxp;
|
|
nrs[j] = num;
|
|
}
|
|
|
|
this.decide_sprites = function (hpos) {
|
|
if (!DO_SPRITES) return; //FIXME
|
|
var nrs = [], posns = [];
|
|
var point = hpos * 2 - 3;
|
|
//var width = sprite_width;
|
|
var sscanmask = 0x100 << sprite_buffer_res;
|
|
//var gotdata = 0;
|
|
var count, i;
|
|
|
|
if (thisline_decision.plfleft < 0 && !(bplcon3 & 2))
|
|
return;
|
|
|
|
if (this.nodraw() || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
|
|
return;
|
|
|
|
this.decide_diw(hpos);
|
|
this.decide_line(hpos);
|
|
|
|
calcsprite();
|
|
|
|
for (i = 0; i < MAX_SPRITES * 2; i++)
|
|
nrs[i] = posns[i] = 0;
|
|
|
|
count = 0;
|
|
for (i = 0; i < MAX_SPRITES; i++) {
|
|
var sprxp = (fmode & 0x8000) ? (spr[i].xpos & ~sscanmask) : spr[i].xpos;
|
|
var hw_xp = sprxp >> sprite_buffer_res;
|
|
|
|
if (!spr[i].armed || spr[i].xpos < 0)
|
|
continue;
|
|
/*if (!((debug_sprite_mask & magic_sprite_mask) & (1 << i)))
|
|
continue;*/
|
|
|
|
if (hw_xp > last_sprite_point && hw_xp <= point)
|
|
add_sprite(count++, i, sprxp, posns, nrs);
|
|
|
|
if ((fmode & 0x8000) && !(sprxp & sscanmask)) {
|
|
sprxp |= sscanmask;
|
|
hw_xp = sprxp >> sprite_buffer_res;
|
|
if (hw_xp > last_sprite_point && hw_xp <= point)
|
|
add_sprite(count++, MAX_SPRITES + i, sprxp, posns, nrs);
|
|
}
|
|
}
|
|
for (i = 0; i < count; i++) {
|
|
var nr = nrs[i] & (MAX_SPRITES - 1);
|
|
//this.record_sprite(next_lineno, nr, posns[i], sprdata[nr], sprdatb[nr], sprctl[nr]);
|
|
this.record_sprite(next_lineno, nr, posns[i]);
|
|
|
|
/* get left and right sprite edge if brdsprt enabled */
|
|
/*#if AUTOSCALE_SPRITES
|
|
if (AMIGA.dmaen(DMAF_SPREN) && (bplcon0 & 1) && (bplcon3 & 0x02) && !(bplcon3 & 0x20) && nr > 0) {
|
|
var j, jj;
|
|
for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) {
|
|
var nx = fromspritexdiw (posns[i] + j);
|
|
if (sprdata[nr][jj] || sprdatb[nr][jj]) {
|
|
if (diwfirstword_total > nx && nx >= (48 << currprefs.hresolution))
|
|
diwfirstword_total = nx;
|
|
if (diwlastword_total < nx + 16 && nx <= (448 << currprefs.hresolution))
|
|
diwlastword_total = nx + 16;
|
|
}
|
|
}
|
|
gotdata = 1;
|
|
}
|
|
#endif*/
|
|
}
|
|
last_sprite_point = point;
|
|
|
|
/* get upper and lower sprite position if brdsprt enabled */
|
|
/*#if AUTOSCALE_SPRITES
|
|
if (gotdata) {
|
|
if (vpos < first_planes_vpos)
|
|
first_planes_vpos = vpos;
|
|
if (vpos < plffirstline_total)
|
|
plffirstline_total = vpos;
|
|
if (vpos > last_planes_vpos)
|
|
last_planes_vpos = vpos;
|
|
if (vpos > plflastline_total)
|
|
plflastline_total = vpos;
|
|
}
|
|
#endif*/
|
|
};
|
|
|
|
this.cursorsprite = function () {
|
|
if (!AMIGA.dmaen(DMAF_SPREN) || first_planes_vpos == 0)
|
|
return;
|
|
sprite_0 = spr[0].pt;
|
|
sprite_0_height = spr[0].vstop - spr[0].vstart;
|
|
sprite_0_colors[0] = 0;
|
|
sprite_0_doubled = 0;
|
|
if (sprres == 0)
|
|
sprite_0_doubled = 1;
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
var sbasecol = ((bplcon4 >> 4) & 15) << 4;
|
|
sprite_0_colors[1] = current_colors.color_regs_aga[sbasecol + 1];
|
|
sprite_0_colors[2] = current_colors.color_regs_aga[sbasecol + 2];
|
|
sprite_0_colors[3] = current_colors.color_regs_aga[sbasecol + 3];
|
|
} else {
|
|
sprite_0_colors[1] = xcolors[current_colors.color_regs_ecs[17]];
|
|
sprite_0_colors[2] = xcolors[current_colors.color_regs_ecs[18]];
|
|
sprite_0_colors[3] = xcolors[current_colors.color_regs_ecs[19]];
|
|
}
|
|
sprite_0_width = sprite_width;
|
|
/*if (currprefs.input_tablet && currprefs.input_magic_mouse) {
|
|
if (currprefs.input_magic_mouse_cursor == MAGICMOUSE_HOST_ONLY && mousehack_alive ())
|
|
magic_sprite_mask &= ~1;
|
|
else
|
|
magic_sprite_mask |= 1;
|
|
}*/
|
|
};
|
|
|
|
function sprite_fetch(s, dma, hpos, cycle, mode) {
|
|
var data = AMIGA.custom.last_value;
|
|
if (dma) {
|
|
//data = AMIGA.mem.load16_chip(s.pt);
|
|
data = AMIGA.custom.last_value = AMIGA.mem.chip.data[s.pt >>> 1];
|
|
}
|
|
s.pt += 2;
|
|
return data;
|
|
}
|
|
function sprite_fetch2(s, hpos, cycle, mode) {
|
|
//var data = AMIGA.mem.load16_chip(s.pt);
|
|
var data = AMIGA.custom.last_value = AMIGA.mem.chip.data[s.pt >>> 1];
|
|
s.pt += 2;
|
|
return data;
|
|
}
|
|
|
|
this.do_sprites_1 = function (num, cycle, hpos) {
|
|
var s = spr[num];
|
|
var isdma = AMIGA.dmaen(DMAF_SPREN) || ((num & 1) && spr[num & ~1].dmacycle);
|
|
|
|
if (isdma && this.vpos == sprite_vblank_endline)
|
|
spr_arm(num, 0);
|
|
/*#ifdef AGA
|
|
if (isdma && s.dblscan && (fmode & 0x8000) && (this.vpos & 1) != (s.vstart & 1) && s.dmastate) {
|
|
spr_arm(num, 1);
|
|
return;
|
|
}
|
|
#endif*/
|
|
|
|
//if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:slot%d:%d', this.vpos, hpos, num, cycle);
|
|
|
|
if (this.vpos == s.vstart) {
|
|
//if (!s.dmastate && this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%d START', this.vpos, hpos, num);
|
|
s.dmastate = 1;
|
|
if (num == 0 && cycle == 0)
|
|
this.cursorsprite();
|
|
}
|
|
if (this.vpos == s.vstop || this.vpos == sprite_vblank_endline) {
|
|
//if (s.dmastate && this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%d STOP', this.vpos, hpos, num);
|
|
s.dmastate = 0;
|
|
/*#if 0
|
|
// roots 2.0 flower zoomer bottom part missing if this enabled
|
|
if (this.vpos == s.vstop) {
|
|
spr_arm (num, 0);
|
|
//return;
|
|
}
|
|
#endif*/
|
|
}
|
|
|
|
if (!isdma)
|
|
return;
|
|
if (cycle && !s.dmacycle)
|
|
return;
|
|
/* Superfrog intro flashing bee fix */
|
|
|
|
var dma = hpos < plfstrt_sprite || diwstate != DIW_WAITING_STOP;
|
|
var posctl = 0;
|
|
|
|
if (this.vpos == s.vstop || this.vpos == sprite_vblank_endline) {
|
|
s.dmastate = 0;
|
|
posctl = 1;
|
|
if (dma) {
|
|
var data = sprite_fetch(s, dma, hpos, cycle, 0);
|
|
switch (sprite_width) {
|
|
case 64:
|
|
sprite_fetch2(s, hpos, cycle, 0);
|
|
sprite_fetch2(s, hpos, cycle, 0);
|
|
break;
|
|
case 32:
|
|
sprite_fetch2(s, hpos, cycle, 0);
|
|
break;
|
|
}
|
|
//BUG.info('%d:%d: %04X=%04X', this.vpos, hpos, 0x140 + cycle * 2 + num * 8, data);
|
|
if (cycle == 0) {
|
|
this.SPRxPOS_1(data, num, hpos);
|
|
s.dmacycle = 1;
|
|
} else {
|
|
this.SPRxCTL_1(data, num, hpos);
|
|
s.dmastate = 0;
|
|
this.sprstartstop(s);
|
|
}
|
|
}
|
|
//if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:dma:P=%06X '), this.vpos, hpos, s.pt);
|
|
}
|
|
if (s.dmastate && !posctl && dma) {
|
|
var data = sprite_fetch(s, dma, hpos, cycle, 1);
|
|
//if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:dma:P=%06X '), this.vpos, hpos, s.pt);
|
|
if (cycle == 0) {
|
|
this.SPRxDATA_1(data, num, hpos);
|
|
s.dmacycle = 1;
|
|
} else {
|
|
this.SPRxDATB_1(data, num, hpos);
|
|
spr_arm(num, 1);
|
|
}
|
|
/*#ifdef AGA
|
|
switch (sprite_width) {
|
|
case 64: {
|
|
var data32 = sprite_fetch2 (s, hpos, cycle, 1);
|
|
var data641 = sprite_fetch2 (s, hpos, cycle, 1);
|
|
var data642 = sprite_fetch2 (s, hpos, cycle, 1);
|
|
if (dma) {
|
|
if (cycle == 0) {
|
|
sprdata[num][3] = data642;
|
|
sprdata[num][2] = data641;
|
|
sprdata[num][1] = data32;
|
|
} else {
|
|
sprdatb[num][3] = data642;
|
|
sprdatb[num][2] = data641;
|
|
sprdatb[num][1] = data32;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 32: {
|
|
var data32 = sprite_fetch2 (s, hpos, cycle, 1);
|
|
if (dma) {
|
|
if (cycle == 0)
|
|
sprdata[num][1] = data32;
|
|
else
|
|
sprdatb[num][1] = data32;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif*/
|
|
}
|
|
};
|
|
|
|
this.do_sprites = function (hpos) {
|
|
if (!DO_SPRITES) return; //FIXME
|
|
if (this.vpos < sprite_vblank_endline)
|
|
return;
|
|
|
|
if (this.doflickerfix() && interlace_seen && (next_lineno & 1))
|
|
return;
|
|
|
|
if (!CUSTOM_SIMPLE) {
|
|
var minspr = last_sprite_hpos + 1;
|
|
var maxspr = hpos;
|
|
|
|
if (minspr >= maxspr || last_sprite_hpos == hpos)
|
|
return;
|
|
|
|
if (maxspr >= SPR0_HPOS + MAX_SPRITES * 4)
|
|
maxspr = SPR0_HPOS + MAX_SPRITES * 4 - 1;
|
|
if (minspr < SPR0_HPOS)
|
|
minspr = SPR0_HPOS;
|
|
|
|
if (minspr == maxspr)
|
|
return;
|
|
|
|
for (var i = minspr; i <= maxspr; i++) {
|
|
var cycle = -1;
|
|
var num = (i - SPR0_HPOS) >> 2;
|
|
switch ((i - SPR0_HPOS) & 3) {
|
|
case 0:
|
|
cycle = 0;
|
|
spr[num].dmacycle = 0;
|
|
break;
|
|
case 2:
|
|
cycle = 1;
|
|
break;
|
|
}
|
|
if (cycle >= 0) {
|
|
spr[num].ptxhpos = MAXHPOS;
|
|
this.do_sprites_1(num, cycle, i);
|
|
}
|
|
}
|
|
last_sprite_hpos = hpos;
|
|
} else {
|
|
for (var i = 0; i < MAX_SPRITES * 2; i++) {
|
|
spr[i >> 1].dmacycle = 1;
|
|
this.do_sprites_1(i >> 1, i & 1, 0);
|
|
}
|
|
}
|
|
};
|
|
|
|
function expand_sprres(con0, con3) {
|
|
switch ((con3 >> 6) & 3) {
|
|
case 0: {
|
|
if ((AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && GET_RES_DENISE(con0) == RES_SUPERHIRES)
|
|
return RES_HIRES;
|
|
else
|
|
return RES_LORES;
|
|
}
|
|
/*#ifdef AGA
|
|
case 1:
|
|
return RES_LORES;
|
|
case 2:
|
|
return RES_HIRES;
|
|
case 3:
|
|
return RES_SUPERHIRES;
|
|
#endif*/
|
|
default:
|
|
return RES_LORES;
|
|
}
|
|
}
|
|
|
|
function spr_arm(num, state) {
|
|
switch (state) {
|
|
case 0:
|
|
nr_armed -= spr[num].armed;
|
|
spr[num].armed = 0;
|
|
break;
|
|
default:
|
|
nr_armed += 1 - spr[num].armed;
|
|
spr[num].armed = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.sprstartstop = function (s) {
|
|
if (this.vpos == s.vstart)
|
|
s.dmastate = 1;
|
|
if (this.vpos == s.vstop)
|
|
s.dmastate = 0;
|
|
};
|
|
|
|
this.CLXCON = function (v) {
|
|
clxcon = v;
|
|
clxcon_bpl_enable = (v >> 6) & 63;
|
|
clxcon_bpl_match = v & 63;
|
|
};
|
|
|
|
this.CLXCON2 = function (v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
return;
|
|
clxcon2 = v;
|
|
clxcon_bpl_enable |= v & (0x40 | 0x80);
|
|
clxcon_bpl_match |= (v & (0x01 | 0x02)) << 6;
|
|
};
|
|
|
|
this.CLXDAT = function () {
|
|
var v = clxdat | 0x8000;
|
|
clxdat = 0;
|
|
return v;
|
|
};
|
|
|
|
this.SPRxCTLPOS = function (num) {
|
|
var sprxp;
|
|
var s = spr[num];
|
|
|
|
this.sprstartstop(s);
|
|
sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1);
|
|
sprxp <<= sprite_buffer_res;
|
|
/*#ifdef AGA
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
sprxp |= ((sprctl[num] >> 3) & 3) >> (RES_MAX - sprite_buffer_res);
|
|
s.dblscan = sprpos[num] & 0x80;
|
|
} else
|
|
#endif*/
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) {
|
|
sprxp |= ((sprctl[num] >> 3) & 2) >> (RES_MAX - sprite_buffer_res);
|
|
}
|
|
s.xpos = sprxp;
|
|
s.vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
|
|
s.vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) {
|
|
s.vstart |= (sprctl[num] << 3) & 0x200;
|
|
s.vstop |= (sprctl[num] << 4) & 0x200;
|
|
}
|
|
this.sprstartstop(s);
|
|
};
|
|
|
|
this.SPRxCTL_1 = function (v, num, hpos) {
|
|
//struct sprite *s = &spr[num];
|
|
sprctl[num] = v;
|
|
spr_arm(num, 0);
|
|
this.SPRxCTLPOS(num);
|
|
/*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) {
|
|
BUG.info('%d:%d:SPR%dCTL %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x', this.vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC);
|
|
}*/
|
|
};
|
|
|
|
this.SPRxPOS_1 = function (v, num, hpos) {
|
|
//struct sprite *s = &spr[num];
|
|
sprpos[num] = v;
|
|
this.SPRxCTLPOS(num);
|
|
/*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) {
|
|
BUG.info('%d:%d:SPR%dPOS %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x', this.vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC);
|
|
}*/
|
|
};
|
|
|
|
this.SPRxDATA_1 = function (v, num, hpos) {
|
|
sprdata[num][0] = v;
|
|
/*#ifdef AGA
|
|
sprdata[num][1] = v;
|
|
sprdata[num][2] = v;
|
|
sprdata[num][3] = v;
|
|
#endif*/
|
|
spr_arm(num, 1);
|
|
/*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) {
|
|
BUG.info('%d:%d:SPR%dDATA %04X P=%06X D=%d A=%d PC=%x', this.vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC);
|
|
}*/
|
|
};
|
|
|
|
this.SPRxDATB_1 = function (v, num, hpos) {
|
|
sprdatb[num][0] = v;
|
|
/*#ifdef AGA
|
|
sprdatb[num][1] = v;
|
|
sprdatb[num][2] = v;
|
|
sprdatb[num][3] = v;
|
|
#endif*/
|
|
/*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) {
|
|
BUG.info('%d:%d:SPR%dDATB %04X P=%06X D=%d A=%d PC=%x', this.vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC);
|
|
}*/
|
|
};
|
|
|
|
this.SPRxDATA = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
this.SPRxDATA_1(v, num, hpos);
|
|
};
|
|
this.SPRxDATB = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
this.SPRxDATB_1(v, num, hpos);
|
|
};
|
|
this.SPRxCTL = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
this.SPRxCTL_1(v, num, hpos);
|
|
};
|
|
this.SPRxPOS = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
this.SPRxPOS_1(v, num, hpos);
|
|
};
|
|
|
|
this.SPRxPTH = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
if (hpos - 1 != spr[num].ptxhpos) {
|
|
spr[num].pt = ((v << 16) | (spr[num].pt & 0xffff)) >>> 0;
|
|
}
|
|
//if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%dPTH %06X', this.vpos, hpos, num, spr[num].pt);
|
|
};
|
|
this.SPRxPTL = function (hpos, v, num) {
|
|
this.decide_sprites(hpos);
|
|
if (hpos - 1 != spr[num].ptxhpos) {
|
|
spr[num].pt = ((spr[num].pt & 0xffff0000) | (v & 0xfffe)) >>> 0;
|
|
}
|
|
//if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%dPTL %06X', this.vpos, hpos, num, spr[num].pt);
|
|
};
|
|
|
|
this.setup_sprites = function () {
|
|
if (!sprinit) {
|
|
sprinit = true;
|
|
setup_sprite_tables();
|
|
}
|
|
};
|
|
|
|
this.cleanup_sprites = function () {
|
|
};
|
|
|
|
this.reset_sprites = function () {
|
|
var i;
|
|
for (i = 0; i < sprpos.length; i++) sprpos[i] = 0; //memset (sprpos, 0, sizeof sprpos);
|
|
for (i = 0; i < sprctl.length; i++) sprctl[i] = 0; //memset (sprctl, 0, sizeof sprctl);
|
|
|
|
for (i = 0; i < spixels.length; i++) spixels[i] = 0; //memset(spixels, 0, sizeof spixels);
|
|
for (i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset(&spixstate, 0, sizeof spixstate);
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* playfield */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/*function debug_cycle_diagram() {
|
|
var fm, res, planes, cycle, v;
|
|
var aa, txt = '';
|
|
|
|
for (fm = 0; fm <= 2; fm++) {
|
|
txt += sprintf('FMODE %d\n=======\n', fm);
|
|
for (res = 0; res <= 2; res++) {
|
|
for (planes = 0; planes <= 8; planes++) {
|
|
txt += sprintf('%d: ',planes);
|
|
for (cycle = 0; cycle < 32; cycle++) {
|
|
v = cycle_diagram_table[fm][res][planes][cycle];
|
|
if (v == 0) aa='-'; else if (v > 0) aa='1'; else aa='X';
|
|
txt += sprintf('%s', aa);
|
|
}
|
|
txt += sprintf(' %d:%d\n', cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]);
|
|
}
|
|
txt += sprintf('\n');
|
|
}
|
|
}
|
|
BUG.info(txt);
|
|
}*/
|
|
|
|
function create_cycle_diagram_table() {
|
|
var fm, res, cycle, planes, rplanes, v;
|
|
var fetch_start, max_planes, freecycles;
|
|
var cycle_sequence;
|
|
var i, j, k, l;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
real_bitplane_number[i] = [];
|
|
cycle_diagram_free_cycles[i] = [];
|
|
cycle_diagram_total_cycles[i] = [];
|
|
for (j = 0; j < 3; j++) {
|
|
real_bitplane_number[i][j] = [];
|
|
cycle_diagram_free_cycles[i][j] = [];
|
|
cycle_diagram_total_cycles[i][j] = [];
|
|
for (k = 0; k < 9; k++) {
|
|
real_bitplane_number[i][j][k] = 0;
|
|
cycle_diagram_free_cycles[i][j][k] = 0;
|
|
cycle_diagram_total_cycles[i][j][k] = 0;
|
|
}
|
|
}
|
|
}
|
|
cycle_diagram_table = [];
|
|
for (i = 0; i < 3; i++) {
|
|
cycle_diagram_table[i] = [];
|
|
for (j = 0; j < 3; j++) {
|
|
cycle_diagram_table[i][j] = [];
|
|
for (k = 0; k < 9; k++) {
|
|
cycle_diagram_table[i][j][k] = [];
|
|
for (l = 0; l < 32; l++)
|
|
cycle_diagram_table[i][j][k][l] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (fm = 0; fm <= 2; fm++) {
|
|
for (res = 0; res <= 2; res++) {
|
|
max_planes = fm_maxplanes[fm * 4 + res];
|
|
fetch_start = 1 << fetchstarts[fm * 4 + res];
|
|
cycle_sequence = cycle_sequences[max_planes - 1];
|
|
max_planes = 1 << max_planes;
|
|
for (planes = 0; planes <= 8; planes++) {
|
|
freecycles = 0;
|
|
for (cycle = 0; cycle < 32; cycle++)
|
|
cycle_diagram_table[fm][res][planes][cycle] = -1;
|
|
if (planes <= max_planes) {
|
|
for (cycle = 0; cycle < fetch_start; cycle++) {
|
|
if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) {
|
|
v = cycle_sequence[cycle & 7];
|
|
} else {
|
|
v = 0;
|
|
freecycles++;
|
|
}
|
|
cycle_diagram_table[fm][res][planes][cycle] = v;
|
|
}
|
|
}
|
|
cycle_diagram_free_cycles[fm][res][planes] = freecycles;
|
|
cycle_diagram_total_cycles[fm][res][planes] = fetch_start;
|
|
rplanes = planes;
|
|
if (rplanes > max_planes)
|
|
rplanes = 0;
|
|
if (rplanes == 7 && fm == 0 && res == 0 && !(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
rplanes = 4;
|
|
real_bitplane_number[fm][res][planes] = rplanes;
|
|
}
|
|
}
|
|
}
|
|
//debug_cycle_diagram();
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
|
|
function doMask(p, bits, shift) {
|
|
/* scale to 0..255, shift to align msb with mask, and apply mask */
|
|
|
|
//if (flashscreen) p ^= 0xff;
|
|
var val = (p << 24) >>> 0;
|
|
if (!bits)
|
|
return 0;
|
|
val >>>= (32 - bits);
|
|
val <<= shift;
|
|
|
|
return val >>> 0;
|
|
}
|
|
function doAlpha (alpha, bits, shift) {
|
|
return ((alpha & ((1 << bits) - 1)) << shift) >>> 0;
|
|
}
|
|
function alloc_colors64k (rw, gw, bw, rs, gs, bs, aw, as, alpha, byte_swap) {
|
|
//#define bswap_16(x) (((x) >> 8) | (((x) & 0xFF) << 8))
|
|
//#define bswap_32(x) (((x) << 24) | (((x) << 8) & 0x00FF0000) | (((x) >> 8) & 0x0000FF00) | ((x) >> 24))
|
|
var bpp = rw + gw + bw + aw;
|
|
//var j = 256;
|
|
|
|
//video_calc_gammatable();
|
|
for (var i = 0; i < 4096; i++) {
|
|
var r = ((i >> 8) << 4) | (i >> 8);
|
|
var g = (((i >> 4) & 0xf) << 4) | ((i >> 4) & 0x0f);
|
|
var b = ((i & 0xf) << 4) | (i & 0x0f);
|
|
//r = gamma[r + j];
|
|
//g = gamma[g + j];
|
|
//b = gamma[b + j];
|
|
xcolors[i] = (doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs) | doAlpha(alpha, aw, as)) >>> 0;
|
|
if (byte_swap) {
|
|
if (bpp <= 16)
|
|
xcolors[i] = bswap_16(xcolors[i]);
|
|
else
|
|
xcolors[i] = bswap_32(xcolors[i]);
|
|
}
|
|
if (bpp <= 16) {
|
|
/* Fill upper 16 bits of each colour value
|
|
* with a copy of the colour. */
|
|
xcolors[i] |= xcolors[i] * 0x00010001;
|
|
xcolors[i] >>>= 0;
|
|
}
|
|
}
|
|
//console.log('alloc_colors64k', xcolors);
|
|
}
|
|
|
|
function update_mirrors() {
|
|
aga_mode = (AMIGA.config.chipset.mask & CSMASK_AGA) != 0;
|
|
direct_rgb = aga_mode;
|
|
}
|
|
|
|
function docols(colentry) {
|
|
/*#ifdef AGA
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
for (var i = 0; i < 256; i++) {
|
|
var v = color_reg_get (colentry, i);
|
|
if (v < 0 || v > 16777215)
|
|
continue;
|
|
colentry->acolors[i] = getxcolor (v);
|
|
}
|
|
} else {
|
|
#endif*/
|
|
for (var i = 0; i < 32; i++) {
|
|
var v = color_reg_get(colentry, i);
|
|
if (v < 0 || v > 4095)
|
|
continue;
|
|
colentry.acolors[i] = getxcolor(v);
|
|
}
|
|
/*#ifdef AGA
|
|
}
|
|
#endif*/
|
|
}
|
|
function notice_new_xcolors() {
|
|
update_mirrors();
|
|
docols(current_colors);
|
|
docols(colors_for_drawing);
|
|
for (var i = 0; i < (MAXVPOS + 1) * 2; i++) {
|
|
docols(color_tables[0][i]);
|
|
docols(color_tables[1][i]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
|
|
function getxcolor(c) {
|
|
/*#ifdef AGA
|
|
if (direct_rgb)
|
|
return CONVERT_RGB(c);
|
|
else
|
|
#endif*/
|
|
return xcolors[c];
|
|
}
|
|
|
|
function color_reg_get(ce, c) {
|
|
/*#ifdef AGA
|
|
if (aga_mode)
|
|
return ce.color_regs_aga[c];
|
|
else
|
|
#endif*/
|
|
return ce.color_regs_ecs[c];
|
|
}
|
|
|
|
function color_reg_set(ce, c, v) {
|
|
/*#ifdef AGA
|
|
if (aga_mode)
|
|
ce.color_regs_aga[c] = v;
|
|
else
|
|
#endif*/
|
|
ce.color_regs_ecs[c] = v;
|
|
}
|
|
|
|
function color_reg_cmp(ce1, ce2) {
|
|
/*#ifdef AGA
|
|
if (aga_mode) {
|
|
v = memcmp (ce1->color_regs_aga, ce2->color_regs_aga, sizeof (uae_u32) * 256);
|
|
} else
|
|
#endif*/
|
|
{
|
|
//v = memcmp (ce1.color_regs_ecs, ce2.color_regs_ecs, sizeof (uae_u16) * 32);
|
|
for (var i = 0; i < 32; i++) {
|
|
if (ce1.color_regs_ecs[i] != ce2.color_regs_ecs[i])
|
|
return 1;
|
|
}
|
|
return ce1.borderblank == ce2.borderblank ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
function color_reg_cpy(dst, src) {
|
|
dst.borderblank = src.borderblank;
|
|
/*#ifdef AGA
|
|
if (aga_mode)
|
|
//copy acolors and color_regs_aga
|
|
memcpy (dst->acolors, src->acolors, sizeof(struct ColorEntry) - sizeof(uae_u16) * 32);
|
|
else
|
|
#endif*/
|
|
//copy first 32 acolors and color_regs_ecs
|
|
//memcpy (dst.color_regs_ecs, src.color_regs_ecs, sizeof(struct ColorEntry));
|
|
|
|
for (var i = 0; i < 32; i++) {
|
|
dst.acolors[i] = src.acolors[i];
|
|
dst.color_regs_ecs[i] = src.color_regs_ecs[i];
|
|
}
|
|
//console.log('color_reg_cpy()', dst, src);
|
|
}
|
|
|
|
function color_reg_cpy_acolors(dst, src) {
|
|
dst.borderblank = src.borderblank;
|
|
for (var i = 0; i < dst.acolors.length; i++)
|
|
dst.acolors[i] = src.acolors[i];
|
|
}
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.remember_ctable = function () {
|
|
if (next_color_entry >= COLOR_TABLE_SIZE) {
|
|
BUG.info('remember_ctable() BUG', next_color_entry);
|
|
return;
|
|
}
|
|
if (remembered_color_entry < 0) {
|
|
color_reg_cpy(curr_color_tables[next_color_entry], current_colors);
|
|
remembered_color_entry = next_color_entry++;
|
|
}
|
|
thisline_decision.ctable = remembered_color_entry;
|
|
|
|
if (color_src_match < 0 || color_dest_match != remembered_color_entry || line_decisions[next_lineno].ctable != color_src_match) {
|
|
var oldctable = line_decisions[next_lineno].ctable;
|
|
var changed = 0;
|
|
|
|
if (oldctable < 0) {
|
|
changed = 1;
|
|
color_src_match = color_dest_match = -1;
|
|
} else {
|
|
color_compare_result = color_reg_cmp(prev_color_tables[oldctable], current_colors) != 0;
|
|
if (color_compare_result)
|
|
changed = 1;
|
|
color_src_match = oldctable;
|
|
color_dest_match = remembered_color_entry;
|
|
}
|
|
thisline_changed |= changed;
|
|
} else {
|
|
if (color_compare_result)
|
|
thisline_changed = 1;
|
|
}
|
|
};
|
|
|
|
this.record_color_change2 = function (hpos, regno, value) {
|
|
//if (FAST_COLORS) //en for better?
|
|
//return;
|
|
var pos = hpos * 2;
|
|
if (regno == 0x1000 + 0x10c) pos++; // BPLCON4 change needs 1 lores pixel delay
|
|
curr_color_changes[next_color_change].linepos = pos;
|
|
curr_color_changes[next_color_change].regno = regno;
|
|
curr_color_changes[next_color_change++].value = value;
|
|
curr_color_changes[next_color_change].regno = -1;
|
|
//console.log('record_color_change2()', next_color_change);
|
|
};
|
|
|
|
this.record_color_change = function (hpos, regno, value) {
|
|
if (FAST_COLORS)
|
|
return;
|
|
if (this.vpos < minfirstline || (regno < 0x1000 && this.nodraw()))
|
|
return;
|
|
|
|
this.decide_diw(hpos);
|
|
this.decide_line(hpos);
|
|
|
|
if (thisline_decision.ctable < 0)
|
|
this.remember_ctable();
|
|
|
|
if ((regno < 0x1000 || regno == 0x1000 + 0x10c) && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) {
|
|
var pdip = curr_drawinfo[prev_lineno];
|
|
var idx = pdip.last_color_change;
|
|
var extrahpos = regno == 0x1000 + 0x10c ? 1 : 0;
|
|
var lastsync = false;
|
|
|
|
if (idx > 0 && curr_color_changes[idx - 1].regno == 0xffff) {
|
|
idx--;
|
|
lastsync = true;
|
|
}
|
|
pdip.last_color_change++;
|
|
pdip.nr_color_changes++;
|
|
curr_color_changes[idx].linepos = (hpos + this.maxhpos) * 2 + extrahpos;
|
|
curr_color_changes[idx].regno = regno;
|
|
curr_color_changes[idx].value = value;
|
|
if (lastsync) {
|
|
curr_color_changes[idx + 1].linepos = hsyncstartpos * 2;
|
|
curr_color_changes[idx + 1].regno = 0xffff;
|
|
curr_color_changes[idx + 2].regno = -1;
|
|
} else
|
|
curr_color_changes[idx + 1].regno = -1;
|
|
}
|
|
this.record_color_change2(hpos, regno, value);
|
|
};
|
|
|
|
this.isbrdblank = function (hpos, con0, con3) {
|
|
var brdblank = (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) != 0 && (con0 & 1) != 0 && (con3 & 0x20) != 0;
|
|
|
|
if (hpos >= 0 && current_colors.borderblank != brdblank) {
|
|
if (!FAST_COLORS) {
|
|
this.record_color_change(hpos, 0, (COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0)) >>> 0);
|
|
remembered_color_entry = -1;
|
|
}
|
|
current_colors.borderblank = brdblank;
|
|
}
|
|
return brdblank;
|
|
};
|
|
|
|
this.record_register_change = function (hpos, regno, value) {
|
|
if (regno == 0x100) { // BPLCON0
|
|
if (value & 0x800)
|
|
thisline_decision.ham_seen = 1;
|
|
thisline_decision.ehb_seen = is_ehb(value, bplcon2);
|
|
this.isbrdblank(hpos, value, bplcon3);
|
|
} else if (regno == 0x104) // BPLCON2
|
|
thisline_decision.ehb_seen = is_ehb(bplcon0, value);
|
|
else if (regno == 0x106) // BPLCON3
|
|
this.isbrdblank(hpos, bplcon0, value);
|
|
|
|
if (!FAST_COLORS)
|
|
this.record_color_change(hpos, regno + 0x1000, value);
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.compute_vsynctime = function () {
|
|
if (AMIGA.config.chipset.refreshrate > 0)
|
|
this.vblank_hz = AMIGA.config.chipset.refreshrate;
|
|
|
|
AMIGA.events.calc_vsynctimebase(this.vblank_hz);
|
|
|
|
if (AMIGA.config.audio.enabled && AMIGA.config.audio.mode > 0)
|
|
AMIGA.audio.calc_sample_evtime(this.vblank_hz, (bplcon0 & 4) ? -1 : this.lof_store, this.is_linetoggle());
|
|
};
|
|
|
|
this.compute_framesync = function () {
|
|
var islace = interlace_seen ? 1 : 0;
|
|
var isntsc = (beamcon0 & 0x20) ? 0 : 1;
|
|
|
|
interlace_changed = 0;
|
|
gfxvidinfo.drawbuffer.inxoffset = -1;
|
|
gfxvidinfo.drawbuffer.inyoffset = -1;
|
|
|
|
if (beamcon0 & 0x80) {
|
|
//var res = GET_RES_AGNUS(bplcon0);
|
|
//var vres = islace ? 1 : 0;
|
|
var res2, vres2;
|
|
|
|
res2 = AMIGA.config.video.hresolution;
|
|
if (doublescan > 0)
|
|
res2++;
|
|
if (res2 > RES_MAX)
|
|
res2 = RES_MAX;
|
|
|
|
vres2 = AMIGA.config.video.vresolution;
|
|
if (doublescan > 0 && !islace)
|
|
vres2--;
|
|
|
|
if (vres2 < 0)
|
|
vres2 = 0;
|
|
if (vres2 > VRES_QUAD)
|
|
vres2 = VRES_QUAD;
|
|
|
|
var start = this.hbstrt;
|
|
var stop = this.hbstop;
|
|
|
|
gfxvidinfo.drawbuffer.inwidth = (((start > stop ? (this.maxhpos - (this.maxhpos - start + stop)) : (this.maxhpos - (stop - start) + 2)) * 2) << res2);
|
|
gfxvidinfo.drawbuffer.inxoffset = ((stop + 1) & ~1) * 2;
|
|
|
|
gfxvidinfo.drawbuffer.extrawidth = 0;
|
|
gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth;
|
|
|
|
gfxvidinfo.drawbuffer.inheight = (this.maxvpos - minfirstline) << vres2;
|
|
gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight;
|
|
} else {
|
|
gfxvidinfo.drawbuffer.inwidth = AMIGA_WIDTH_MAX << AMIGA.config.video.hresolution;
|
|
gfxvidinfo.drawbuffer.extrawidth = AMIGA.config.video.extrawidth ? AMIGA.config.video.extrawidth : -1;
|
|
gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth;
|
|
gfxvidinfo.drawbuffer.inheight = (this.maxvpos_nom - minfirstline + 1) << AMIGA.config.video.vresolution;
|
|
gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight;
|
|
}
|
|
|
|
if (gfxvidinfo.drawbuffer.inwidth > gfxvidinfo.drawbuffer.width_allocated)
|
|
gfxvidinfo.drawbuffer.inwidth = gfxvidinfo.drawbuffer.width_allocated;
|
|
if (gfxvidinfo.drawbuffer.inwidth2 > gfxvidinfo.drawbuffer.width_allocated)
|
|
gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.width_allocated;
|
|
|
|
if (gfxvidinfo.drawbuffer.inheight > gfxvidinfo.drawbuffer.height_allocated)
|
|
gfxvidinfo.drawbuffer.inheight = gfxvidinfo.drawbuffer.height_allocated;
|
|
if (gfxvidinfo.drawbuffer.inheight2 > gfxvidinfo.drawbuffer.height_allocated)
|
|
gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.height_allocated;
|
|
|
|
gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.inwidth;
|
|
gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.inheight;
|
|
|
|
if (gfxvidinfo.drawbuffer.outwidth > gfxvidinfo.drawbuffer.width_allocated)
|
|
gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.width_allocated;
|
|
|
|
if (gfxvidinfo.drawbuffer.outheight > gfxvidinfo.drawbuffer.height_allocated)
|
|
gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.height_allocated;
|
|
|
|
//if (target_graphics_buffer_update()) this.reset_drawing();
|
|
|
|
for (var i = 0; i < 2 * (MAXVPOS + 2) + 1; i++) //memset (line_decisions, 0, sizeof line_decisions);
|
|
line_decisions[i].clr();
|
|
|
|
this.compute_vsynctime();
|
|
|
|
BUG.info('%s mode%s%s V=%.4fHz H=%.4fHz (%dx%d+%d)',
|
|
isntsc ? 'NTSC' : 'PAL',
|
|
islace ? ' lace' : '',
|
|
doublescan > 0 ? ' dblscan' : '',
|
|
this.vblank_hz,
|
|
(AMIGA.config.video.ntsc ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (this.maxhpos + (this.is_linetoggle() ? 0.5 : 0)),
|
|
this.maxhpos, this.maxvpos, this.lof_store ? 1 : 0
|
|
);
|
|
};
|
|
|
|
this.init_hz = function (fullinit) {
|
|
var isntsc, islace;
|
|
var odbl = doublescan, omaxvpos = this.maxvpos;
|
|
var hzc = 0;
|
|
|
|
if (fullinit)
|
|
this.vpos_count = 0;
|
|
|
|
this.vpos_count_diff = this.vpos_count;
|
|
|
|
doublescan = 0;
|
|
//programmedmode = false;
|
|
if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0))
|
|
hzc = 1;
|
|
if (beamcon0 != new_beamcon0) {
|
|
BUG.info('init_hz() BEAMCON0 %04x -> %04x', beamcon0, new_beamcon0);
|
|
this.vpos_count_diff = this.vpos_count = 0;
|
|
}
|
|
beamcon0 = new_beamcon0;
|
|
isntsc = (beamcon0 & 0x20) ? 0 : 1;
|
|
islace = (interlace_seen) ? 1 : 0;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
isntsc = AMIGA.config.video.ntsc ? 1 : 0;
|
|
if (!isntsc) {
|
|
this.maxvpos = MAXVPOS_PAL;
|
|
this.maxhpos = MAXHPOS_PAL;
|
|
this.vblank_hz = VBLANK_HZ_PAL;
|
|
minfirstline = VBLANK_ENDLINE_PAL;
|
|
sprite_vblank_endline = VBLANK_SPRITE_PAL;
|
|
equ_vblank_endline = EQU_ENDLINE_PAL;
|
|
equ_vblank_toggle = true;
|
|
} else {
|
|
this.maxvpos = MAXVPOS_NTSC;
|
|
this.maxhpos = MAXHPOS_NTSC;
|
|
this.vblank_hz = VBLANK_HZ_NTSC;
|
|
minfirstline = VBLANK_ENDLINE_NTSC;
|
|
sprite_vblank_endline = VBLANK_SPRITE_NTSC;
|
|
equ_vblank_endline = EQU_ENDLINE_NTSC;
|
|
equ_vblank_toggle = false;
|
|
}
|
|
// long/short field refresh rate adjustment
|
|
//this.vblank_hz >>= (AMIGA.config.video.framerate > 1 ? 1 : 0);
|
|
this.vblank_hz = this.vblank_hz * (this.maxvpos * 2 + 1) / ((this.maxvpos + this.lof_current) * 2);
|
|
|
|
this.maxvpos_nom = this.maxvpos;
|
|
if (this.vpos_count > 0) {
|
|
BUG.info('init_hz() poked VPOSW at %d', this.vpos_count);
|
|
// we come here if this.vpos_count != this.maxvpos and beamcon0 didn't change (someone poked VPOSW)
|
|
if (this.vpos_count < 10)
|
|
this.vpos_count = 10;
|
|
this.vblank_hz = (isntsc ? 15734 : 15625) / this.vpos_count;
|
|
this.maxvpos_nom = this.vpos_count - (this.lof_current ? 1 : 0);
|
|
this.reset_drawing();
|
|
}
|
|
if (beamcon0 & 0x80) {
|
|
// programmable scanrates (ECS Agnus)
|
|
if (this.vtotal >= MAXVPOS)
|
|
this.vtotal = MAXVPOS - 1;
|
|
this.maxvpos = this.vtotal + 1;
|
|
if (this.htotal >= MAXHPOS)
|
|
this.htotal = MAXHPOS - 1;
|
|
this.maxhpos = this.htotal + 1;
|
|
this.vblank_hz = 227 * 312 * 50 / (this.maxvpos * this.maxhpos);
|
|
minfirstline = this.vsstop > this.vbstop ? this.vsstop : this.vbstop;
|
|
if (minfirstline > this.maxvpos / 2)
|
|
minfirstline = this.vsstop > this.vsstop ? this.vbstop : this.vsstop;
|
|
if (minfirstline < 2)
|
|
minfirstline = 2;
|
|
if (minfirstline >= this.maxvpos)
|
|
minfirstline = this.maxvpos - 1;
|
|
sprite_vblank_endline = minfirstline - 2;
|
|
this.maxvpos_nom = this.maxvpos;
|
|
equ_vblank_endline = -1;
|
|
doublescan = this.htotal <= 164 ? 1 : 0;
|
|
//programmedmode = true;
|
|
this.dumpsync();
|
|
hzc = 1;
|
|
}
|
|
if (this.maxvpos_nom >= MAXVPOS)
|
|
this.maxvpos_nom = MAXVPOS;
|
|
if (AMIGA.config.video.scandoubler && doublescan == 0)
|
|
doublescan = -1;
|
|
|
|
if (doublescan != odbl || this.maxvpos != omaxvpos)
|
|
hzc = 1;
|
|
if (this.vblank_hz < 10)
|
|
this.vblank_hz = 10;
|
|
if (this.vblank_hz > 300)
|
|
this.vblank_hz = 300;
|
|
this.maxhpos_short = this.maxhpos;
|
|
if (beamcon0 & 0x80) {
|
|
if (this.hbstrt > this.maxhpos)
|
|
hsyncstartpos = this.hbstrt;
|
|
else
|
|
hsyncstartpos = this.maxhpos + this.hbstrt;
|
|
if (this.hbstop > this.maxhpos)
|
|
hsyncendpos = this.maxhpos - this.hbstop;
|
|
else
|
|
hsyncendpos = this.hbstop;
|
|
} else {
|
|
hsyncstartpos = this.maxhpos_short + 13;
|
|
hsyncendpos = 24;
|
|
}
|
|
|
|
AMIGA.events.eventtab[EV_HSYNC].evtime = AMIGA.events.currcycle + this.maxhpos * CYCLE_UNIT;
|
|
AMIGA.events.eventtab[EV_HSYNC].oldcycles = AMIGA.events.currcycle;
|
|
AMIGA.events.schedule();
|
|
|
|
if (hzc) {
|
|
interlace_seen = islace;
|
|
this.reset_drawing();
|
|
}
|
|
|
|
this.maxvpos_total = (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) ? 2047 : 511;
|
|
if (this.maxvpos_total > MAXVPOS)
|
|
this.maxvpos_total = MAXVPOS;
|
|
/*#ifdef PICASSO96
|
|
if (!p96refresh_active) {
|
|
maxvpos_stored = this.maxvpos;
|
|
maxhpos_stored = this.maxhpos;
|
|
vblank_hz_stored = this.vblank_hz;
|
|
}
|
|
#endif*/
|
|
this.compute_framesync();
|
|
/*#ifdef PICASSO96
|
|
init_hz_p96 ();
|
|
#endif*/
|
|
if (fullinit)
|
|
this.vpos_count_diff = this.maxvpos_nom;
|
|
};
|
|
|
|
this.BPLxPTH = function (hpos, v, num) {
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
bplpt[num] = ((v << 16) | (bplpt[num] & 0xffff)) >>> 0;
|
|
bplptx[num] = ((v << 16) | (bplptx[num] & 0xffff)) >>> 0;
|
|
//BUG.info('%d:%d:BPL%dPTH %08X', hpos, this.vpos, num, bplpt[num]);
|
|
};
|
|
|
|
this.BPLxPTL = function (hpos, v, num) {
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
//if (AMIGA.copper.access && this.is_bitplane_dma(hpos + 1) == num + 1) return;
|
|
|
|
bplpt[num] = ((bplpt[num] & 0xffff0000) | (v & 0xfffe)) >>> 0;
|
|
bplptx[num] = ((bplptx[num] & 0xffff0000) | (v & 0xfffe)) >>> 0;
|
|
//BUG.info('%d:%d:BPL%dPTL %08X', hpos, this.vpos, num, bplpt[num]);
|
|
};
|
|
|
|
this.BPLxDAT = function (hpos, v, num) {
|
|
if (num == 0 && hpos >= 7) {
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
}
|
|
bplxdat[num] = v;
|
|
if (num == 0 && hpos >= 7) {
|
|
bpl1dat_written = true;
|
|
bpl1dat_written_at_least_once = true;
|
|
if (thisline_decision.plfleft < 0) {
|
|
thisline_decision.plfleft = hpos & ~3;
|
|
this.reset_bpl_vars();
|
|
this.compute_delay_offset();
|
|
}
|
|
this.update_bpldats(hpos);
|
|
}
|
|
};
|
|
|
|
this.BPLCON0_Denise = function (hpos, v, immediate) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE))
|
|
v &= ~0x00F1;
|
|
else if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v &= ~0x00B0;
|
|
v &= ~(0x0200 | 0x0100 | 0x0080 | 0x0020);
|
|
/*#if SPRBORDER
|
|
v |= 1;
|
|
#endif*/
|
|
if (bplcon0_d == v)
|
|
return;
|
|
|
|
bplcon0_dd = -1;
|
|
if (is_ehb(bplcon0_d, bplcon2))
|
|
v |= 0x80;
|
|
|
|
if (immediate)
|
|
this.record_register_change(hpos, 0x100, v);
|
|
else
|
|
this.record_register_change(hpos, 0x100, (bplcon0_d & ~(0x800 | 0x400 | 0x80)) | (v & (0x0800 | 0x400 | 0x80 | 0x01)));
|
|
|
|
bplcon0_d = v & ~0x80;
|
|
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) {
|
|
this.decide_sprites(hpos);
|
|
sprres = expand_sprres(v, bplcon3);
|
|
}
|
|
if (thisline_decision.plfleft < 0)
|
|
this.update_denise(hpos);
|
|
};
|
|
|
|
this.BPLCON0 = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE))
|
|
v &= ~0x00F1;
|
|
else if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v &= ~0x00B0;
|
|
v &= ~(0x0080 | 0x0020);
|
|
|
|
/*#if SPRBORDER
|
|
v |= 1;
|
|
#endif*/
|
|
if (bplcon0 == v)
|
|
return;
|
|
|
|
if (!this.issyncstopped()) {
|
|
vpos_previous = this.vpos;
|
|
hpos_previous = hpos;
|
|
}
|
|
|
|
if ((bplcon0 & 4) != (v & 4))
|
|
this.checklacecount((v & 4) != 0);
|
|
|
|
bplcon0 = v;
|
|
|
|
this.bpldmainitdelay(hpos);
|
|
|
|
if (thisline_decision.plfleft < 0)
|
|
this.BPLCON0_Denise(hpos, v, true);
|
|
};
|
|
|
|
this.BPLCON1 = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v &= 0xff;
|
|
if (bplcon1 == v)
|
|
return;
|
|
ddf_change = this.vpos;
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
bplcon1_hpos = hpos;
|
|
bplcon1 = v;
|
|
};
|
|
|
|
this.BPLCON2 = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v &= 0x7f;
|
|
if (bplcon2 == v)
|
|
return;
|
|
this.decide_line(hpos);
|
|
bplcon2 = v;
|
|
this.record_register_change(hpos, 0x104, v);
|
|
};
|
|
|
|
this.BPLCON3 = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE))
|
|
return;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) {
|
|
v &= 0x003f;
|
|
v |= 0x0c00;
|
|
}
|
|
/*#if SPRBORDER
|
|
v |= 2;
|
|
#endif*/
|
|
if (bplcon3 == v)
|
|
return;
|
|
this.decide_line(hpos);
|
|
this.decide_sprites(hpos);
|
|
bplcon3 = v;
|
|
sprres = expand_sprres(bplcon0, bplcon3);
|
|
this.record_register_change(hpos, 0x106, v);
|
|
};
|
|
|
|
/*#ifdef AGA
|
|
this.BPLCON4 = function(hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
return;
|
|
if (bplcon4 == v)
|
|
return;
|
|
this.decide_line(hpos);
|
|
bplcon4 = v;
|
|
this.record_register_change(hpos, 0x10c, v);
|
|
}
|
|
#endif*/
|
|
|
|
function castWord(v) { return (v & 0x8000) ? (v - 0x10000) : v; }
|
|
|
|
this.BPL1MOD = function (hpos, v) {
|
|
v &= ~1;
|
|
if (bpl1mod == castWord(v))
|
|
return;
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
bpl1mod = castWord(v);
|
|
};
|
|
|
|
this.BPL2MOD = function (hpos, v) {
|
|
v &= ~1;
|
|
if (bpl2mod == castWord(v))
|
|
return;
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
bpl2mod = castWord(v);
|
|
};
|
|
|
|
this.calcdiw = function () {
|
|
var hstrt = diwstrt & 0xFF;
|
|
var hstop = diwstop & 0xFF;
|
|
var vstrt = diwstrt >> 8;
|
|
var vstop = diwstop >> 8;
|
|
|
|
// vertical in ECS Agnus
|
|
if (diwhigh_written && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) {
|
|
vstrt |= (diwhigh & 7) << 8;
|
|
vstop |= ((diwhigh >> 8) & 7) << 8;
|
|
} else {
|
|
if ((vstop & 0x80) == 0)
|
|
vstop |= 0x100;
|
|
}
|
|
// horizontal in ECS Denise
|
|
if (diwhigh_written && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) {
|
|
hstrt |= ((diwhigh >> 5) & 1) << 8;
|
|
hstop |= ((diwhigh >> 13) & 1) << 8;
|
|
} else {
|
|
hstop += 0x100;
|
|
}
|
|
|
|
diw_hstrt = hstrt;
|
|
diw_hstop = hstop;
|
|
|
|
diwfirstword = coord_diw_to_window_x(hstrt);
|
|
diwlastword = coord_diw_to_window_x(hstop);
|
|
if (diwfirstword >= diwlastword) {
|
|
diwfirstword = 0;
|
|
diwlastword = max_diwlastword();
|
|
}
|
|
if (diwfirstword < 0)
|
|
diwfirstword = 0;
|
|
|
|
plffirstline = vstrt;
|
|
plflastline = vstop;
|
|
|
|
plfstrt = ddfstrt;
|
|
plfstop = ddfstop;
|
|
/* probably not the correct place.. should use plf_state instead */
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) {
|
|
/* ECS/AGA and ddfstop > maxhpos == always-on display */
|
|
if (plfstop > this.maxhpos)
|
|
plfstrt = 0;
|
|
if (plfstrt < HARD_DDF_START)
|
|
plfstrt = HARD_DDF_START;
|
|
plfstrt_start = plfstrt - 4;
|
|
} else {
|
|
/* OCS and ddfstrt >= ddfstop == ddfstop = max */
|
|
if (plfstrt >= plfstop && plfstrt >= HARD_DDF_START)
|
|
plfstop = 0xff;
|
|
plfstrt_start = HARD_DDF_START - 2;
|
|
}
|
|
diw_change = 2;
|
|
//console.log('calcdiw', hstrt,hstop,vstrt,vstop, plfstrt,plfstop);
|
|
};
|
|
|
|
this.DIWSTRT = function (hpos, v) {
|
|
if (diwstrt == v && !diwhigh_written)
|
|
return;
|
|
this.decide_diw(hpos);
|
|
this.decide_line(hpos);
|
|
diwhigh_written = false;
|
|
diwstrt = v;
|
|
this.calcdiw();
|
|
};
|
|
|
|
this.DIWSTOP = function (hpos, v) {
|
|
if (diwstop == v && !diwhigh_written)
|
|
return;
|
|
this.decide_diw(hpos);
|
|
this.decide_line(hpos);
|
|
diwhigh_written = false;
|
|
diwstop = v;
|
|
this.calcdiw();
|
|
};
|
|
|
|
this.DIWHIGH = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & (CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS)))
|
|
return;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800);
|
|
v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040);
|
|
if (diwhigh_written && diwhigh == v)
|
|
return;
|
|
this.decide_line(hpos);
|
|
diwhigh_written = true;
|
|
diwhigh = v;
|
|
this.calcdiw();
|
|
};
|
|
|
|
this.DDFSTRT = function (hpos, v) {
|
|
v &= 0xfe;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
v &= 0xfc;
|
|
if (ddfstrt == v && hpos + 2 != ddfstrt)
|
|
return;
|
|
ddf_change = this.vpos;
|
|
this.decide_line(hpos);
|
|
ddfstrt_old_hpos = hpos;
|
|
ddfstrt = v;
|
|
this.calcdiw();
|
|
/*if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
|
|
static int last_warned;
|
|
last_warned = (last_warned + 1) & 4095;
|
|
if (last_warned == 0) BUG.info('WARNING! Very strange DDF values (%x %x).', ddfstrt, ddfstop);
|
|
}*/
|
|
};
|
|
|
|
this.DDFSTOP = function (hpos, v) {
|
|
v &= 0xfe;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
v &= 0xfc;
|
|
if (ddfstop == v && hpos + 2 != ddfstop)
|
|
return;
|
|
ddf_change = this.vpos;
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
ddfstop = v;
|
|
this.calcdiw();
|
|
if (fetch_state != FETCH_NOT_STARTED)
|
|
this.estimate_last_fetch_cycle(hpos);
|
|
/*if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
|
|
static int last_warned;
|
|
if (last_warned == 0) BUG.info('WARNING! Very strange DDF values (%x).', ddfstop);
|
|
last_warned = (last_warned + 1) & 4095;
|
|
}*/
|
|
};
|
|
|
|
this.FMODE = function (hpos, v) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
|
|
v = 0;
|
|
v &= 0xC00F;
|
|
if (fmode == v)
|
|
return;
|
|
ddf_change = this.vpos;
|
|
fmode = v;
|
|
sprite_width = GET_SPRITEWIDTH(fmode);
|
|
this.bpldmainitdelay(hpos);
|
|
};
|
|
|
|
this.checkautoscalecol0 = function () {
|
|
if (!AMIGA.copper.access || this.vpos < 20 || this.isbrdblank(-1, bplcon0, bplcon3))
|
|
return;
|
|
// autoscale if copper changes COLOR00 on top or bottom of screen
|
|
if (this.vpos >= minfirstline) {
|
|
var vpos2 = autoscale_bordercolors ? minfirstline : this.vpos;
|
|
if (first_planes_vpos == 0)
|
|
first_planes_vpos = vpos2 - 2;
|
|
if (plffirstline_total == this.current_maxvpos())
|
|
plffirstline_total = vpos2 - 2;
|
|
if (vpos2 > last_planes_vpos || vpos2 > plflastline_total)
|
|
plflastline_total = last_planes_vpos = vpos2 + 3;
|
|
autoscale_bordercolors = 0;
|
|
} else
|
|
autoscale_bordercolors++;
|
|
};
|
|
|
|
this.COLOR_WRITE = function (hpos, v, num) {
|
|
//var colzero = false;
|
|
v &= 0xFFF;
|
|
/*#ifdef AGA
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
int r,g,b;
|
|
int cr,cg,cb;
|
|
int colreg;
|
|
uae_u32 cval;
|
|
|
|
if (bplcon2 & 0x0100)
|
|
return;
|
|
|
|
colreg = ((bplcon3 >> 13) & 7) * 32 + num;
|
|
r = (v & 0xF00) >> 8;
|
|
g = (v & 0xF0) >> 4;
|
|
b = (v & 0xF) >> 0;
|
|
cr = current_colors.color_regs_aga[colreg] >> 16;
|
|
cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
|
|
cb = current_colors.color_regs_aga[colreg] & 0xFF;
|
|
|
|
if (bplcon3 & 0x200) {
|
|
cr &= 0xF0; cr |= r;
|
|
cg &= 0xF0; cg |= g;
|
|
cb &= 0xF0; cb |= b;
|
|
} else {
|
|
cr = r + (r << 4);
|
|
cg = g + (g << 4);
|
|
cb = b + (b << 4);
|
|
color_regs_aga_genlock[colreg] = v >> 15;
|
|
}
|
|
cval = (cr << 16) | (cg << 8) | cb;
|
|
if (cval && colreg == 0)
|
|
colzero = true;
|
|
|
|
if (cval == current_colors.color_regs_aga[colreg])
|
|
return;
|
|
|
|
if (colreg == 0)
|
|
this.checkautoscalecol0 ();
|
|
|
|
//Call this with the old table still intact.
|
|
this.record_color_change (hpos, colreg, cval);
|
|
remembered_color_entry = -1;
|
|
current_colors.color_regs_aga[colreg] = cval;
|
|
current_colors.acolors[colreg] = getxcolor (cval);
|
|
|
|
} else {
|
|
#endif*/
|
|
//if (num && v == 0) colzero = true;
|
|
|
|
if (!FAST_COLORS) {
|
|
if (current_colors.color_regs_ecs[num] == v)
|
|
return;
|
|
}
|
|
if (num == 0)
|
|
this.checkautoscalecol0();
|
|
|
|
if (!FAST_COLORS) {
|
|
this.record_color_change(hpos, num, v);
|
|
remembered_color_entry = -1;
|
|
}
|
|
current_colors.color_regs_ecs[num] = v;
|
|
current_colors.acolors[num] = getxcolor(v);
|
|
/*#ifdef AGA
|
|
}
|
|
#endif*/
|
|
};
|
|
|
|
/*this.islightpentriggered = function() {
|
|
if (beamcon0 & 0x2000) // LPENDIS
|
|
return 0;
|
|
return lightpen_triggered > 0;
|
|
}
|
|
this.GETVPOS = function() {
|
|
return this.islightpentriggered() ? vpos_lpen : (this.issyncstopped() ? vpos_previous : this.vpos);
|
|
}
|
|
this.GETHPOS = function() {
|
|
return this.islightpentriggered() ? hpos_lpen : (this.issyncstopped() ? hpos_previous : this.hpos());
|
|
}*/
|
|
this.issyncstopped = function () {
|
|
return (bplcon0 & 2) != 0 && !AMIGA.config.chipset.genlock;
|
|
};
|
|
this.GETVPOS = function () {
|
|
return this.issyncstopped() ? vpos_previous : this.vpos;
|
|
};
|
|
this.GETHPOS = function () {
|
|
return this.issyncstopped() ? hpos_previous : this.hpos();
|
|
};
|
|
|
|
const HPOS_OFFSET = 3; //(currprefs.cpu_model < 68020 ? 3 : 0)
|
|
|
|
this.VPOSR = function () {
|
|
var vp = this.GETVPOS();
|
|
var hp = this.GETHPOS();
|
|
//var vp = this.vpos;
|
|
//var hp = this.hpos();
|
|
var csbit = 0;
|
|
|
|
if (hp + HPOS_OFFSET >= this.maxhpos) {
|
|
vp++;
|
|
if (vp >= this.maxvpos + this.lof_store)
|
|
vp = 0;
|
|
}
|
|
vp = (vp >> 8) & 7;
|
|
|
|
if (AMIGA.config.chipset.agnus_rev >= 0)
|
|
csbit |= AMIGA.config.chipset.agnus_rev << 8;
|
|
else {
|
|
/*#ifdef AGA
|
|
csbit |= (AMIGA.config.chipset.mask & CSMASK_AGA) ? 0x2300 : 0;
|
|
#endif*/
|
|
csbit |= (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
|
|
if (AMIGA.mem.chip.size > 1024 * 1024 && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
csbit |= 0x2100;
|
|
if (AMIGA.config.video.ntsc)
|
|
csbit |= 0x1000;
|
|
}
|
|
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
vp &= 1;
|
|
vp = vp | (this.lof_store ? 0x8000 : 0) | csbit;
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)
|
|
vp |= this.lol ? 0x80 : 0;
|
|
|
|
//BUG.info('VPOSR $%x', vp);
|
|
return vp;
|
|
};
|
|
|
|
this.VPOSW = function (v) {
|
|
if (this.lof_store != ((v & 0x8000) ? 1 : 0)) {
|
|
this.lof_store = (v & 0x8000) ? 1 : 0;
|
|
this.lof_changing = this.lof_store ? 1 : -1;
|
|
}
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) {
|
|
this.lol = (v & 0x0080) ? 1 : 0;
|
|
if (!this.is_linetoggle())
|
|
this.lol = 0;
|
|
}
|
|
if (this.lof_changing)
|
|
return;
|
|
|
|
v &= 7;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
v &= 1;
|
|
|
|
this.vpos &= 0x00ff;
|
|
this.vpos |= v << 8;
|
|
//BUG.info('VPOSW $%x', this.vpos);
|
|
};
|
|
|
|
this.VHPOSW = function (v) {
|
|
this.vpos &= 0xff00;
|
|
this.vpos |= v >> 8;
|
|
//BUG.info('VHPOSW %x %d', v, this.vpos);
|
|
};
|
|
|
|
this.VHPOSR = function () {
|
|
var vp = this.GETVPOS();
|
|
var hp = this.GETHPOS();
|
|
//var vp = this.vpos;
|
|
//var hp = this.hpos();
|
|
|
|
hp += HPOS_OFFSET;
|
|
if (hp >= this.maxhpos) {
|
|
hp -= this.maxhpos;
|
|
vp++;
|
|
if (vp >= this.maxvpos + this.lof_store)
|
|
vp = 0;
|
|
}
|
|
if (HPOS_OFFSET) {
|
|
hp += 1;
|
|
if (hp >= this.maxhpos)
|
|
hp -= this.maxhpos;
|
|
}
|
|
vp &= 0xff;
|
|
hp &= 0xff;
|
|
|
|
vp <<= 8;
|
|
vp |= hp;
|
|
|
|
//BUG.info('VHPOSR $%x', vp);
|
|
return vp;
|
|
};
|
|
|
|
this.BEAMCON0 = function (v) {
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE))
|
|
v &= 0x20;
|
|
|
|
if (v != new_beamcon0) {
|
|
new_beamcon0 = v;
|
|
if (v & ~0x20)
|
|
BUG.info('BEAMCON0() $%04x written.', v);
|
|
}
|
|
}
|
|
};
|
|
|
|
this.DENISEID = function () {
|
|
if (AMIGA.config.chipset.denise_rev >= 0)
|
|
return [0, AMIGA.config.chipset.denise_rev];
|
|
/*#ifdef AGA
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
if (currprefs.cs_ide == IDE_A4000) return [0, 0xFCF8];
|
|
return [0, 0x00F8];
|
|
}
|
|
#endif*/
|
|
if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)
|
|
return [0, 0xFFFC];
|
|
|
|
if (AMIGA.config.cpu.model == 68000 && AMIGA.config.cpu.compatible)
|
|
return [1, 0xFFFF];
|
|
return [0, 0xFFFF];
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.is_bitplane_dma = function (hpos) {
|
|
if (hpos < plfstrt)
|
|
return 0;
|
|
if ((plf_state == PLF_END && hpos >= thisline_decision.plfright) || hpos >= estimated_last_fetch_cycle)
|
|
return 0;
|
|
|
|
return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
|
|
};
|
|
|
|
this.update_denise = function (hpos) {
|
|
toscr_res = GET_RES_DENISE(bplcon0_d);
|
|
if (bplcon0_dd != bplcon0_d) {
|
|
this.record_color_change2(hpos, 0x100 + 0x1000, bplcon0_d);
|
|
bplcon0_dd = bplcon0_d;
|
|
}
|
|
toscr_nr_planes = GET_PLANES(bplcon0_d);
|
|
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_AGA) && bplcon0_res == 0 && bplcon0_planes == 7) { //OCS 7 planes
|
|
if (toscr_nr_planes2 < 6)
|
|
toscr_nr_planes2 = 6;
|
|
} else
|
|
toscr_nr_planes2 = toscr_nr_planes;
|
|
};
|
|
|
|
this.setup_fmodes = function (hpos) {
|
|
switch (fmode & 3) {
|
|
case 0:
|
|
fetchmode = 0;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
fetchmode = 1;
|
|
break;
|
|
case 3:
|
|
fetchmode = 2;
|
|
break;
|
|
}
|
|
badmode = GET_RES_AGNUS(bplcon0) != GET_RES_DENISE(bplcon0);
|
|
bplcon0_res = GET_RES_AGNUS(bplcon0);
|
|
bplcon0_planes = GET_PLANES(bplcon0);
|
|
bplcon0_planes_limit = GET_PLANES_LIMIT(bplcon0);
|
|
fetchunit = fetchunits[fetchmode * 4 + bplcon0_res];
|
|
fetchunit_mask = fetchunit - 1;
|
|
fetchstart_shift = fetchstarts[fetchmode * 4 + bplcon0_res];
|
|
fetchstart = 1 << fetchstart_shift;
|
|
fetchstart_mask = fetchstart - 1;
|
|
fm_maxplane_shift = fm_maxplanes[fetchmode * 4 + bplcon0_res];
|
|
fm_maxplane = 1 << fm_maxplane_shift;
|
|
fetch_modulo_cycle = fetchunit - fetchstart;
|
|
curr_diagram = cycle_diagram_table[fetchmode][bplcon0_res][bplcon0_planes_limit];
|
|
this.estimate_last_fetch_cycle(hpos);
|
|
bpldmasetuphpos = -1;
|
|
bpldmasetupphase = 0;
|
|
ddf_change = this.vpos;
|
|
};
|
|
|
|
this.maybe_setup_fmodes = function (hpos) {
|
|
switch (bpldmasetupphase) {
|
|
case 0:
|
|
this.BPLCON0_Denise(hpos, bplcon0, false);
|
|
bpldmasetupphase++;
|
|
bpldmasetuphpos += (4 + (bplcon0_planes == 8 ? 1 : 0)) - BPLCON_DENISE_DELAY;
|
|
break;
|
|
case 1:
|
|
this.setup_fmodes(hpos);
|
|
break;
|
|
}
|
|
};
|
|
|
|
this.maybe_check = function (hpos) {
|
|
if (bpldmasetuphpos > 0 && hpos >= bpldmasetuphpos)
|
|
this.maybe_setup_fmodes(hpos);
|
|
};
|
|
|
|
this.compute_delay_offset = function () {
|
|
delayoffset = (16 << fetchmode) - (((plfstrt - HARD_DDF_START) & fetchstart_mask) << 1);
|
|
};
|
|
|
|
this.compute_toscr_delay_1 = function (con1) {
|
|
var delay1 = (con1 & 0x0f) | ((con1 & 0x0c00) >> 6);
|
|
var delay2 = ((con1 >> 4) & 0x0f) | (((con1 >> 4) & 0x0c00) >> 6);
|
|
var shdelay1 = (con1 >> 12) & 3;
|
|
var shdelay2 = (con1 >> 8) & 3;
|
|
var delaymask;
|
|
var fetchwidth = 16 << fetchmode;
|
|
|
|
delay1 += delayoffset;
|
|
delay2 += delayoffset;
|
|
delaymask = (fetchwidth - 1) >> toscr_res;
|
|
toscr_delay1 = (delay1 & delaymask) << toscr_res;
|
|
toscr_delay1 |= shdelay1 >> (RES_MAX - toscr_res);
|
|
toscr_delay2 = (delay2 & delaymask) << toscr_res;
|
|
toscr_delay2 |= shdelay2 >> (RES_MAX - toscr_res);
|
|
};
|
|
|
|
this.compute_toscr_delay = function (hpos, con1) {
|
|
this.update_denise(hpos);
|
|
this.compute_toscr_delay_1(con1);
|
|
};
|
|
|
|
this.update_toscr_planes = function () {
|
|
if (toscr_nr_planes2 > thisline_decision.nr_planes) {
|
|
for (var j = thisline_decision.nr_planes; j < toscr_nr_planes2; j++) {
|
|
if (!thisline_changed) {
|
|
for (var i = 0; i < out_offs; i++) {
|
|
if (line_data[next_lineno][j][i]) {
|
|
thisline_changed = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < out_offs; i++) line_data[next_lineno][j][i] = 0; //memset(ptr, 0, out_offs * 4);
|
|
}
|
|
thisline_decision.nr_planes = toscr_nr_planes2;
|
|
}
|
|
};
|
|
|
|
this.maybe_first_bpl1dat = function (hpos) {
|
|
if (thisline_decision.plfleft >= 0) {
|
|
if (plfleft_real < 0) {
|
|
for (var i = 0; i < MAX_PLANES; i++) {
|
|
todisplay[i][0] = 0;
|
|
/*#ifdef AGA
|
|
todisplay[i][1] = 0;
|
|
todisplay[i][2] = 0;
|
|
todisplay[i][3] = 0;
|
|
#endif*/
|
|
}
|
|
plfleft_real = hpos;
|
|
bpl1dat_early = true;
|
|
}
|
|
} else {
|
|
plfleft_real = thisline_decision.plfleft = hpos;
|
|
this.compute_delay_offset();
|
|
}
|
|
};
|
|
|
|
this.checklacecount = function (lace) {
|
|
if (lace === null)
|
|
lace = (bplcon0 & 4) != 0;
|
|
|
|
if (!interlace_changed) {
|
|
if (nlace_cnt >= NLACE_CNT_NEEDED && lace) {
|
|
lof_togglecnt_lace = LOF_TOGGLES_NEEDED;
|
|
lof_togglecnt_nlace = 0;
|
|
//BUG.info('immediate lace');
|
|
nlace_cnt = 0;
|
|
} else if (nlace_cnt <= -NLACE_CNT_NEEDED && !lace) {
|
|
lof_togglecnt_nlace = LOF_TOGGLES_NEEDED;
|
|
lof_togglecnt_lace = 0;
|
|
//BUG.info('immediate nlace');
|
|
nlace_cnt = 0;
|
|
}
|
|
}
|
|
if (lace) {
|
|
if (nlace_cnt > 0)
|
|
nlace_cnt = 0;
|
|
nlace_cnt--;
|
|
if (nlace_cnt < -NLACE_CNT_NEEDED * 2)
|
|
nlace_cnt = -NLACE_CNT_NEEDED * 2;
|
|
} else if (!lace) {
|
|
if (nlace_cnt < 0)
|
|
nlace_cnt = 0;
|
|
nlace_cnt++;
|
|
if (nlace_cnt > NLACE_CNT_NEEDED * 2)
|
|
nlace_cnt = NLACE_CNT_NEEDED * 2;
|
|
}
|
|
};
|
|
|
|
var dumpcnt = 100;
|
|
this.dumpsync = function () {
|
|
if (dumpcnt < 0)
|
|
return;
|
|
dumpcnt--;
|
|
BUG.info('BEAMCON0=%04X VTOTAL=%04X HTOTAL=%04X', new_beamcon0, this.vtotal, this.htotal);
|
|
BUG.info(' HSSTOP=%04X HBSTRT=%04X HBSTOP=%04X', this.hsstop, this.hbstrt, this.hbstop);
|
|
BUG.info(' VSSTOP=%04X VBSTRT=%04X VBSTOP=%04X', this.vsstop, this.vbstrt, this.vbstop);
|
|
BUG.info(' HSSTRT=%04X VSSTRT=%04X HCENTER=%04X', this.hsstrt, this.vsstrt, this.hcenter);
|
|
};
|
|
|
|
this.varsync = function () {
|
|
//console.log('varsync()');
|
|
if (!CUSTOM_SIMPLE) {
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
return;
|
|
if (!(beamcon0 & 0x80))
|
|
return;
|
|
this.vpos_count = 0;
|
|
//this.dumpsync();
|
|
}
|
|
};
|
|
|
|
this.count_frame = function () {
|
|
if (++this.framecnt >= AMIGA.config.video.framerate)
|
|
this.framecnt = 0;
|
|
};
|
|
|
|
this.vsync_handle_redraw = function () { //(long_frame, lof_changed, bplcon0p, bplcon3p)
|
|
last_redraw_point++;
|
|
if (this.lof_changed || this.lof_store || interlace_seen <= 0 || doublescan < 0 || last_redraw_point >= 2) {
|
|
last_redraw_point = 0;
|
|
|
|
if (this.framecnt == 0)
|
|
this.finish_drawing_frame();
|
|
/*#if 0
|
|
if (interlace_seen > 0)
|
|
interlace_seen = -1;
|
|
else if (interlace_seen == -1) {
|
|
interlace_seen = 0;
|
|
if (currprefs.scandoubler && currprefs.vresolution)
|
|
notice_screen_contents_lost ();
|
|
}
|
|
#endif*/
|
|
this.count_frame();
|
|
|
|
if (this.framecnt == 0)
|
|
this.init_drawing_frame();
|
|
}
|
|
};
|
|
|
|
this.init_hardware_frame = function () {
|
|
first_bpl_vpos = -1;
|
|
next_lineno = 0;
|
|
prev_lineno = -1;
|
|
nextline_how = NLN_NORMAL;
|
|
diwstate = DIW_WAITING_START;
|
|
ddfstate = DIW_WAITING_START;
|
|
first_planes_vpos = 0;
|
|
last_planes_vpos = 0;
|
|
diwfirstword_total = max_diwlastword();
|
|
diwlastword_total = 0;
|
|
ddffirstword_total = max_diwlastword();
|
|
ddflastword_total = 0;
|
|
plflastline_total = 0;
|
|
plffirstline_total = this.current_maxvpos();
|
|
autoscale_bordercolors = 0;
|
|
for (var i = 0; i < MAX_SPRITES; i++)
|
|
spr[i].ptxhpos = MAXHPOS;
|
|
};
|
|
|
|
this.init_hardware_for_drawing_frame = function () {
|
|
if (prev_sprite_entries) {
|
|
var first_pixel = prev_sprite_entries[0].first_pixel;
|
|
var npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
|
|
for (var i = 0; i < npixels; i++) spixels[first_pixel + i] = 0; //memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
|
|
for (var i = 0; i < npixels; i++) spixstate[first_pixel + i] = 0; //memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
|
|
}
|
|
prev_next_sprite_entry = next_sprite_entry;
|
|
|
|
next_color_change = 0;
|
|
next_sprite_entry = 0;
|
|
next_color_entry = 0;
|
|
remembered_color_entry = -1;
|
|
|
|
prev_sprite_entries = sprite_entries[current_change_set];
|
|
curr_sprite_entries = sprite_entries[current_change_set ^ 1];
|
|
prev_color_changes = color_changes[current_change_set];
|
|
curr_color_changes = color_changes[current_change_set ^ 1];
|
|
prev_color_tables = color_tables[current_change_set];
|
|
curr_color_tables = color_tables[current_change_set ^ 1];
|
|
|
|
prev_drawinfo = line_drawinfo[current_change_set];
|
|
curr_drawinfo = line_drawinfo[current_change_set ^ 1];
|
|
current_change_set ^= 1;
|
|
|
|
color_src_match = color_dest_match = -1;
|
|
|
|
curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
|
|
next_sprite_forced = 1;
|
|
};
|
|
|
|
this.reset_decisions = function () {
|
|
if (this.nodraw())
|
|
return;
|
|
|
|
plfleft_real = -1;
|
|
toscr_nr_planes = toscr_nr_planes2 = 0;
|
|
|
|
bpl1dat_written = false;
|
|
bpl1dat_written_at_least_once = false;
|
|
bpl1dat_early = false;
|
|
|
|
thisline_decision.bplres = bplcon0_res;
|
|
thisline_decision.nr_planes = 0;
|
|
thisline_decision.plfleft = -1;
|
|
thisline_decision.plflinelen = -1;
|
|
thisline_decision.ham_seen = !!(bplcon0 & 0x800);
|
|
thisline_decision.ehb_seen = !!is_ehb(bplcon0, bplcon2);
|
|
thisline_decision.ham_at_start = !!(bplcon0 & 0x800);
|
|
|
|
thisline_changed = 0;
|
|
thisline_decision.diwfirstword = -1;
|
|
thisline_decision.diwlastword = -1;
|
|
if (hdiwstate == DIW_WAITING_STOP) {
|
|
thisline_decision.diwfirstword = 0;
|
|
if (SMART_UPDATE) {
|
|
if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
|
|
thisline_changed = 1; //MARK_LINE_CHANGED;
|
|
}
|
|
}
|
|
thisline_decision.ctable = -1;
|
|
|
|
curr_drawinfo[next_lineno].first_color_change = next_color_change;
|
|
curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
|
|
|
|
next_sprite_forced = 1;
|
|
last_sprite_point = 0;
|
|
fetch_state = FETCH_NOT_STARTED;
|
|
bplcon1_hpos = -1;
|
|
if (bpldmasetuphpos >= 0) {
|
|
this.BPLCON0_Denise(0, bplcon0, true);
|
|
this.setup_fmodes(0);
|
|
}
|
|
bpldmasetuphpos = -1;
|
|
bpldmasetupphase = 0;
|
|
ddfstrt_old_hpos = -1;
|
|
|
|
if (plf_state > PLF_ACTIVE || (plf_state == PLF_ACTIVE && !(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)))
|
|
plf_state = PLF_IDLE;
|
|
|
|
/*memset (todisplay, 0, sizeof todisplay);
|
|
memset (fetched, 0, sizeof fetched);
|
|
memset (fetched_aga0, 0, sizeof fetched_aga0);
|
|
memset (fetched_aga1, 0, sizeof fetched_aga1);
|
|
memset (outword, 0, sizeof outword);*/
|
|
for (var i = 0; i < MAX_PLANES; i++) {
|
|
for (var j = 0; j < 4; j++)
|
|
todisplay[i][j] = 0;
|
|
|
|
fetched[i] = 0;
|
|
/*#ifdef AGA
|
|
if (AMIGA.config.chipset.mask & CSMASK_AGA) {
|
|
fetched_aga0[i] = 0;
|
|
fetched_aga1[i] = 0;
|
|
}
|
|
#endif*/
|
|
outword[i] = 0;
|
|
}
|
|
|
|
last_decide_line_hpos = -1;
|
|
last_ddf_pix_hpos = -1;
|
|
last_sprite_hpos = -1;
|
|
last_fetch_hpos = -1;
|
|
|
|
thisline_decision.bplcon0 = bplcon0;
|
|
thisline_decision.bplcon2 = bplcon2;
|
|
thisline_decision.bplcon3 = bplcon3;
|
|
/*#ifdef AGA
|
|
thisline_decision.bplcon4 = bplcon4;
|
|
#endif*/
|
|
};
|
|
|
|
this.record_diw_line = function (plfstrt, first, last) {
|
|
if (last > max_diwstop)
|
|
max_diwstop = last;
|
|
if (first < min_diwstart) {
|
|
min_diwstart = first;
|
|
/*
|
|
if (plfstrt * 2 > min_diwstart)
|
|
min_diwstart = plfstrt * 2;
|
|
*/
|
|
}
|
|
};
|
|
|
|
this.sprites_differ = function (dip, dip_old) {
|
|
var this_first = curr_sprite_entries[dip.first_sprite_entry];
|
|
var this_last = curr_sprite_entries[dip.last_sprite_entry];
|
|
var prev_first = prev_sprite_entries[dip_old.first_sprite_entry];
|
|
|
|
if (dip.nr_sprites != dip_old.nr_sprites)
|
|
return 1;
|
|
|
|
if (dip.nr_sprites == 0)
|
|
return 0;
|
|
|
|
/*for (var i = 0; i < dip.nr_sprites; i++) { //FIXME
|
|
if (this_first[i].pos != prev_first[i].pos
|
|
|| this_first[i].max != prev_first[i].max
|
|
|| this_first[i].has_attached != prev_first[i].has_attached)
|
|
return 1;
|
|
}*/
|
|
if (this_first.pos != prev_first.pos || this_first.max != prev_first.max || this_first.has_attached != prev_first.has_attached) //FIX
|
|
return 1;
|
|
|
|
var npixels = this_last.first_pixel + (this_last.max - this_last.pos) - this_first.first_pixel;
|
|
|
|
//if (memcmp (spixels + this_first.first_pixel, spixels + prev_first.first_pixel, npixels * sizeof (uae_u16)) != 0) return 1;
|
|
for (i = 0; i < npixels; i++) {
|
|
if (spixels[this_first.first_pixel + i] != spixels[prev_first.first_pixel + i])
|
|
return 1;
|
|
}
|
|
//if (memcmp (spixstate.bytes + this_first.first_pixel, spixstate.bytes + prev_first.first_pixel, npixels) != 0) return 1;
|
|
for (i = 0; i < npixels; i++) {
|
|
if (spixstate[this_first.first_pixel + i] != spixstate[prev_first.first_pixel + i])
|
|
return 1;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
this.color_changes_differ = function (dip, dip_old) {
|
|
if (dip.nr_color_changes != dip_old.nr_color_changes)
|
|
return 1;
|
|
if (dip.nr_color_changes == 0)
|
|
return 0;
|
|
//if (memcmp(curr_color_changes + dip.first_color_change, prev_color_changes + dip_old.first_color_change, dip.nr_color_changes * sizeof *curr_color_changes) != 0)
|
|
for (i = 0; i < dip.nr_color_changes; i++) {
|
|
if (curr_color_changes[dip.first_color_change + i].cmp(prev_color_changes[dip_old.first_color_change + i]) != 0)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
this.finish_decisions = function () {
|
|
var hpos = this.maxhpos;
|
|
|
|
if (this.nodraw())
|
|
return;
|
|
|
|
this.decide_diw(hpos);
|
|
this.decide_line(hpos);
|
|
this.decide_fetch(hpos);
|
|
|
|
this.record_color_change2(hsyncstartpos, 0xffff, 0);
|
|
if (thisline_decision.plfleft >= 0 && thisline_decision.plflinelen < 0) {
|
|
if (fetch_state != FETCH_NOT_STARTED) {
|
|
BUG.info('finish_decisions() fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d', fetch_state, thisline_decision.plfleft, thisline_decision.plflinelen, this.vpos, hpos);
|
|
Fatal(333, 'finish_decisions() fetch_state != FETCH_NOT_STARTED');
|
|
}
|
|
thisline_decision.plfright = thisline_decision.plfleft;
|
|
thisline_decision.plflinelen = 0;
|
|
thisline_decision.bplres = RES_LORES;
|
|
}
|
|
if (hdiwstate == DIW_WAITING_STOP) {
|
|
thisline_decision.diwlastword = max_diwlastword();
|
|
if (thisline_decision.diwfirstword < 0)
|
|
thisline_decision.diwfirstword = 0;
|
|
}
|
|
if (SMART_UPDATE) {
|
|
if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
|
|
thisline_changed = 1; //MARK_LINE_CHANGED;
|
|
if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
|
|
thisline_changed = 1; //MARK_LINE_CHANGED;
|
|
}
|
|
var dip = curr_drawinfo[next_lineno];
|
|
var dip_old = prev_drawinfo[next_lineno];
|
|
var dp = line_decisions[next_lineno];
|
|
var changed = thisline_changed;
|
|
if (thisline_decision.plfleft >= 0 && thisline_decision.nr_planes > 0)
|
|
this.record_diw_line(thisline_decision.plfleft, diwfirstword, diwlastword);
|
|
|
|
this.decide_sprites(hpos + 1);
|
|
|
|
dip.last_sprite_entry = next_sprite_entry;
|
|
dip.last_color_change = next_color_change;
|
|
|
|
if (thisline_decision.ctable < 0)
|
|
this.remember_ctable();
|
|
|
|
dip.nr_color_changes = next_color_change - dip.first_color_change;
|
|
dip.nr_sprites = next_sprite_entry - dip.first_sprite_entry;
|
|
|
|
if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
|
|
changed = 1;
|
|
if (!changed && this.color_changes_differ(dip, dip_old))
|
|
changed = 1;
|
|
if (!changed && /* bitplane visible in this line OR border sprites enabled */
|
|
(thisline_decision.plfleft >= 0 || ((thisline_decision.bplcon0 & 1) && (thisline_decision.bplcon3 & 0x02) && !(thisline_decision.bplcon3 & 0x20)))
|
|
&& this.sprites_differ(dip, dip_old))
|
|
changed = 1;
|
|
|
|
if (changed) {
|
|
thisline_changed = 1;
|
|
dp.set(thisline_decision); //*dp = thisline_decision;
|
|
} else
|
|
line_decisions[next_lineno].ctable = thisline_decision.ctable;
|
|
|
|
next_color_change += ((HBLANK_OFFSET + 1) >> 1);
|
|
|
|
diw_hcounter += this.maxhpos * 2;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && this.vpos == this.get_equ_vblank_endline() - 1)
|
|
diw_hcounter++;
|
|
if ((AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) || this.vpos > this.get_equ_vblank_endline() || (AMIGA.config.chipset.agnus_dip && this.vpos == 0)) {
|
|
diw_hcounter = this.maxhpos * 2;
|
|
last_hdiw = 1; //2 - 1;
|
|
}
|
|
if (next_color_change >= MAX_REG_CHANGE - 30) {
|
|
BUG.info('ColorChange buffer overflow!');
|
|
next_color_change = 0;
|
|
dip.nr_color_changes = 0;
|
|
dip.first_color_change = 0;
|
|
dip.last_color_change = 0;
|
|
}
|
|
};
|
|
|
|
this.hsync_record_line_state = function (lineno, how, changed) {
|
|
if (this.framecnt != 0)
|
|
return;
|
|
|
|
//changed += ((frame_redraw_necessary ? 1 : 0) + ((lineno >= lightpen_y1 && lineno <= lightpen_y2) ? 1 : 0));
|
|
changed += (frame_redraw_necessary ? 1 : 0);
|
|
|
|
switch (how) {
|
|
case NLN_NORMAL:
|
|
linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE;
|
|
break;
|
|
case NLN_DOUBLED:
|
|
linestate[lineno] = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
|
|
changed += (linestate[lineno + 1] != LINE_REMEMBERED_AS_PREVIOUS ? 1 : 0);
|
|
linestate[lineno + 1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
|
|
break;
|
|
case NLN_NBLACK:
|
|
linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE;
|
|
if (linestate[lineno + 1] != LINE_REMEMBERED_AS_BLACK)
|
|
linestate[lineno + 1] = LINE_BLACK;
|
|
break;
|
|
case NLN_LOWER:
|
|
if (linestate[lineno - 1] == LINE_UNDECIDED)
|
|
linestate[lineno - 1] = LINE_DECIDED; //LINE_BLACK;
|
|
linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE;
|
|
break;
|
|
case NLN_UPPER:
|
|
linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE;
|
|
if (linestate[lineno + 1] == LINE_UNDECIDED
|
|
|| linestate[lineno + 1] == LINE_REMEMBERED_AS_PREVIOUS
|
|
|| linestate[lineno + 1] == LINE_AS_PREVIOUS)
|
|
linestate[lineno + 1] = LINE_DECIDED; //LINE_BLACK;
|
|
break;
|
|
}
|
|
};
|
|
|
|
this.get_equ_vblank_endline = function () {
|
|
return equ_vblank_endline + (equ_vblank_toggle ? (this.lof_current ? 1 : 0) : 0);
|
|
};
|
|
|
|
this.decide_diw = function (hpos) {
|
|
var hdiw = hpos >= this.maxhpos ? this.maxhpos * 2 + 1 : hpos * 2 + 2;
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && this.vpos <= this.get_equ_vblank_endline())
|
|
hdiw = diw_hcounter;
|
|
|
|
hdiw &= 511;
|
|
for (; ;) {
|
|
var lhdiw = hdiw;
|
|
if (last_hdiw > lhdiw)
|
|
lhdiw = 512;
|
|
|
|
if (lhdiw >= diw_hstrt && last_hdiw < diw_hstrt && hdiwstate == DIW_WAITING_START) {
|
|
if (thisline_decision.diwfirstword < 0)
|
|
thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
|
|
hdiwstate = DIW_WAITING_STOP;
|
|
}
|
|
if (lhdiw >= diw_hstop && last_hdiw < diw_hstop && hdiwstate == DIW_WAITING_STOP) {
|
|
if (thisline_decision.diwlastword < 0)
|
|
thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
|
|
hdiwstate = DIW_WAITING_START;
|
|
}
|
|
if (lhdiw != 512)
|
|
break;
|
|
last_hdiw = -1; //0 - 1;
|
|
}
|
|
last_hdiw = hdiw;
|
|
};
|
|
|
|
this.reset_bpl_vars = function (hpos) {
|
|
out_nbits = 0;
|
|
out_offs = 0;
|
|
toscr_nbits = 0;
|
|
thisline_decision.bplres = bplcon0_res;
|
|
};
|
|
|
|
this.start_bpl_dma = function (hpos, hstart) {
|
|
if (first_bpl_vpos < 0)
|
|
first_bpl_vpos = this.vpos;
|
|
|
|
if (this.doflickerfix() && interlace_seen > 0) { //&& !scandoubled_line) {
|
|
for (var i = 0; i < 8; i++) {
|
|
prevbpl[this.lof_current][this.vpos][i] = bplptx[i];
|
|
if (!this.lof_current && (bplcon0 & 4))
|
|
bplpt[i] = prevbpl[1 - this.lof_current][this.vpos][i];
|
|
if (!(bplcon0 & 4) || interlace_seen < 0)
|
|
prevbpl[1 - this.lof_current][this.vpos][i] = prevbpl[this.lof_current][this.vpos][i] = 0;
|
|
}
|
|
}
|
|
plfstrt_sprite = plfstrt;
|
|
fetch_state = FETCH_STARTED;
|
|
fetch_cycle = 0;
|
|
|
|
ddfstate = DIW_WAITING_STOP;
|
|
this.compute_toscr_delay(last_fetch_hpos, bplcon1);
|
|
|
|
if (bpl1dat_written_at_least_once && hstart > last_fetch_hpos) {
|
|
this.update_fetch_x(hstart, fetchmode);
|
|
bpl1dat_written_at_least_once = false;
|
|
} else
|
|
this.reset_bpl_vars();
|
|
/*#if 0
|
|
if (!this.nodraw ()) {
|
|
if (thisline_decision.plfleft >= 0) {
|
|
out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res);
|
|
out_offs = out_nbits >> 5;
|
|
out_nbits &= 31;
|
|
}
|
|
this.update_toscr_planes();
|
|
}
|
|
#endif*/
|
|
last_fetch_hpos = hstart;
|
|
cycle_diagram_shift = hstart;
|
|
};
|
|
|
|
this.maybe_start_bpl_dma = function (hpos) {
|
|
//console.log('maybe_start_bpl_dma', hpos);
|
|
if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))
|
|
return;
|
|
if (fetch_state != FETCH_NOT_STARTED)
|
|
return;
|
|
if (diwstate != DIW_WAITING_STOP)
|
|
return;
|
|
if (hpos <= plfstrt)
|
|
return;
|
|
if (hpos > plfstop - fetchunit)
|
|
return;
|
|
if (ddfstate != DIW_WAITING_START)
|
|
plf_state = PLF_PASSED_STOP;
|
|
|
|
this.start_bpl_dma(hpos, hpos);
|
|
};
|
|
|
|
this.decide_line = function (hpos) {
|
|
if (this.vpos == plffirstline) {
|
|
diwstate = DIW_WAITING_STOP;
|
|
ddf_change = this.vpos;
|
|
}
|
|
if (this.vpos == plflastline) {
|
|
diwstate = DIW_WAITING_START;
|
|
ddf_change = this.vpos;
|
|
}
|
|
if (hpos <= last_decide_line_hpos)
|
|
return;
|
|
|
|
if (fetch_state == FETCH_NOT_STARTED && (diwstate == DIW_WAITING_STOP || (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))) {
|
|
var ok = 0;
|
|
if (last_decide_line_hpos < plfstrt_start && hpos >= plfstrt_start) {
|
|
if (plf_state == PLF_IDLE)
|
|
plf_state = PLF_START;
|
|
}
|
|
if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
|
|
if (plf_state == PLF_START)
|
|
plf_state = PLF_ACTIVE;
|
|
if (plf_state == PLF_ACTIVE)
|
|
ok = 1;
|
|
if (hpos - 2 == ddfstrt_old_hpos)
|
|
ok = 0;
|
|
}
|
|
if (ok && diwstate == DIW_WAITING_STOP) {
|
|
if (AMIGA.dmaen(DMAF_BPLEN)) {
|
|
this.start_bpl_dma(hpos, plfstrt);
|
|
this.estimate_last_fetch_cycle(plfstrt);
|
|
}
|
|
//last_decide_line_hpos = hpos;
|
|
if (!CUSTOM_SIMPLE)
|
|
this.do_sprites(hpos);
|
|
|
|
return;
|
|
}
|
|
}
|
|
if (!CUSTOM_SIMPLE) {
|
|
if (hpos > last_sprite_hpos && last_sprite_hpos < SPR0_HPOS + 4 * MAX_SPRITES)
|
|
this.do_sprites(hpos);
|
|
}
|
|
last_decide_line_hpos = hpos;
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
/* to screen */
|
|
|
|
this.toscr_2_ecs = function (nbits) {
|
|
var mask = 0xffff >> (16 - nbits);
|
|
var i;
|
|
|
|
for (i = 0; i < toscr_nr_planes2; i += 2) {
|
|
outword[i] <<= nbits;
|
|
outword[i] |= (todisplay[i][0] >> (16 - nbits + toscr_delay1)) & mask;
|
|
todisplay[i][0] <<= nbits;
|
|
}
|
|
for (i = 1; i < toscr_nr_planes2; i += 2) {
|
|
outword[i] <<= nbits;
|
|
outword[i] |= (todisplay[i][0] >> (16 - nbits + toscr_delay2)) & mask;
|
|
todisplay[i][0] <<= nbits;
|
|
}
|
|
};
|
|
|
|
this.toscr_1 = function (nbits, fm) {
|
|
switch (fm) {
|
|
case 0:
|
|
this.toscr_2_ecs(nbits);
|
|
break;
|
|
/*#ifdef AGA
|
|
case 1:
|
|
this.toscr_3_aga(nbits, 1);
|
|
break;
|
|
case 2:
|
|
this.toscr_3_aga(nbits, 2);
|
|
break;
|
|
#endif*/
|
|
}
|
|
out_nbits += nbits;
|
|
if (out_nbits == 32) {
|
|
for (var i = 0; i < thisline_decision.nr_planes; i++) {
|
|
if (line_data[next_lineno][i][out_offs] != outword[i]) {
|
|
thisline_changed = 1;
|
|
line_data[next_lineno][i][out_offs] = outword[i];
|
|
}
|
|
outword[i] = 0;
|
|
}
|
|
out_offs++;
|
|
out_nbits = 0;
|
|
}
|
|
};
|
|
|
|
this.toscr = function (nbits, fm) {
|
|
if (nbits > 16) {
|
|
this.toscr(16, fm);
|
|
nbits -= 16;
|
|
}
|
|
var t = 32 - out_nbits;
|
|
if (t < nbits) {
|
|
this.toscr_1(t, fm);
|
|
nbits -= t;
|
|
}
|
|
this.toscr_1(nbits, fm);
|
|
};
|
|
|
|
this.flush_plane_data = function (fm) {
|
|
var i = 0;
|
|
|
|
if (out_nbits <= 16) {
|
|
i += 16;
|
|
this.toscr_1(16, fm);
|
|
}
|
|
if (out_nbits != 0) {
|
|
i += 32 - out_nbits;
|
|
this.toscr_1(32 - out_nbits, fm);
|
|
}
|
|
i += 32;
|
|
|
|
this.toscr_1(16, fm);
|
|
this.toscr_1(16, fm);
|
|
|
|
if (fm == 2) {
|
|
// flush AGA full 64-bit shift register
|
|
i += 32;
|
|
this.toscr_1(16, fm);
|
|
this.toscr_1(16, fm);
|
|
}
|
|
if (bpl1dat_early) {
|
|
this.toscr_1(16, fm);
|
|
this.toscr_1(16, fm);
|
|
}
|
|
return i >> (1 + toscr_res);
|
|
};
|
|
|
|
this.flush_display = function (fm) {
|
|
if (toscr_nbits > 0 && thisline_decision.plfleft >= 0)
|
|
this.toscr(toscr_nbits, fm);
|
|
toscr_nbits = 0;
|
|
};
|
|
|
|
this.beginning_of_plane_block = function (hpos, fm) {
|
|
var oleft = thisline_decision.plfleft;
|
|
|
|
this.flush_display(fm);
|
|
|
|
if (fm == 0)
|
|
for (var i = 0; i < MAX_PLANES; i++) {
|
|
todisplay[i][0] |= fetched[i];
|
|
}
|
|
/*#ifdef AGA
|
|
else
|
|
for (i = 0; i < MAX_PLANES; i++) {
|
|
if (fm == 2)
|
|
todisplay[i][1] = fetched_aga1[i];
|
|
todisplay[i][0] = fetched_aga0[i];
|
|
}
|
|
#endif*/
|
|
|
|
this.update_denise(hpos);
|
|
this.maybe_first_bpl1dat(hpos);
|
|
|
|
bplcon1t2 = bplcon1t;
|
|
bplcon1t = bplcon1;
|
|
if (bplcon1_hpos != hpos || oleft < 0)
|
|
bplcon1t2 = bplcon1t;
|
|
|
|
this.compute_toscr_delay(hpos, bplcon1t2);
|
|
};
|
|
|
|
this.update_bpldats = function (hpos) {
|
|
for (var i = 0; i < MAX_PLANES; i++) {
|
|
/*#ifdef AGA
|
|
fetched_aga0[i] = bplxdat[i];
|
|
fetched_aga1[i] = 0;
|
|
#endif*/
|
|
fetched[i] = bplxdat[i];
|
|
}
|
|
this.beginning_of_plane_block(hpos, fetchmode);
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
/* fetch */
|
|
|
|
this.finish_final_fetch = function (pos, fm) {
|
|
if (thisline_decision.plfleft < 0 || plf_state == PLF_END)
|
|
return;
|
|
|
|
plf_state = PLF_END;
|
|
ddfstate = DIW_WAITING_START;
|
|
pos += this.flush_plane_data(fm);
|
|
thisline_decision.plfright = pos;
|
|
thisline_decision.plflinelen = out_offs;
|
|
|
|
if (this.vpos >= minfirstline && (thisframe_first_drawn_line < 0 || this.vpos < thisframe_first_drawn_line))
|
|
thisframe_first_drawn_line = this.vpos;
|
|
thisframe_last_drawn_line = this.vpos;
|
|
|
|
if (SMART_UPDATE) {
|
|
if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
|
|
|| line_decisions[next_lineno].plfleft != thisline_decision.plfleft
|
|
|| line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
|
|
|| line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
|
|
|| line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
|
|
/*#ifdef AGA
|
|
|| line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
|
|
#endif*/
|
|
) thisline_changed = 1;
|
|
} else
|
|
thisline_changed = 1;
|
|
};
|
|
|
|
this.long_fetch_ecs = function (plane, nwords, weird_number_of_bits, dma) {
|
|
//uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane], nwords * 2);
|
|
var real_pt = bplpt[plane];
|
|
var delay = (plane & 1) ? toscr_delay2 : toscr_delay1;
|
|
var tmp_nbits = out_nbits;
|
|
var shiftbuffer = todisplay[plane][0];
|
|
var outval = outword[plane];
|
|
var fetchval = fetched[plane];
|
|
//var *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
|
|
var dataptr = out_offs;
|
|
|
|
if (dma) {
|
|
bplpt[plane] += nwords * 2;
|
|
bplptx[plane] += nwords * 2;
|
|
}
|
|
|
|
//if (real_pt == 0) /* @@@ Don't do this, fall back on chipmem_wget instead. */
|
|
//return;
|
|
|
|
while (nwords > 0) {
|
|
var bits_left = 32 - tmp_nbits;
|
|
var t;
|
|
|
|
shiftbuffer |= fetchval;
|
|
|
|
t = (shiftbuffer >>> delay) & 0xFFFF;
|
|
|
|
if (weird_number_of_bits && bits_left < 16) {
|
|
//outval <<= bits_left;
|
|
//outval |= t >>> (16 - bits_left);
|
|
outval = ((outval << bits_left) | (t >>> (16 - bits_left))) >>> 0;
|
|
//thisline_changed |= *dataptr ^ outval; *dataptr++ = outval;
|
|
thisline_changed |= line_data[next_lineno][plane][dataptr] ^ outval;
|
|
line_data[next_lineno][plane][dataptr++] = outval;
|
|
outval = t;
|
|
tmp_nbits = 16 - bits_left;
|
|
//shiftbuffer <<= 16;
|
|
shiftbuffer = (shiftbuffer << 16) >>> 0;
|
|
} else {
|
|
outval = ((outval << 16) | t) >>> 0;
|
|
shiftbuffer = (shiftbuffer << 16) >>> 0;
|
|
tmp_nbits += 16;
|
|
if (tmp_nbits == 32) {
|
|
//thisline_changed |= *dataptr ^ outval; *dataptr++ = outval;
|
|
thisline_changed |= line_data[next_lineno][plane][dataptr] ^ outval;
|
|
line_data[next_lineno][plane][dataptr++] = outval;
|
|
tmp_nbits = 0;
|
|
}
|
|
}
|
|
nwords--;
|
|
if (dma) {
|
|
//fetchval = do_get_mem_word (real_pt); real_pt++;
|
|
//fetchval = AMIGA.mem.load16_chip(real_pt); real_pt += 2;
|
|
fetchval = AMIGA.custom.last_value = AMIGA.mem.chip.data[real_pt >>> 1];
|
|
real_pt += 2;
|
|
}
|
|
}
|
|
fetched[plane] = fetchval;
|
|
todisplay[plane][0] = shiftbuffer;
|
|
outword[plane] = outval;
|
|
};
|
|
|
|
this.do_long_fetch = function (hpos, nwords, dma, fm) {
|
|
var i;
|
|
|
|
this.flush_display(fm);
|
|
switch (fm) {
|
|
case 0:
|
|
if (out_nbits & 15) {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_ecs(i, nwords, 1, dma);
|
|
} else {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_ecs(i, nwords, 0, dma);
|
|
}
|
|
break;
|
|
/*#ifdef AGA
|
|
case 1:
|
|
if (out_nbits & 15) {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_aga(i, nwords, 1, 1, dma);
|
|
} else {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_aga(i, nwords, 0, 1, dma);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (out_nbits & 15) {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_aga(i, nwords, 1, 2, dma);
|
|
} else {
|
|
for (i = 0; i < toscr_nr_planes; i++)
|
|
this.long_fetch_aga(i, nwords, 0, 2, dma);
|
|
}
|
|
break;
|
|
#endif*/
|
|
}
|
|
out_nbits += nwords * 16;
|
|
out_offs += out_nbits >> 5;
|
|
out_nbits &= 31;
|
|
|
|
if (dma && toscr_nr_planes > 0)
|
|
fetch_state = FETCH_WAS_PLANE0;
|
|
};
|
|
|
|
this.add_modulos = function () {
|
|
var m1, m2;
|
|
|
|
if (fmode & 0x4000) {
|
|
if (((diwstrt >> 8) ^ this.vpos) & 1)
|
|
m1 = m2 = bpl2mod;
|
|
else
|
|
m1 = m2 = bpl1mod;
|
|
} else {
|
|
m1 = bpl1mod;
|
|
m2 = bpl2mod;
|
|
}
|
|
|
|
switch (bplcon0_planes_limit) {
|
|
/*#ifdef AGA
|
|
case 8: bplpt[7] += m2; bplptx[7] += m2;
|
|
case 7: bplpt[6] += m1; bplptx[6] += m1;
|
|
#endif*/
|
|
case 6:
|
|
bplpt[5] += m2;
|
|
bplptx[5] += m2;
|
|
case 5:
|
|
bplpt[4] += m1;
|
|
bplptx[4] += m1;
|
|
case 4:
|
|
bplpt[3] += m2;
|
|
bplptx[3] += m2;
|
|
case 3:
|
|
bplpt[2] += m1;
|
|
bplptx[2] += m1;
|
|
case 2:
|
|
bplpt[1] += m2;
|
|
bplptx[1] += m2;
|
|
case 1:
|
|
bplpt[0] += m1;
|
|
bplptx[0] += m1;
|
|
}
|
|
};
|
|
|
|
this.fetch = function (nr, fm, hpos) {
|
|
if (nr < bplcon0_planes_limit) {
|
|
var p = bplpt[nr];
|
|
bplpt[nr] += (2 << fm);
|
|
bplptx[nr] += (2 << fm);
|
|
if (nr == 0)
|
|
bpl1dat_written = true;
|
|
|
|
switch (fm) {
|
|
case 0:
|
|
//fetched[nr] = bplxdat[nr] = last_custom_value1 = chipmem_wget_indirect (p);
|
|
//fetched[nr] = bplxdat[nr] = AMIGA.mem.load16_chip(p);
|
|
fetched[nr] = bplxdat[nr] = AMIGA.custom.last_value = AMIGA.mem.chip.data[p >>> 1];
|
|
break;
|
|
/*#ifdef AGA
|
|
case 1:
|
|
fetched_aga0[nr] = chipmem_lget_indirect (p);
|
|
last_custom_value1 = (uae_u16)fetched_aga0[nr];
|
|
break;
|
|
case 2:
|
|
fetched_aga1[nr] = chipmem_lget_indirect (p);
|
|
fetched_aga0[nr] = chipmem_lget_indirect (p + 4);
|
|
last_custom_value1 = (uae_u16)fetched_aga0[nr];
|
|
break;
|
|
#endif*/
|
|
}
|
|
if (plf_state == PLF_PASSED_STOP2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetch_modulo_cycle) {
|
|
var mod;
|
|
if (fmode & 0x4000) {
|
|
if (((diwstrt >> 8) ^ this.vpos) & 1)
|
|
mod = bpl2mod;
|
|
else
|
|
mod = bpl1mod;
|
|
} else if (nr & 1)
|
|
mod = bpl2mod;
|
|
else
|
|
mod = bpl1mod;
|
|
|
|
bplpt[nr] += mod;
|
|
bplptx[nr] += mod;
|
|
}
|
|
} else {
|
|
if (nr < MAX_PLANES) //FIX for illegal memory access if not #ifdef AGA
|
|
fetched[nr] = bplxdat[nr];
|
|
}
|
|
};
|
|
|
|
this.one_fetch_cycle = function (pos, ddfstop_to_test, dma, fm) {
|
|
if (plf_state < PLF_PASSED_STOP && pos == ddfstop_to_test)
|
|
plf_state = PLF_PASSED_STOP;
|
|
|
|
if ((fetch_cycle & fetchunit_mask) == 0) {
|
|
if (plf_state == PLF_PASSED_STOP2) {
|
|
this.finish_final_fetch(pos, fm);
|
|
return 1;
|
|
}
|
|
if (plf_state == PLF_PASSED_STOP)
|
|
plf_state = PLF_PASSED_STOP2;
|
|
else if (plf_state == PLF_PASSED_STOP2)
|
|
plf_state = PLF_END;
|
|
}
|
|
this.maybe_check(pos);
|
|
|
|
if (dma) {
|
|
var cycle_start = fetch_cycle & fetchstart_mask;
|
|
switch (fm_maxplane) {
|
|
case 8:
|
|
switch (cycle_start) {
|
|
case 0:
|
|
this.fetch(7, fm, pos);
|
|
break;
|
|
case 1:
|
|
this.fetch(3, fm, pos);
|
|
break;
|
|
case 2:
|
|
this.fetch(5, fm, pos);
|
|
break;
|
|
case 3:
|
|
this.fetch(1, fm, pos);
|
|
break;
|
|
case 4:
|
|
this.fetch(6, fm, pos);
|
|
break;
|
|
case 5:
|
|
this.fetch(2, fm, pos);
|
|
break;
|
|
case 6:
|
|
this.fetch(4, fm, pos);
|
|
break;
|
|
case 7:
|
|
this.fetch(0, fm, pos);
|
|
break;
|
|
}
|
|
break;
|
|
case 4:
|
|
switch (cycle_start) {
|
|
case 0:
|
|
this.fetch(3, fm, pos);
|
|
break;
|
|
case 1:
|
|
this.fetch(1, fm, pos);
|
|
break;
|
|
case 2:
|
|
this.fetch(2, fm, pos);
|
|
break;
|
|
case 3:
|
|
this.fetch(0, fm, pos);
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
switch (cycle_start) {
|
|
case 0:
|
|
this.fetch(1, fm, pos);
|
|
break;
|
|
case 1:
|
|
this.fetch(0, fm, pos);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (bpl1dat_written) {
|
|
fetch_state = FETCH_WAS_PLANE0;
|
|
bpl1dat_written = false;
|
|
}
|
|
|
|
fetch_cycle++;
|
|
toscr_nbits += (2 << toscr_res);
|
|
|
|
if (toscr_nbits > 16) {
|
|
Fatal(333, sprintf('one_fetch_cycle() toscr_nbits > 16 (%d)', toscr_nbits));
|
|
toscr_nbits = 0;
|
|
}
|
|
if (toscr_nbits == 16)
|
|
this.flush_display(fm);
|
|
|
|
return 0;
|
|
};
|
|
|
|
this.update_fetch = function (until, fm) {
|
|
var dma = AMIGA.dmaen(DMAF_BPLEN);
|
|
|
|
if (this.nodraw() || plf_state == PLF_END)
|
|
return;
|
|
|
|
var ddfstop_to_test = HARD_DDF_STOP;
|
|
if (ddfstop >= last_fetch_hpos && plfstop < ddfstop_to_test)
|
|
ddfstop_to_test = plfstop;
|
|
|
|
this.update_toscr_planes();
|
|
|
|
var pos = last_fetch_hpos;
|
|
cycle_diagram_shift = last_fetch_hpos - fetch_cycle;
|
|
|
|
for (; ; pos++) {
|
|
if (pos == until) {
|
|
if (until >= this.maxhpos) {
|
|
this.finish_final_fetch(pos, fm);
|
|
return;
|
|
}
|
|
this.flush_display(fm);
|
|
return;
|
|
}
|
|
if (fetch_state == FETCH_WAS_PLANE0)
|
|
break;
|
|
|
|
fetch_state = FETCH_STARTED;
|
|
if (this.one_fetch_cycle(pos, ddfstop_to_test, dma, fm))
|
|
return;
|
|
}
|
|
|
|
// Unrolled version of the for loop below.
|
|
if (1
|
|
&& plf_state < PLF_PASSED_STOP && ddf_change != this.vpos && ddf_change + 1 != this.vpos
|
|
&& dma
|
|
&& (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
|
|
&& !badmode
|
|
//&& (out_nbits & 15) == 0
|
|
&& toscr_nr_planes == thisline_decision.nr_planes) {
|
|
var offs = (pos - fetch_cycle) & fetchunit_mask;
|
|
var ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs;
|
|
var ddf3 = ddf2 + fetchunit;
|
|
var stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3;
|
|
var count = stop - pos;
|
|
|
|
if (count >= fetchstart) {
|
|
count &= ~fetchstart_mask;
|
|
|
|
if (thisline_decision.plfleft < 0) {
|
|
this.compute_delay_offset();
|
|
this.compute_toscr_delay_1(bplcon1);
|
|
}
|
|
|
|
this.do_long_fetch(pos, count >> (3 - toscr_res), dma, fm);
|
|
|
|
this.maybe_first_bpl1dat(pos);
|
|
|
|
if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test)
|
|
plf_state = PLF_PASSED_STOP;
|
|
if (pos <= ddfstop_to_test && pos + count > ddf2)
|
|
plf_state = PLF_PASSED_STOP2;
|
|
if (pos <= ddf2 && pos + count >= ddf2 + fm_maxplane)
|
|
this.add_modulos();
|
|
pos += count;
|
|
fetch_cycle += count;
|
|
}
|
|
}
|
|
|
|
for (; pos < until; pos++) {
|
|
if (fetch_state == FETCH_WAS_PLANE0) {
|
|
this.beginning_of_plane_block(pos, fm);
|
|
this.estimate_last_fetch_cycle(pos);
|
|
}
|
|
fetch_state = FETCH_STARTED;
|
|
if (this.one_fetch_cycle(pos, ddfstop_to_test, dma, fm))
|
|
return;
|
|
}
|
|
if (until >= this.maxhpos) {
|
|
this.finish_final_fetch(pos, fm);
|
|
return;
|
|
}
|
|
this.flush_display(fm);
|
|
};
|
|
|
|
this.update_fetch_x = function (until, fm) {
|
|
if (this.nodraw())
|
|
return;
|
|
|
|
var pos = last_fetch_hpos;
|
|
this.update_toscr_planes();
|
|
|
|
for (; pos < until; pos++) {
|
|
toscr_nbits += (2 << toscr_res);
|
|
if (toscr_nbits > 16) {
|
|
Fatal(333, sprintf('update_fetch_x() xtoscr_nbits > 16 (%d)', toscr_nbits));
|
|
toscr_nbits = 0;
|
|
}
|
|
if (toscr_nbits == 16)
|
|
this.flush_display(fm);
|
|
}
|
|
if (until >= this.maxhpos) {
|
|
this.finish_final_fetch(pos, fm);
|
|
return;
|
|
}
|
|
this.flush_display(fm);
|
|
};
|
|
|
|
this.decide_fetch = function (hpos) {
|
|
if (hpos > last_fetch_hpos) {
|
|
if (fetch_state != FETCH_NOT_STARTED) {
|
|
this.update_fetch(hpos, fetchmode);
|
|
//cycle_diagram_shift = hpos - fetch_cycle;
|
|
} else if (bpl1dat_written_at_least_once) {
|
|
this.update_fetch_x(hpos, fetchmode);
|
|
bpl1dat_written = false;
|
|
}
|
|
this.maybe_check(hpos);
|
|
last_fetch_hpos = hpos;
|
|
}
|
|
};
|
|
|
|
/*this.decide_fetch_ce = function (hpos) {
|
|
if ((ddf_change == this.vpos || ddf_change + 1 == this.vpos) && this.vpos < this.current_maxvpos())
|
|
this.decide_fetch(hpos);
|
|
};*/
|
|
|
|
this.estimate_last_fetch_cycle = function (hpos) {
|
|
var fetchunit = fetchunits[fetchmode * 4 + bplcon0_res];
|
|
|
|
if (plf_state < PLF_PASSED_STOP) {
|
|
var stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
|
|
var fetch_cycle_at_stop = fetch_cycle + (stop - hpos);
|
|
var starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1);
|
|
|
|
estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
|
|
} else {
|
|
var starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
|
|
if (plf_state == PLF_PASSED_STOP2)
|
|
starting_last_block_at -= fetchunit;
|
|
|
|
estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
|
|
}
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.vsync_handler_post = function () {
|
|
if (bplcon0 & 4)
|
|
this.lof_store = this.lof_store ? 0 : 1;
|
|
this.lof_current = this.lof_store;
|
|
if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) {
|
|
interlace_changed = this.notice_interlace_seen(true);
|
|
if (interlace_changed)
|
|
this.notice_screen_contents_lost();
|
|
} else if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED) {
|
|
interlace_changed = this.notice_interlace_seen(false);
|
|
if (interlace_changed)
|
|
this.notice_screen_contents_lost();
|
|
}
|
|
if (this.lof_changing) {
|
|
// still same? Trigger change now.
|
|
if ((!this.lof_store && this.lof_changing < 0) || (this.lof_store && this.lof_changing > 0)) {
|
|
this.lof_changed = 1;
|
|
}
|
|
this.lof_changing = 0;
|
|
}
|
|
|
|
/*#ifdef PICASSO96
|
|
if (p96refresh_active) {
|
|
vpos_count = p96refresh_active;
|
|
vtotal = vpos_count;
|
|
}
|
|
#endif*/
|
|
|
|
if ((beamcon0 & (0x20 | 0x80)) != (new_beamcon0 & (0x20 | 0x80)) || (this.vpos_count > 0 && Math.abs(this.vpos_count - this.vpos_count_diff) > 1) || this.lof_changed)
|
|
this.init_hz(false);
|
|
else if (interlace_changed)
|
|
this.compute_framesync();
|
|
|
|
this.lof_changed = 0;
|
|
|
|
AMIGA.copper.COPJMP(1, 1);
|
|
|
|
this.init_hardware_frame();
|
|
};
|
|
|
|
this.hsync_scandoubler = function () {
|
|
console.log('hsync_scandoubler');
|
|
var bpltmp = [0, 0, 0, 0, 0, 0, 0, 0], bpltmpx = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
|
|
next_lineno++;
|
|
//scandoubled_line = 1;
|
|
|
|
for (var i = 0; i < 8; i++) {
|
|
bpltmp[i] = bplpt[i];
|
|
bpltmpx[i] = bplptx[i];
|
|
if (prevbpl[this.lof_store][this.vpos][i] && prevbpl[1 - this.lof_store][this.vpos][i]) {
|
|
var diff = prevbpl[this.lof_store][this.vpos][i] - prevbpl[1 - this.lof_store][this.vpos][i];
|
|
if (this.lof_store) {
|
|
if (bplcon0 & 4)
|
|
bplpt[i] = prevbpl[this.lof_store][this.vpos][i] - diff;
|
|
} else {
|
|
if (bplcon0 & 4)
|
|
bplpt[i] = prevbpl[this.lof_store][this.vpos][i];
|
|
else
|
|
bplpt[i] = bplpt[i] - diff;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
this.reset_decisions();
|
|
plf_state = PLF_IDLE;
|
|
|
|
// copy color changes
|
|
var dip1 = curr_drawinfo[next_lineno - 1];
|
|
for (var idx1 = dip1.first_color_change; idx1 < dip1.last_color_change; idx1++) {
|
|
var cs2 = curr_color_changes[idx1];
|
|
var regno = cs2.regno;
|
|
var hpos = cs2.linepos;
|
|
if (regno < 0x1000 && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) {
|
|
var pdip = curr_drawinfo[next_lineno - 1];
|
|
var idx = pdip.last_color_change;
|
|
pdip.last_color_change++;
|
|
pdip.nr_color_changes++;
|
|
curr_color_changes[idx].linepos = hpos + this.maxhpos + 1;
|
|
curr_color_changes[idx].regno = regno;
|
|
curr_color_changes[idx].value = cs2.value;
|
|
curr_color_changes[idx + 1].regno = -1;
|
|
} else {
|
|
var cs1 = curr_color_changes[next_color_change];
|
|
cs1.set(cs2); //memcpy (cs1, cs2, sizeof (struct ColorChange));
|
|
next_color_change++;
|
|
}
|
|
}
|
|
|
|
curr_color_changes[next_color_change].regno = -1;
|
|
|
|
this.finish_decisions();
|
|
this.hsync_record_line_state(next_lineno, NLN_NORMAL, thisline_changed);
|
|
this.hardware_line_completed(next_lineno);
|
|
//scandoubled_line = 0;
|
|
|
|
for (var i = 0; i < 8; i++) {
|
|
bplpt[i] = bpltmp[i];
|
|
bplptx[i] = bpltmpx[i];
|
|
}
|
|
};
|
|
|
|
this.hsync_handler_pre = function () {
|
|
this.finish_decisions();
|
|
if (thisline_decision.plfleft >= 0) {
|
|
if (AMIGA.config.chipset.collision_level > 1)
|
|
this.do_sprite_collisions();
|
|
if (AMIGA.config.chipset.collision_level > 2)
|
|
this.do_playfield_collisions();
|
|
}
|
|
this.hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
|
|
if (this.vpos == sprite_vblank_endline) {
|
|
//lightpen_triggered = 0;
|
|
sprite_0 = 0;
|
|
}
|
|
/*if (lightpen_cx > 0 && (bplcon0 & 8) && !lightpen_triggered && lightpen_cy == this.vpos) {
|
|
vpos_lpen = this.vpos;
|
|
hpos_lpen = lightpen_cx;
|
|
lightpen_triggered = 1;
|
|
}*/
|
|
this.hardware_line_completed(next_lineno);
|
|
if (this.doflickerfix() && interlace_seen > 0)
|
|
this.hsync_scandoubler();
|
|
};
|
|
|
|
this.hsync_handler_pre_next_vpos = function (onvsync) {
|
|
if (this.is_linetoggle())
|
|
this.lol ^= 1;
|
|
else
|
|
this.lol = 0;
|
|
|
|
this.vpos++;
|
|
this.vpos_count++;
|
|
if (this.vpos >= this.maxvpos_total)
|
|
this.vpos = 0;
|
|
if (onvsync) {
|
|
this.vpos = 0;
|
|
//vsync_counter++;
|
|
}
|
|
this.maxhpos = this.maxhpos_short + this.lol;
|
|
};
|
|
|
|
this.hsync_handler_post = function () {
|
|
if (this.vpos == equ_vblank_endline + 1) {
|
|
//if (this.lof_current != this.lof_store) {}
|
|
if (this.lof_store != this.lof_previous) {
|
|
if (lof_togglecnt_lace < LOF_TOGGLES_NEEDED)
|
|
lof_togglecnt_lace++;
|
|
if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED)
|
|
lof_togglecnt_nlace = 0;
|
|
} else {
|
|
if (lof_togglecnt_nlace < LOF_TOGGLES_NEEDED)
|
|
lof_togglecnt_nlace++;
|
|
if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED)
|
|
lof_togglecnt_lace = 0;
|
|
}
|
|
this.lof_previous = this.lof_store;
|
|
}
|
|
};
|
|
|
|
this.hsync_handler_post_nextline_how = function () {
|
|
var lineno = this.vpos;
|
|
if (lineno >= MAXVPOS)
|
|
lineno %= MAXVPOS;
|
|
nextline_how = NLN_NORMAL;
|
|
if (this.doflickerfix() && interlace_seen > 0)
|
|
lineno *= 2;
|
|
else if (AMIGA.config.video.vresolution && (doublescan <= 0 || interlace_seen > 0)) {
|
|
lineno *= 2;
|
|
nextline_how = AMIGA.config.video.vresolution > VRES_NONDOUBLE && AMIGA.config.video.scanlines == false ? NLN_DOUBLED : NLN_NBLACK;
|
|
if (interlace_seen) {
|
|
if (!this.lof_current) {
|
|
lineno++;
|
|
nextline_how = NLN_LOWER;
|
|
} else {
|
|
nextline_how = NLN_UPPER;
|
|
}
|
|
}
|
|
}
|
|
prev_lineno = next_lineno;
|
|
next_lineno = lineno;
|
|
this.reset_decisions();
|
|
|
|
plfstrt_sprite = plfstrt;
|
|
};
|
|
|
|
this.hsync_handler_post_diw_change = function () {
|
|
if (GET_PLANES(bplcon0) > 0 && AMIGA.dmaen(DMAF_BPLEN)) {
|
|
if (this.vpos > last_planes_vpos)
|
|
last_planes_vpos = this.vpos;
|
|
if (this.vpos >= minfirstline && first_planes_vpos == 0)
|
|
first_planes_vpos = this.vpos > minfirstline ? this.vpos - 1 : this.vpos;
|
|
else if (this.vpos >= this.current_maxvpos() - 1)
|
|
last_planes_vpos = this.current_maxvpos();
|
|
}
|
|
if (diw_change == 0) {
|
|
if (this.vpos >= first_planes_vpos && this.vpos <= last_planes_vpos) {
|
|
if (diwlastword > diwlastword_total) {
|
|
diwlastword_total = diwlastword;
|
|
if (diwlastword_total > coord_diw_to_window_x(hsyncstartpos * 2))
|
|
diwlastword_total = coord_diw_to_window_x(hsyncstartpos * 2);
|
|
}
|
|
if (diwfirstword < diwfirstword_total) {
|
|
diwfirstword_total = diwfirstword;
|
|
if (diwfirstword_total < coord_diw_to_window_x(hsyncendpos * 2))
|
|
diwfirstword_total = coord_diw_to_window_x(hsyncendpos * 2);
|
|
firstword_bplcon1 = bplcon1;
|
|
}
|
|
}
|
|
if (diwstate == DIW_WAITING_STOP) {
|
|
var f = 8 << fetchmode;
|
|
if (plfstrt + f < ddffirstword_total + f)
|
|
ddffirstword_total = plfstrt + f;
|
|
if (plfstop + 2 * f > ddflastword_total + 2 * f)
|
|
ddflastword_total = plfstop + 2 * f;
|
|
}
|
|
if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && this.vpos > minfirstline)) && plffirstline < (this.vpos >> 1)) {
|
|
firstword_bplcon1 = bplcon1;
|
|
if (plffirstline < minfirstline)
|
|
plffirstline_total = minfirstline;
|
|
else
|
|
plffirstline_total = plffirstline;
|
|
}
|
|
if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > (this.maxvpos >> 1))
|
|
plflastline_total = plflastline;
|
|
}
|
|
if (diw_change > 0)
|
|
diw_change--;
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.getDiwstate = function () {
|
|
return diwstate;
|
|
};
|
|
|
|
this.getData = function () {
|
|
return [
|
|
thisline_decision.plfleft,
|
|
thisline_decision.plfright - (16 << fetchmode),
|
|
cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS(bplcon0)][GET_PLANES_LIMIT(bplcon0)],
|
|
cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS(bplcon0)][GET_PLANES_LIMIT(bplcon0)]
|
|
];
|
|
};
|
|
|
|
/*---------------------------------*/
|
|
|
|
this.setup = function () {
|
|
if (cycle_diagram_table === null)
|
|
create_cycle_diagram_table();
|
|
|
|
if (AMIGA.video.available == 1)
|
|
alloc_colors64k(4, 4, 4, 8, 4, 0, 0, 0, 0, 0);
|
|
else
|
|
alloc_colors64k(5, 6, 5, 11, 5, 0, 0, 0, 0, 0);
|
|
|
|
notice_new_xcolors();
|
|
|
|
this.setup_drawing();
|
|
this.setup_sprites();
|
|
};
|
|
|
|
this.cleanup = function () {
|
|
this.cleanup_sprites();
|
|
this.cleanup_drawing();
|
|
};
|
|
|
|
this.reset = function() {
|
|
/*lightpen_active = -1;
|
|
lightpen_triggered = 0;
|
|
lightpen_cx = lightpen_cy = -1;*/
|
|
|
|
update_mirrors();
|
|
|
|
if (!aga_mode) {
|
|
for (i = 0; i < 32; i++) {
|
|
current_colors.color_regs_ecs[i] = 0;
|
|
current_colors.acolors[i] = getxcolor(0);
|
|
}
|
|
/*#ifdef AGA
|
|
} else {
|
|
for (i = 0; i < 256; i++) {
|
|
current_colors.color_regs_aga[i] = 0;
|
|
current_colors.acolors[i] = getxcolor(0);
|
|
}
|
|
#endif*/
|
|
}
|
|
|
|
clxdat = 0;
|
|
|
|
/* Clear the armed flags of all sprites. */
|
|
for (var i = 0; i < MAX_SPRITES; i++) spr[i].clr();
|
|
nr_armed = 0;
|
|
|
|
bplcon0 = 0;
|
|
bplcon3 = 0x0C00;
|
|
bplcon4 = 0x0011; // Get AGA chipset into ECS compatibility mode
|
|
|
|
diwhigh = 0;
|
|
diwhigh_written = false;
|
|
hdiwstate = DIW_WAITING_START; // this does not reset at vblank
|
|
|
|
this.FMODE(0, 0);
|
|
this.CLXCON(0);
|
|
this.CLXCON2(0);
|
|
this.setup_fmodes(0);
|
|
//sprite_width = GET_SPRITEWIDTH(fmode);
|
|
beamcon0 = new_beamcon0 = AMIGA.config.video.ntsc ? 0x00 : 0x20;
|
|
this.lof_store = this.lof_current = 1;
|
|
|
|
this.vpos = 0;
|
|
this.vpos_count = this.vpos_count_diff = 0;
|
|
|
|
//timehack_alive = 0;
|
|
|
|
curr_sprite_entries = null;
|
|
prev_sprite_entries = null;
|
|
sprite_entries[0][0].first_pixel = 0;
|
|
sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
|
|
sprite_entries[0][1].first_pixel = 0;
|
|
sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
|
|
for (var i = 0; i < spixels.length; i++) spixels[i] = 0; //memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels);
|
|
for (var i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset (&spixstate, 0, sizeof spixstate);
|
|
|
|
diwstate = DIW_WAITING_START;
|
|
|
|
this.init_hz(true);
|
|
//vpos_lpen = -1;
|
|
this.lof_changing = 0;
|
|
this.lof_previous = this.lof_store;
|
|
lof_togglecnt_nlace = lof_togglecnt_lace = 0;
|
|
nlace_cnt = NLACE_CNT_NEEDED;
|
|
|
|
this.reset_sprites();
|
|
this.init_hardware_frame();
|
|
this.reset_drawing();
|
|
this.reset_decisions();
|
|
|
|
sprres = expand_sprres(bplcon0, bplcon3);
|
|
sprite_width = GET_SPRITEWIDTH(fmode);
|
|
this.setup_fmodes(0);
|
|
|
|
/*#ifdef PICASSO96
|
|
picasso_reset();
|
|
#endif*/
|
|
}
|
|
}
|