mirror of
https://github.com/holub/mame
synced 2025-07-06 02:18:09 +03:00
changela: fix tree priorities, tweak layer offsets, merge driver
This commit is contained in:
parent
4a5b8a415f
commit
793afee14b
File diff suppressed because it is too large
Load Diff
@ -1,134 +0,0 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Jarek Burczynski, Phil Stroffolino, Tomasz Slanina
|
||||
|
||||
#include "cpu/m6805/m68705.h"
|
||||
#include "machine/timer.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
class changela_state : public driver_device
|
||||
{
|
||||
public:
|
||||
changela_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_mcu(*this, "mcu")
|
||||
, m_screen(*this, "screen")
|
||||
, m_palette(*this, "palette")
|
||||
, m_spriteram(*this, "spriteram")
|
||||
, m_videoram(*this, "videoram")
|
||||
, m_colorram(*this, "colorram")
|
||||
, m_tilerom(*this, "tiles")
|
||||
, m_obj0rom(*this, "obj0")
|
||||
, m_obj1rom(*this, "obj1")
|
||||
, m_sloperom(*this, "slope")
|
||||
, m_treerom(*this, "tree")
|
||||
, m_proms(*this, "proms")
|
||||
, m_inputs(*this, "IN%u", 0)
|
||||
, m_gas(*this, "GAS")
|
||||
, m_wheel(*this, "WHEEL")
|
||||
{
|
||||
}
|
||||
|
||||
void changela(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
// devices/pointers
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<m68705p_device> m_mcu;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<u8> m_spriteram;
|
||||
required_shared_ptr<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_colorram;
|
||||
required_region_ptr<u8> m_tilerom;
|
||||
required_region_ptr<u8> m_obj0rom;
|
||||
required_region_ptr<u8> m_obj1rom;
|
||||
required_region_ptr<u8> m_sloperom;
|
||||
required_region_ptr<u8> m_treerom;
|
||||
required_region_ptr<u8> m_proms;
|
||||
|
||||
// input ports
|
||||
required_ioport_array<2> m_inputs;
|
||||
required_ioport m_gas;
|
||||
required_ioport m_wheel;
|
||||
|
||||
// video-related
|
||||
bitmap_ind16 m_obj0_bitmap;
|
||||
bitmap_ind16 m_river_bitmap;
|
||||
bitmap_ind16 m_tree0_bitmap;
|
||||
bitmap_ind16 m_tree1_bitmap;
|
||||
|
||||
std::unique_ptr<u8[]> m_riverram;
|
||||
std::unique_ptr<u8[]> m_treeram;
|
||||
u8 m_treeram2[0x20 * 2] = { };
|
||||
u8 m_stateram[0x40 * 3] = { };
|
||||
|
||||
u8 m_mem_dev_selected = 0;
|
||||
u32 m_sloperom_bank = 0;
|
||||
u8 m_tree_en = 0;
|
||||
u8 m_horizon = 0;
|
||||
u8 m_v_count_river = 0;
|
||||
u8 m_v_count_tree = 0;
|
||||
u8 m_tree_on[2] = { };
|
||||
emu_timer *m_scanline_timer = nullptr;
|
||||
|
||||
// mcu-related
|
||||
u8 m_port_a_out = 0xff;
|
||||
u8 m_port_c_out = 0xff;
|
||||
u8 m_mcu_out = 0xff;
|
||||
u8 m_mcu_in = 0xff;
|
||||
|
||||
// misc
|
||||
u8 m_tree0_col = 0;
|
||||
u8 m_tree1_col = 0;
|
||||
u8 m_left_bank_col = 0;
|
||||
u8 m_right_bank_col = 0;
|
||||
u8 m_boat_shore_col = 0;
|
||||
u8 m_collision_reset = 0;
|
||||
u8 m_tree_collision_reset = 0;
|
||||
u8 m_prev_value_31 = 0;
|
||||
u8 m_dir_31 = 0;
|
||||
|
||||
// devices
|
||||
u8 mcu_r();
|
||||
void mcu_w(u8 data);
|
||||
void changela_68705_port_a_w(u8 data);
|
||||
void changela_68705_port_c_w(u8 data);
|
||||
u8 changela_24_r();
|
||||
u8 changela_25_r();
|
||||
u8 changela_30_r();
|
||||
u8 changela_31_r();
|
||||
u8 changela_2d_r();
|
||||
void mcu_pc_0_w(int state);
|
||||
void collision_reset_0_w(int state);
|
||||
void collision_reset_1_w(int state);
|
||||
void coin_counter_1_w(int state);
|
||||
void coin_counter_2_w(int state);
|
||||
void changela_colors_w(offs_t offset, u8 data);
|
||||
void changela_mem_device_select_w(u8 data);
|
||||
void changela_mem_device_w(offs_t offset, u8 data);
|
||||
u8 changela_mem_device_r(offs_t offset);
|
||||
void changela_slope_rom_addr_hi_w(u8 data);
|
||||
void changela_slope_rom_addr_lo_w(u8 data);
|
||||
|
||||
INTERRUPT_GEN_MEMBER(chl_mcu_irq);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(changela_scanline);
|
||||
TIMER_CALLBACK_MEMBER(changela_scanline_callback);
|
||||
|
||||
u32 screen_update_changela(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_obj0(bitmap_ind16 &bitmap, int sy);
|
||||
void draw_obj1(bitmap_ind16 &bitmap);
|
||||
void draw_river(bitmap_ind16 &bitmap, int sy);
|
||||
void draw_tree(bitmap_ind16 &bitmap, int sy, int tree_num);
|
||||
|
||||
void changela_map(address_map &map);
|
||||
};
|
@ -1,779 +0,0 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Jarek Burczynski, Phil Stroffolino, Tomasz Slanina
|
||||
/**************************************************************************
|
||||
|
||||
Change Lanes - Video Hardware
|
||||
(C) Taito 1983
|
||||
|
||||
Jarek Burczynski
|
||||
Phil Stroffolino
|
||||
Tomasz Slanina
|
||||
Adam Bousley
|
||||
|
||||
TODO: Priority between tree0 and tree1.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "changela.h"
|
||||
|
||||
|
||||
void changela_state::video_start()
|
||||
{
|
||||
m_riverram = std::make_unique<u8[]>(0x800);
|
||||
save_pointer(NAME(m_riverram), 0x800);
|
||||
|
||||
m_treeram = std::make_unique<u8[]>(0x800);
|
||||
save_pointer(NAME(m_treeram), 0x800);
|
||||
|
||||
m_screen->register_screen_bitmap(m_obj0_bitmap);
|
||||
m_screen->register_screen_bitmap(m_river_bitmap);
|
||||
m_screen->register_screen_bitmap(m_tree0_bitmap);
|
||||
m_screen->register_screen_bitmap(m_tree1_bitmap);
|
||||
|
||||
m_scanline_timer = timer_alloc(FUNC(changela_state::changela_scanline_callback), this);
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(30), 30);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
Obj 0 - Sprite Layer
|
||||
*********************************/
|
||||
|
||||
void changela_state::draw_obj0(bitmap_ind16 &bitmap, int sy)
|
||||
{
|
||||
u8 const *const ROM = m_obj0rom;
|
||||
u8 const *const RAM = m_spriteram;
|
||||
|
||||
for (int sx = 0; sx < 256; sx++)
|
||||
{
|
||||
int vr = (RAM[sx * 4 + 0] & 0x80) >> 7;
|
||||
int hr = (RAM[sx * 4 + 0] & 0x40) >> 6;
|
||||
int hs = (RAM[sx * 4 + 0] & 0x20) >> 5;
|
||||
u32 vsize = RAM[sx * 4 + 0] & 0x1f;
|
||||
u8 ypos = ~RAM[sx * 4 + 1];
|
||||
u8 tile = RAM[sx * 4 + 2];
|
||||
u8 xpos = RAM[sx * 4 + 3];
|
||||
|
||||
if (sy - ypos <= vsize)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
u8 sum = sy - ypos;
|
||||
|
||||
u8 counter = i;
|
||||
if (hr) counter ^= 0x0f;
|
||||
|
||||
u32 A8 = ((tile & 0x02) >> 1) ^ ((hr & hs) ^ hs);
|
||||
u32 A7 = ((((vr ^ ((sum & 0x10) >> 4)) & ((vsize & 0x10) >> 4)) ^ 0x01) & (tile & 0x01)) ^ 0x01;
|
||||
u32 rom_addr = (counter >> 1) | ((sum & 0x0f) << 3) | (A7 << 7) | (A8 << 8) | ((tile >> 2) << 9);
|
||||
if (vr) rom_addr ^= (0x0f << 3);
|
||||
|
||||
u8 data;
|
||||
if (counter & 1)
|
||||
data = ROM[rom_addr] & 0x0f;
|
||||
else
|
||||
data = (ROM[rom_addr] & 0xf0) >> 4;
|
||||
|
||||
if ((data != 0x0f) && (data != 0))
|
||||
bitmap.pix(sy, xpos + i) = data | 0x10;
|
||||
|
||||
if (hs)
|
||||
{
|
||||
if (counter & 1)
|
||||
data = ROM[rom_addr ^ 0x100] & 0x0f;
|
||||
else
|
||||
data = (ROM[rom_addr ^ 0x100] & 0xf0) >> 4;
|
||||
|
||||
if ((data != 0x0f) && (data != 0))
|
||||
bitmap.pix(sy, xpos + i + 16) = data | 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
Obj 1 - Text Layer
|
||||
*********************************/
|
||||
|
||||
void changela_state::draw_obj1(bitmap_ind16 &bitmap)
|
||||
{
|
||||
u8 const *const ROM = m_obj1rom;
|
||||
u8 const *const RAM = m_videoram;
|
||||
|
||||
u8 reg[4] = { 0 }; // 4x4-bit registers (U58, U59)
|
||||
|
||||
u8 attrib = 0;
|
||||
|
||||
for (int sy = 0; sy < 256; sy++)
|
||||
{
|
||||
for (int sx = 0; sx < 256; sx++)
|
||||
{
|
||||
// 11 Bits: H1, H3, H4, H5, H6, H7, V3, V4, V5, V6, V7
|
||||
int ram_addr = ((sx & 0xf8) >> 2) | ((sy & 0xf8) << 3);
|
||||
int tile_addr = RAM[ram_addr];
|
||||
|
||||
if (!(RAM[ram_addr + 1] & 0x10) && (sx & 0x04)) // D4=0 enables latch at U32
|
||||
attrib = RAM[ram_addr + 1];
|
||||
|
||||
u8 tile = ROM[(tile_addr << 4) | ((sx & 0x04) >> 2) | ((sy & 0x07) << 1)];
|
||||
reg[(sx & 0x0c) >> 2] = tile;
|
||||
int sum = (sx & 0x0f) + (attrib & 0x0f); // 4-bit adder (U45)
|
||||
|
||||
// Multiplexers (U57)
|
||||
int c0, c1;
|
||||
if ((sum & 0x03) == 0)
|
||||
{
|
||||
c0 = (reg[(sum & 0x0c) >> 2] & 0x08) >> 3;
|
||||
c1 = (reg[(sum & 0x0c) >> 2] & 0x80) >> 7;
|
||||
}
|
||||
else if ((sum & 0x03) == 1)
|
||||
{
|
||||
c0 = (reg[(sum & 0x0c) >> 2] & 0x04) >> 2;
|
||||
c1 = (reg[(sum & 0x0c) >> 2] & 0x40) >> 6;
|
||||
}
|
||||
else if ((sum & 0x03) == 2)
|
||||
{
|
||||
c0 = (reg[(sum & 0x0c) >> 2] & 0x02) >> 1;
|
||||
c1 = (reg[(sum & 0x0c) >> 2] & 0x20) >> 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
c0 = (reg[(sum & 0x0c) >> 2] & 0x01) >> 0;
|
||||
c1 = (reg[(sum & 0x0c) >> 2] & 0x10) >> 4;
|
||||
}
|
||||
|
||||
int col = c0 | (c1 << 1) | ((attrib & 0xc0) >> 4);
|
||||
if ((col & 0x07) != 0x07)
|
||||
bitmap.pix(sy, sx) = col | 0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
River Video Generator
|
||||
*********************************/
|
||||
|
||||
void changela_state::draw_river(bitmap_ind16 &bitmap, int sy)
|
||||
{
|
||||
u8 const *const ROM = m_sloperom;
|
||||
u8 *const RAM = m_stateram;
|
||||
u8 const *const TILE_ROM = m_tilerom;
|
||||
u8 const *const TILE_RAM = m_riverram.get();
|
||||
u8 const *const PROM = m_proms;
|
||||
|
||||
int preload = ((sy < 32) ? 1 : 0);
|
||||
|
||||
u8 math_train[10] = { 0 };
|
||||
u8 pre_train[3] = { 0 };
|
||||
|
||||
u8 prev_state = 0;
|
||||
|
||||
u8 ram_count = 0;
|
||||
u8 rom_count = 0;
|
||||
|
||||
int hosc = 0;
|
||||
int carry = 0;
|
||||
|
||||
// Update Counters
|
||||
if (sy == 30) m_v_count_river = m_horizon;
|
||||
m_v_count_river = (m_v_count_river + 1) & 0xff;
|
||||
|
||||
// ----- STATE MACHINE -----
|
||||
for (int i = 0; i < 0x20; i++)
|
||||
{
|
||||
u8 curr_state = PROM[i];
|
||||
|
||||
// Update Counters
|
||||
if (prev_state & 0x80)
|
||||
ram_count = (ram_count + 1) & 0x0f;
|
||||
if ((curr_state & 0x40) && !(prev_state & 0x40))
|
||||
rom_count = (rom_count + 1) & 0x0f;
|
||||
|
||||
if (prev_state & 0x02)
|
||||
carry = (((pre_train[1] + pre_train[2] + carry) > 0x0f) ? 1 : 0);
|
||||
if (!(curr_state & 0x08))
|
||||
carry = 0;
|
||||
|
||||
if (prev_state & 0x10)
|
||||
hosc = (math_train[8] << 4) | math_train[9];
|
||||
|
||||
int rom_addr = m_sloperom_bank | ((m_v_count_river & 0x7e) << 2) | ((rom_count & 0x0e) >> 1);
|
||||
int ram_a5 = ((curr_state & 0x01) & ((curr_state & 0x40) >> 6) & preload) ^ 0x01;
|
||||
int ram_addr = (ram_a5 << 5) | (ram_count << 1) | ((curr_state & 0x20) >> 5);
|
||||
int mux45 = rom_count & 0x01;
|
||||
int mux61 = m_v_count_river & 0x01;
|
||||
|
||||
switch (curr_state)
|
||||
{
|
||||
case 0x01: case 0x09: case 0x19: case 0x0d: case 0x8d:
|
||||
pre_train[0] = (mux45 ? ((ROM[rom_addr] & 0xf0) >> 4) : (ROM[rom_addr] & 0x0f));
|
||||
break;
|
||||
case 0x0f: case 0x2f:
|
||||
math_train[0] = RAM[ram_addr] = (mux45 ? ((ROM[rom_addr] & 0xf0) >> 4) : (ROM[rom_addr] & 0x0f));
|
||||
break;
|
||||
case 0x4d: case 0x69: case 0x6d: case 0xc5: case 0xcd:
|
||||
pre_train[0] = RAM[ram_addr] & 0x0f;
|
||||
break;
|
||||
case 0xea: case 0xee:
|
||||
math_train[0] = RAM[ram_addr] = (mux61 ? (pre_train[1]) : ((pre_train[1] + pre_train[2] + carry) & 0x0f));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Shift each item down the train
|
||||
if (curr_state & 0x02)
|
||||
{
|
||||
for (int j = 9; j > 0; j--)
|
||||
{
|
||||
math_train[j] = math_train[j - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pre_train[2] = pre_train[1];
|
||||
pre_train[1] = pre_train[0];
|
||||
}
|
||||
|
||||
prev_state = curr_state;
|
||||
}
|
||||
|
||||
if (!(m_v_count_river & 0x80))
|
||||
{
|
||||
int h_count = 0x80 | (hosc >> 1);
|
||||
int tile_v = ((math_train[3] & 0x0c) >> 2) | ((math_train[2] & 0x0f) << 2) | ((math_train[1] & 0x07) << 6);
|
||||
int tile_h = (math_train[7] & 0x0f) | ((math_train[6] & 0x0f) << 4) | ((math_train[5] & 0x01) << 8);
|
||||
|
||||
// Burst of 16 10Mhz Clocks
|
||||
for (int sx = 0; sx < 16; sx++)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (h_count > 0xff)
|
||||
{
|
||||
h_count = ((math_train[9] & 0x0f) >> 1) | ((math_train[8] & 0x0f) << 3) | 0x80;
|
||||
tile_h = (tile_h+1) & 0xfff;
|
||||
|
||||
// Skip one count if LSB is high
|
||||
if (((math_train[9] & 0x01) && (tile_h & 0x01)))
|
||||
h_count--;
|
||||
}
|
||||
else
|
||||
h_count++;
|
||||
}
|
||||
|
||||
int ram_addr = ((tile_h & 0x1f8) >> 3) | ((tile_v & 0x1f0) << 2);
|
||||
int rom_addr = ((tile_h & 0x06) >> 1) | ((tile_v & 0x0f) << 2) | ((TILE_RAM[ram_addr] & 0x7f) << 6);
|
||||
|
||||
int col;
|
||||
if (tile_h & 0x01)
|
||||
col = TILE_ROM[rom_addr] & 0x0f;
|
||||
else
|
||||
col = (TILE_ROM[rom_addr] & 0xf0) >> 4;
|
||||
|
||||
bitmap.pix(sy, sx) = col;
|
||||
}
|
||||
|
||||
for (int sx = 16; sx < 256; sx++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (h_count > 0xff)
|
||||
{
|
||||
h_count = ((math_train[9] & 0x0f) >> 1) | ((math_train[8] & 0x0f) << 3) | 0x80;
|
||||
tile_h = (tile_h+1) & 0xfff;
|
||||
|
||||
// Skip one count if LSB is high
|
||||
if (((math_train[9] & 0x01) && (tile_h & 0x01)))
|
||||
h_count--;
|
||||
}
|
||||
else
|
||||
h_count++;
|
||||
}
|
||||
|
||||
int ram_addr = ((tile_h & 0x1f8) >> 3) | ((tile_v & 0x1f0) << 2);
|
||||
int rom_addr = ((tile_h & 0x06) >> 1) | ((tile_v & 0x0f) << 2) | ((TILE_RAM[ram_addr] & 0x7f) << 6);
|
||||
|
||||
int col;
|
||||
if (tile_h & 0x01)
|
||||
col = TILE_ROM[rom_addr] & 0x0f;
|
||||
else
|
||||
col = (TILE_ROM[rom_addr] & 0xf0) >> 4;
|
||||
|
||||
bitmap.pix(sy, sx) = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
Tree Generators
|
||||
*********************************/
|
||||
|
||||
void changela_state::draw_tree(bitmap_ind16 &bitmap, int sy, int tree_num)
|
||||
{
|
||||
// State machine
|
||||
u8 const *const ROM = m_sloperom;
|
||||
u8 *const RAM = m_stateram + 0x40 + 0x40 * tree_num;
|
||||
u8 const *const PROM = m_proms;
|
||||
|
||||
// Tree Data
|
||||
u8 *const RAM2 = m_treeram2 + 0x20 * tree_num;
|
||||
u8 const *const TILE_ROM = (tree_num ? (m_treerom + 0x1000) : (m_tilerom + 0x2000));
|
||||
u8 const *const TILE_RAM = (tree_num ? m_treerom : m_treeram.get());
|
||||
|
||||
int preload = ((sy < 32) ? 1 : 0);
|
||||
|
||||
u8 math_train[10] = { 0 };
|
||||
u8 pre_train[3] = { 0 };
|
||||
u8 tree_train[3] = { 0 };
|
||||
|
||||
u8 prev_state = 0;
|
||||
|
||||
u8 ram_count = 0;
|
||||
u8 rom_count = 0;
|
||||
|
||||
int hosc = 0;
|
||||
int carry = 0;
|
||||
int tree_carry = 0;
|
||||
|
||||
int h_count, tile_v, tile_h;
|
||||
int all_ff;
|
||||
|
||||
// Update Counters
|
||||
if (sy == 30)
|
||||
{
|
||||
m_tree_on[tree_num] = 0;
|
||||
if (tree_num == 0)
|
||||
m_v_count_tree = m_horizon;
|
||||
}
|
||||
if (tree_num == 0)
|
||||
m_v_count_tree = (m_v_count_tree + 1) & 0xff;
|
||||
|
||||
//* ----- STATE MACHINE -----
|
||||
for (int i = 0; i < 0x20; i++)
|
||||
{
|
||||
u8 curr_state = PROM[i];
|
||||
|
||||
// Update Counters
|
||||
if (prev_state & 0x80)
|
||||
ram_count = (ram_count + 1) & 0x0f;
|
||||
if ((curr_state & 0x40) && !(prev_state & 0x40))
|
||||
rom_count = (rom_count + 1) & 0x0f;
|
||||
|
||||
if (prev_state & 0x02)
|
||||
{
|
||||
carry = (((pre_train[1] + pre_train[2] + carry) > 0x0f) ? 1 : 0);
|
||||
tree_carry = (((tree_train[1] + tree_train[2] + tree_carry) > 0x0f) ? 1 : 0);
|
||||
}
|
||||
if (!(curr_state & 0x08))
|
||||
carry = tree_carry = 0;
|
||||
|
||||
if (prev_state & 0x10)
|
||||
hosc = (math_train[8] << 4) | math_train[9];
|
||||
|
||||
int rom_addr = m_sloperom_bank | ((m_v_count_tree & 0x7e) << 2) | ((rom_count & 0x0e) >> 1);
|
||||
int ram_a5 = ((curr_state & 0x01) & ((curr_state & 0x40) >> 6) & preload) ^ 0x01;
|
||||
int ram_addr = (ram_a5 << 5) | (ram_count << 1) | ((curr_state & 0x20) >> 5);
|
||||
int ram2_addr = (ram_count << 1) | ((curr_state & 0x20) >> 5);
|
||||
int mux45 = rom_count & 0x01;
|
||||
int mux61 = m_v_count_tree & 0x01;
|
||||
|
||||
switch (curr_state)
|
||||
{
|
||||
case 0x01: case 0x09: case 0x19: case 0x0d: case 0x8d:
|
||||
pre_train[0] = (mux45 ? ((ROM[rom_addr] & 0xf0) >> 4) : (ROM[rom_addr] & 0x0f));
|
||||
break;
|
||||
case 0x0f: case 0x2f:
|
||||
RAM[ram_addr] = (mux45 ? ((ROM[rom_addr] & 0xf0) >> 4) : (ROM[rom_addr] & 0x0f));
|
||||
break;
|
||||
case 0x4d: case 0x69: case 0x6d: case 0xc5: case 0xcd:
|
||||
pre_train[0] = RAM[ram_addr] & 0x0f;
|
||||
break;
|
||||
case 0xea: case 0xee:
|
||||
RAM[ram_addr] = (mux61 ? (pre_train[1]) : ((pre_train[1] + pre_train[2] + carry) & 0x0f));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_tree_on[tree_num])
|
||||
{
|
||||
int mux82 = (m_v_count_tree & 0x01) ^ 0x01;
|
||||
|
||||
switch (curr_state)
|
||||
{
|
||||
case 0x01: case 0x09: case 0x19: case 0x0d: case 0x8d:
|
||||
tree_train[0] = RAM2[ram2_addr] = pre_train[0];
|
||||
break;
|
||||
case 0x0f: case 0x2f:
|
||||
math_train[0] = RAM2[ram2_addr] = RAM[ram_addr] & 0x0f;
|
||||
break;
|
||||
case 0x4d: case 0x69: case 0x6d: case 0xc5: case 0xcd:
|
||||
tree_train[0] = RAM2[ram2_addr] = pre_train[0];
|
||||
break;
|
||||
case 0xea: case 0xee:
|
||||
math_train[0] = RAM2[ram2_addr] = (mux82 ? ((tree_train[1] + tree_train[2] + tree_carry) & 0x0f) : (tree_train[1]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int mux82 = ((curr_state & 0x04) ? 0 : 1);
|
||||
|
||||
switch (curr_state)
|
||||
{
|
||||
case 0x01: case 0x09: case 0x19: case 0x0d: case 0x8d:
|
||||
tree_train[0] = RAM2[ram2_addr];
|
||||
break;
|
||||
case 0x0f: case 0x2f:
|
||||
math_train[0] = RAM2[ram2_addr];
|
||||
break;
|
||||
case 0x4d: case 0x69: case 0x6d: case 0xc5: case 0xcd:
|
||||
tree_train[0] = RAM2[ram2_addr];
|
||||
break;
|
||||
case 0xea: case 0xee:
|
||||
math_train[0] = RAM2[ram2_addr] = (mux82 ? ((tree_train[1] + tree_train[2] + tree_carry) & 0x0f) : (tree_train[1]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shift each item down the train
|
||||
if (curr_state & 0x02)
|
||||
{
|
||||
for (int j = 9; j > 0; j--)
|
||||
math_train[j] = math_train[j-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
pre_train[2] = pre_train[1];
|
||||
pre_train[1] = pre_train[0];
|
||||
tree_train[2] = tree_train[1];
|
||||
tree_train[1] = tree_train[0];
|
||||
}
|
||||
|
||||
prev_state = curr_state;
|
||||
}
|
||||
|
||||
h_count = 0x80 | (hosc >> 1);
|
||||
tile_v = ((math_train[3] & 0x0c) >> 2) | ((math_train[2] & 0x0f) << 2) | ((math_train[1] & 0x07) << 6);
|
||||
tile_h = (math_train[7] & 0x0f) | ((math_train[6] & 0x0f) << 4) | ((math_train[5] & 0x01) << 8);
|
||||
all_ff = 1;
|
||||
|
||||
// Burst of 16 10Mhz clocks
|
||||
for (int sx = 0; sx < 16; sx++)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (h_count > 0xff)
|
||||
{
|
||||
h_count = ((math_train[9] & 0x0f) >> 1) | ((math_train[8] & 0x0f) << 3) | 0x80;
|
||||
tile_h = (tile_h+1) & 0xfff;
|
||||
|
||||
// Skip one count if LSB is high
|
||||
if (((math_train[9] & 0x01) && (tile_h & 0x01)))
|
||||
h_count--;
|
||||
}
|
||||
else
|
||||
h_count++;
|
||||
}
|
||||
|
||||
int ram_addr = ((tile_h & 0x1f8) >> 3) | ((tile_v & 0x1f0) << 2);
|
||||
int rom_addr = ((tile_h & 0x06) >> 1) | ((tile_v & 0x0f) << 2) | ((TILE_RAM[ram_addr] & 0x7f) << 6);
|
||||
|
||||
if (!(m_v_count_tree & 0x80) && (m_tree_en & (0x01 << tree_num)) && ((TILE_ROM[rom_addr] & 0xf0) == 0))
|
||||
m_tree_on[tree_num] = 1;
|
||||
|
||||
if (m_tree_on[tree_num])
|
||||
{
|
||||
int col;
|
||||
if (tile_h & 0x01)
|
||||
col = TILE_ROM[rom_addr] & 0x0f;
|
||||
else
|
||||
col = (TILE_ROM[rom_addr] & 0xf0) >> 4;
|
||||
|
||||
if (col != 0x0f)
|
||||
all_ff = 0;
|
||||
|
||||
if (col != 0x0f && col != 0x00)
|
||||
bitmap.pix(sy, sx) = col | 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
for (int sx = 16; sx < 256; sx++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (h_count > 0xff)
|
||||
{
|
||||
h_count = ((math_train[9] & 0x0f) >> 1) | ((math_train[8] & 0x0f) << 3) | 0x80;
|
||||
tile_h = (tile_h+1) & 0xfff;
|
||||
|
||||
// Skip one count if LSB is high
|
||||
if (((math_train[9] & 0x01) && (tile_h & 0x01)))
|
||||
h_count--;
|
||||
}
|
||||
else
|
||||
h_count++;
|
||||
}
|
||||
|
||||
int ram_addr = ((tile_h & 0x1f8) >> 3) | ((tile_v & 0x1f0) << 2);
|
||||
int rom_addr = ((tile_h & 0x06) >> 1) | ((tile_v & 0x0f) << 2) | ((TILE_RAM[ram_addr] & 0x7f) << 6);
|
||||
|
||||
if (!(m_v_count_tree & 0x80) && (m_tree_en & (0x01 << tree_num)) && ((TILE_ROM[rom_addr] & 0xf0) == 0))
|
||||
m_tree_on[tree_num] = 1;
|
||||
|
||||
if (m_tree_on[tree_num])
|
||||
{
|
||||
int col;
|
||||
if (tile_h & 0x01)
|
||||
col = TILE_ROM[rom_addr] & 0x0f;
|
||||
else
|
||||
col = (TILE_ROM[rom_addr] & 0xf0) >> 4;
|
||||
|
||||
if (col != 0x0f)
|
||||
all_ff = 0;
|
||||
|
||||
if (col != 0x0f && col != 0x00)
|
||||
bitmap.pix(sy, sx) = col | 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
// Tree on only stays high if a pixel that is not 0xf is encountered, because any non 0xf pixel sets U56 high
|
||||
if (all_ff) m_tree_on[tree_num] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
--+-------------------+-----------------------------------------------------+-----------------------------------------------------------------
|
||||
St| PROM contents: | Main signals: | DESCRIPTION
|
||||
at+-------------------+-----------------------------------------------------+-----------------------------------------------------------------
|
||||
e:|7 6 5 4 3 2 1 0 Hex|/RAMw /RAMr /ROM /AdderOutput AdderInput TrainInputs|
|
||||
| | enable GateU61Enable Enable Enable |
|
||||
--+-------------------+-----------------------------------------------------+-----------------------------------------------------------------
|
||||
00|0 0 0 0 1 1 0 1 0d | 1 1 0 1 0 1 | (noop ROM 00-lsb to adder)
|
||||
01|0 0 0 0 1 1 1 1 0f | 0 1 0 1 1 0 | ROM 00-lsb to train, and to RAM 00
|
||||
02|0 1 0 0 1 1 0 1 4d | 1 0 1 1 0 1 | (noop RAM 00 to adder)
|
||||
03|0 0 1 0 1 1 1 1 2f | 0 1 0 1 1 0 | ROM 00-msb to train, and to RAM 01
|
||||
04|1 1 0 0 1 1 0 1 cd | 1 0 1 1 0 1 | (noop RAM 00 to adder)
|
||||
05|0 0 0 0 1 1 1 1 0f | 0 1 0 1 1 0 | ROM 01-lsb to train, and to RAM 02
|
||||
06|0 1 0 0 1 1 0 1 4d | 1 0 1 1 0 1 | (noop RAM 02 to adder)
|
||||
07|0 0 1 0 1 1 1 1 2f | 0 1 0 1 1 0 | ROM 01-msb to train, and to RAM 03
|
||||
08|1 1 0 0 0 1 0 1 c5 | 1 0 1 1 0 1 | CLR carry
|
||||
09|0 0 0 0 1 1 0 1 0d | 1 1 0 1 0 1 | ROM 02-lsb to adder
|
||||
0a|0 1 1 0 1 1 0 1 6d | 1 0 1 1 0 1 | RAM 05 to adder
|
||||
0b|1 1 1 0 1 1 1 0 ee | 0 1 1 0 1 0 | Adder to train, and to RAM 05, CLOCK carry
|
||||
0c|0 0 0 0 1 1 0 1 0d | 1 1 0 1 0 1 | ROM 02-msb to adder
|
||||
0d|0 1 1 0 1 1 0 1 6d | 1 0 1 1 0 1 | RAM 07 to adder
|
||||
0e|1 1 1 0 1 1 1 0 ee | 0 1 1 0 1 0 | Adder to train, and to RAM 07, CLOCK carry
|
||||
0f|0 0 0 0 1 1 0 1 0d | 1 1 0 1 0 1 | ROM 03-lsb to adder
|
||||
10|0 1 1 0 1 1 0 1 6d | 1 0 1 1 0 1 | RAM 09 to adder
|
||||
11|1 1 1 0 1 1 1 0 ee | 0 1 1 0 1 0 | Adder to train, and to RAM 09, CLOCK carry
|
||||
12|1 0 0 0 1 1 0 1 8d | 1 1 0 1 0 1 | (noop ROM 03-msb to adder)
|
||||
13|0 1 0 0 1 1 0 1 4d | 1 0 1 1 0 1 | (noop RAM 0c to adder)
|
||||
14|0 0 0 0 0 0 0 1 01 | 1 1 0 1 0 1 | ROM 04-lsb to adder, CLR carry
|
||||
15|0 1 1 0 1 0 0 1 69 | 1 0 1 1 0 1 | RAM 0d to adder
|
||||
16|1 1 1 0 1 0 1 0 ea | 0 1 1 0 1 0 | Adder to train and to RAM 0d, CLOCK carry
|
||||
17|0 0 0 0 1 0 0 1 09 | 1 1 0 1 0 1 | ROM 04-msb to adder
|
||||
18|0 1 1 0 1 0 0 1 69 | 1 0 1 1 0 1 | RAM 0f to adder
|
||||
19|1 1 1 0 1 0 1 0 ea | 0 1 1 0 1 0 | Adder to train and to RAM 0f, CLOCK carry
|
||||
1a|0 0 0 1 1 0 0 1 19 | 1 1 0 1 0 1 | ROM 05-lsb to adder, /LD HOSC
|
||||
1b|0 1 1 0 1 0 0 1 69 | 1 0 1 1 0 1 | RAM 11 to adder
|
||||
1c|1 1 1 0 1 0 1 0 ea | 0 1 1 0 1 0 | Adder to train and to RAM 11, CLOCK carry
|
||||
1d|0 0 0 0 1 0 0 1 09 | 1 1 0 1 0 1 | ROM 05-msb to adder
|
||||
1e|0 1 1 0 1 0 0 1 69 | 1 0 1 1 0 1 | RAM 13 to adder
|
||||
1f|1 1 1 0 1 0 1 0 ea | 0 1 1 0 1 0 | Adder to train and to RAM 13, CLOCK carry
|
||||
* ========================= ====================
|
||||
* only one of these signals these signals select
|
||||
* can be active at a time the output for the result
|
||||
* ------- SOURCE -------- ----- TARGET -----
|
||||
*
|
||||
******************
|
||||
result needs to be
|
||||
written back to RAM
|
||||
*/
|
||||
|
||||
TIMER_CALLBACK_MEMBER(changela_state::changela_scanline_callback)
|
||||
{
|
||||
int sy = param;
|
||||
|
||||
// clear the current scanline first
|
||||
const rectangle rect(0, 255, sy, sy);
|
||||
m_river_bitmap.fill(0x00, rect);
|
||||
m_obj0_bitmap.fill(0x00, rect);
|
||||
m_tree0_bitmap.fill(0x00, rect);
|
||||
m_tree1_bitmap.fill(0x00, rect);
|
||||
|
||||
draw_river(m_river_bitmap, sy);
|
||||
draw_obj0(m_obj0_bitmap, sy);
|
||||
draw_tree(m_tree0_bitmap, sy, 0);
|
||||
draw_tree(m_tree1_bitmap, sy, 1);
|
||||
|
||||
// Collision Detection
|
||||
for (int sx = 1; sx < 256; sx++)
|
||||
{
|
||||
u16 pix = m_river_bitmap.pix(sy, sx);
|
||||
const bool riv_col = (pix == 0x08 || pix == 0x09 || pix == 0x0a);
|
||||
|
||||
pix = m_river_bitmap.pix(sy, sx-1);
|
||||
const bool prev_col = (pix == 0x08 || pix == 0x09 || pix == 0x0a);
|
||||
|
||||
if (m_obj0_bitmap.pix(sy, sx) == 0x14) // Car Outline Color
|
||||
{
|
||||
// Tree 0 Collision
|
||||
if (m_tree0_bitmap.pix(sy, sx) != 0)
|
||||
m_tree0_col = 1;
|
||||
|
||||
// Tree 1 Collision
|
||||
if (m_tree1_bitmap.pix(sy, sx) != 0)
|
||||
m_tree1_col = 1;
|
||||
|
||||
// Hit Right Bank
|
||||
if (!riv_col && prev_col)
|
||||
m_right_bank_col = 1;
|
||||
|
||||
// Hit Left Bank
|
||||
if (riv_col && !prev_col)
|
||||
m_left_bank_col = 1;
|
||||
|
||||
// Boat Hit Shore
|
||||
if (riv_col)
|
||||
m_boat_shore_col = 1;
|
||||
}
|
||||
}
|
||||
if (!m_tree_collision_reset)
|
||||
{
|
||||
m_tree0_col = 0;
|
||||
m_tree1_col = 0;
|
||||
}
|
||||
if (!m_collision_reset)
|
||||
{
|
||||
m_left_bank_col = 0;
|
||||
m_right_bank_col = 0;
|
||||
m_boat_shore_col = 0;
|
||||
}
|
||||
|
||||
sy++;
|
||||
if (sy > 256) sy = 30;
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(sy), sy);
|
||||
}
|
||||
|
||||
u32 changela_state::screen_update_changela(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, m_river_bitmap, 0, 0, 0, 0, cliprect);
|
||||
copybitmap_trans(bitmap, m_obj0_bitmap, 0, 0, 0, 0, cliprect, 0);
|
||||
copybitmap_trans(bitmap, m_tree0_bitmap, 0, 0, 0, 0, cliprect, 0);
|
||||
copybitmap_trans(bitmap, m_tree1_bitmap, 0, 0, 0, 0, cliprect, 0);
|
||||
draw_obj1(bitmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void changela_state::changela_colors_w(offs_t offset, u8 data)
|
||||
{
|
||||
/* Each color is combined from 3 bits from open-collector outputs of ram.
|
||||
Each of the bits is connected to a 220, 470, or 1000 Ohm resistor.
|
||||
There is also a 680 Ohm pull-up resistor connected to 5V, and a
|
||||
2.2k resistor connected to GND. Thus these output voltages are obtained:
|
||||
Val | Vout
|
||||
000 | 0.766 (220 || 470 || 1k || 2.2k)
|
||||
001 | 0.855 (220 || 470 || 2.2k)
|
||||
010 | 0.984 (220 || 1k || 2.2k)
|
||||
011 | 1.136 (220 || 2.2k)
|
||||
100 | 1.455 (470 || 1k || 2.2k)
|
||||
101 | 1.814 (470 || 2.2k)
|
||||
110 | 2.514 (1k || 2.2k)
|
||||
111 | 3.819 (2.2k)
|
||||
Which were normalized to produce the following table: */
|
||||
|
||||
static const u8 color_table[8] = { 0, 7, 18, 31, 58, 88, 146, 255 };
|
||||
|
||||
int r, g, b;
|
||||
u32 c, color_index;
|
||||
|
||||
c = (data) | ((offset & 0x01) << 8); //* a0 used as D8 bit input
|
||||
c ^= 0x1ff; // active low
|
||||
|
||||
color_index = offset >> 1;
|
||||
color_index ^= 0x30; // A4 and A5 lines are negated
|
||||
|
||||
r = color_table[(c >> 0) & 0x07];
|
||||
g = color_table[(c >> 3) & 0x07];
|
||||
b = color_table[(c >> 6) & 0x07];
|
||||
|
||||
m_palette->set_pen_color(color_index,r,g,b);
|
||||
}
|
||||
|
||||
|
||||
void changela_state::changela_mem_device_select_w(u8 data)
|
||||
{
|
||||
/*
|
||||
(data & 0x07) possible settings:
|
||||
0 - not connected (no device)
|
||||
1 - ADR1 is 2114 RAM at U59 (state machine) (accessible range: 0x0000-0x003f)
|
||||
2 - ADR2 is 2128 RAM at U109 (River RAM) (accessible range: 0x0000-0x07ff)
|
||||
3 - ADR3 is 2128 RAM at U114 (Tree RAM) (accessible range: 0x0000-0x07ff)
|
||||
4 - ADR4 is 2732 ROM at U7 (Tree ROM) (accessible range: 0x0000-0x07ff)
|
||||
5 - SLOPE is ROM at U44 (state machine) (accessible range: 0x0000-0x07ff)
|
||||
*/
|
||||
m_mem_dev_selected = data & 0x07;
|
||||
m_tree_en = (data & 0x30) >> 4;
|
||||
}
|
||||
|
||||
void changela_state::changela_mem_device_w(offs_t offset, u8 data)
|
||||
{
|
||||
switch (m_mem_dev_selected)
|
||||
{
|
||||
case 1:
|
||||
for (int i = 0; i < 3; i++)
|
||||
m_stateram[(i * 0x40) + (offset & 0x3f)] = data & 0xf;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_riverram[offset] = data;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_treeram[offset] = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 changela_state::changela_mem_device_r(offs_t offset)
|
||||
{
|
||||
switch (m_mem_dev_selected)
|
||||
{
|
||||
case 1: return m_stateram[offset & 0x3f];
|
||||
case 2: return m_riverram[offset];
|
||||
case 3: return m_treeram[offset];
|
||||
case 4: return m_treerom[offset];
|
||||
case 5: return m_sloperom[offset];
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void changela_state::changela_slope_rom_addr_hi_w(u8 data)
|
||||
{
|
||||
m_sloperom_bank = (data & 0x03) << 9;
|
||||
}
|
||||
|
||||
void changela_state::changela_slope_rom_addr_lo_w(u8 data)
|
||||
{
|
||||
m_horizon = data;
|
||||
}
|
Loading…
Reference in New Issue
Block a user