// license:BSD-3-Clause
// copyright-holders:Angelo Salese
/*******************************************************************************************************************************************************
PC-6001 series (c) 1981 NEC
driver by Angelo Salese
TODO:
- Hook up tape loading, images that are floating around the net are already
ADC'ed, so they should be easy to implement (but not exactly faithful)
- cassette handling requires a decap of the MCU. It could be possible to
do some tight synch between the master CPU and a code simulation,but I think
it's not worth the effort...
- Identify and hook-up the FDC device, apparently PC-6001 and PC-6601 doesn't even use the same thing;
- PC-6601: mon r-0 type games doesn't seem to work at all on this system?
- PC-6001SR: get it to boot, also implement MK-2 compatibility mode (it changes the memory map to behave like the older versions)
- Currently rewriting the video part without the MC6847 for two reasons:
A) the later models have a custom video chip in the place of the MC6847,
so this implementation will be used in the end.
B) It's easier to me to see what the attribute vram does since I don't
have any docs atm.
TODO (game specific):
- (several AX* games, namely Galaxy Mission Part 1/2 and others): inputs doesn't work
- AX6 - Demo: When AY-based speech talks, other emus emulates the screen drawing to be a solid green (plain PC-6001) or solid white (Mk2 version),
but, according to an original video reference that I've seen, that screen should actually some kind of weird garbage on it ...
- AX6 - Powered Knight: doesn't work too well, according to the asm code it asks the player to press either 'B' or 'C' then a number but
nothing is shown on screen, other emus behaves the same, bad dump?
- Dawn Patrol (cart): presumably too slow;
(Mk2 mode 5 games)
- 3D Golf Simulation Super Version: gameplay / inputs seems broken
- American Truck: Screen is offset at the loading screen, loading bug?
- Castle Excellent: copyright text drawing is quite bogus, scans text in vertical instead of horizontal?
- Dezeni Land (ALL versions) / Hurry Fox 1/2: asks you to "load something", can't do it with current cassette kludge, also, for Dezeni Land(s) keyboard irqs
doesn't seem to work too well with halt opcode execution?
- Dezeni Land 1/4: dies after loading of main program
- Dezeni Land 2: dies at the "load something" screen with presumably wrong stack opcodes
- (MyCom BASIC games with multiple files): most of them refuses to run ... how to load them?
- Grobda: when "get ready" speech plays, screen should be full white but instead it's all black, same issue as AX-6 Demo?
- Pac-Man / Tiny Xevious 2: gameplay is too fast
- Salad no Kunino Tomato-Hime: can't start a play
- Space Harrier: inputs doesn't work properly
- The Black Onyx: dies when it attempts to save the character, that obviously means saving on the tape
- Yakyukyo / Punchball Mario: waits for an irq, check which one;
========================================================================================================================================================
PC-6001 (1981-09):
* CPU: Z80A @ 4 MHz
* ROM: 16KB + 4KB (chargen) - no kanji
* RAM: 16KB, it can be expanded to 32KB
* Text Mode: 32x16 and 2 colors
* Graphic Modes: 64x48 (9 colors), 128x192 (4 colors), 256x192 (2 colors)
* Sound: BEEP + PSG - Optional Voice Synth Cart
* Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
HOME/CLR key, INS key, DEL key, GRAPH key, Japanese syllabary
key, page key, STOP key, and cursor key (4 directions)
* 1 cartslot, optional floppy drive, optional serial 232 port, 2
joystick ports
PC-6001 mkII (1983-07):
* CPU: Z80A @ 4 MHz
* ROM: 32KB + 16KB (chargen) + 32KB (kanji) + 16KB (Voice Synth)
* RAM: 64KB
* Text Mode: same as PC-6001 with N60-BASIC; 40x20 and 15 colors with
N60M-BASIC
* Graphic Modes: same as PC-6001 with N60-BASIC; 80x40 (15 colors),
160x200 (15 colors), 320x200 (4 colors) with N60M-BASIC
* Sound: BEEP + PSG
* Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
HOME/CLR key, INS key, DEL key, CAPS key, GRAPH key, Japanese
syllabary key, page key, mode key, STOP key, and cursor key (4
directions)
* 1 cartslot, floppy drive, optional serial 232 port, 2 joystick ports
PC-6001 mkIISR (1984-12):
* CPU: Z80A @ 3.58 MHz
* ROM: 64KB + 16KB (chargen) + 32KB (kanji) + 32KB (Voice Synth)
* RAM: 64KB
* Text Mode: same as PC-6001/PC-6001mkII with N60-BASIC; 40x20, 40x25,
80x20, 80x25 and 15 colors with N66SR-BASIC
* Graphic Modes: same as PC-6001/PC-6001mkII with N60-BASIC; 80x40 (15 colors),
320x200 (15 colors), 640x200 (15 colors) with N66SR-BASIC
* Sound: BEEP + PSG + FM
* Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
HOME/CLR key, INS key, DEL key, CAPS key, GRAPH key, Japanese
syllabary key, page key, mode key, STOP key, and cursor key (4
directions)
* 1 cartslot, floppy drive, optional serial 232 port, 2 joystick ports
info from http://www.geocities.jp/retro_zzz/machines/nec/6001/spc60.html
==================================================================================
PC-6001 irq table:
irq vector 0x00: writes 0x00 to [$fa19] ;(unused)
irq vector 0x02: (A = 0, B = 0) tests ppi port c, does something with ay ports (plus more?) ;keyboard data ready, no kanji lock, no caps lock
irq vector 0x04: ;uart irq
irq vector 0x06: operates with $fa28, $fa2e, $fd1b ;timer irq
irq vector 0x08: tests ppi port c, puts port A to $fa1d,puts 0x02 to [$fa19] ;tape data ready
irq vector 0x0a: writes 0x00 to [$fa19] ;(unused)
irq vector 0x0c: writes 0x00 to [$fa19] ;(unused)
irq vector 0x0e: same as 2, (A = 0x03, B = 0x00) ;keyboard data ready, unknown type
irq vector 0x10: same as 2, (A = 0x03, B = 0x00) ;(unused)
irq vector 0x12: writes 0x10 to [$fa19] ;end of tape reached
irq vector 0x14: same as 2, (A = 0x00, B = 0x01) ;kanji lock enabled
irq vector 0x16: tests ppi port c, writes the result to $feca. ;joystick
irq vector 0x18: ;TVR (?)
irq vector 0x1a: ;Date
irq vector 0x1c: ;(unused)
irq vector 0x1e: ;(unused)
irq vector 0x20: ;voice
irq vector 0x22: ;VRTC (?)
irq vector 0x24: ;(unused)
irq vector 0x26: ;(unused)
*******************************************************************************************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "machine/i8255.h"
#include "machine/i8251.h"
#include "video/mc6847.h"
#include "sound/ay8910.h"
#include "sound/upd7752.h"
#include "sound/wave.h"
#include "imagedev/cassette.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
#include "formats/p6001_cas.h"
class pc6001_state : public driver_device
{
public:
pc6001_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_ppi(*this, "ppi8255"),
m_ram(*this, "ram"),
m_maincpu(*this, "maincpu"),
m_cassette(*this, "cassette"),
m_cas_hack(*this, "cas_hack"),
m_cart(*this, "cartslot"),
m_region_maincpu(*this, "maincpu"),
m_region_gfx1(*this, "gfx1"),
m_io_mode4_dsw(*this, "MODE4_DSW"),
m_io_p1(*this, "P1"),
m_io_p2(*this, "P2"),
m_io_key1(*this, "key1"),
m_io_key2(*this, "key2"),
m_io_key3(*this, "key3"),
m_io_key_modifiers(*this, "key_modifiers"),
m_bank1(*this, "bank1"),
m_bank2(*this, "bank2"),
m_bank3(*this, "bank3"),
m_bank4(*this, "bank4"),
m_bank5(*this, "bank5"),
m_bank6(*this, "bank6"),
m_bank7(*this, "bank7"),
m_bank8(*this, "bank8"),
m_palette(*this, "palette") { }
required_device<i8255_device> m_ppi;
optional_shared_ptr<UINT8> m_ram;
UINT8 *m_video_ram;
UINT8 m_irq_vector;
UINT8 m_cas_switch;
UINT8 m_sys_latch;
UINT8 m_timer_irq_mask;
UINT32 m_cas_offset;
UINT32 m_cas_maxsize;
emu_timer *m_timer_irq_timer;
UINT16 m_timer_hz_div;
UINT8 m_ex_vram_bank;
UINT8 m_bgcol_bank;
UINT8 m_exgfx_text_mode;
UINT8 m_exgfx_bitmap_mode;
UINT8 m_exgfx_2bpp_mode;
UINT8 m_bank_r0;
UINT8 m_bank_r1;
UINT8 m_gfx_bank_on;
UINT8 m_bank_w;
UINT8 m_bank_opt;
UINT8 m_timer_irq_mask2;
UINT8 m_timer_irq_vector;
UINT32 m_cgrom_bank_addr;
UINT8 m_sr_video_mode;
UINT8 m_port_c_8255;
UINT8 m_cur_keycode;
UINT8 m_sr_bank_r[8];
UINT8 m_sr_bank_w[8];
UINT8 m_kludge;
UINT32 m_old_key1;
UINT32 m_old_key2;
UINT32 m_old_key3;
DECLARE_WRITE8_MEMBER(pc6001_system_latch_w);
DECLARE_READ8_MEMBER(nec_ppi8255_r);
DECLARE_WRITE8_MEMBER(nec_ppi8255_w);
DECLARE_WRITE8_MEMBER(pc6001m2_bank_r0_w);
DECLARE_WRITE8_MEMBER(pc6001m2_bank_r1_w);
DECLARE_WRITE8_MEMBER(pc6001m2_bank_w0_w);
DECLARE_WRITE8_MEMBER(pc6001m2_opt_bank_w);
DECLARE_WRITE8_MEMBER(work_ram0_w);
DECLARE_WRITE8_MEMBER(work_ram1_w);
DECLARE_WRITE8_MEMBER(work_ram2_w);
DECLARE_WRITE8_MEMBER(work_ram3_w);
DECLARE_WRITE8_MEMBER(work_ram4_w);
DECLARE_WRITE8_MEMBER(work_ram5_w);
DECLARE_WRITE8_MEMBER(work_ram6_w);
DECLARE_WRITE8_MEMBER(work_ram7_w);
DECLARE_WRITE8_MEMBER(necmk2_ppi8255_w);
DECLARE_WRITE8_MEMBER(pc6001m2_system_latch_w);
DECLARE_WRITE8_MEMBER(pc6001m2_vram_bank_w);
DECLARE_WRITE8_MEMBER(pc6001m2_col_bank_w);
DECLARE_WRITE8_MEMBER(pc6001m2_0xf3_w);
DECLARE_WRITE8_MEMBER(pc6001m2_timer_adj_w);
DECLARE_WRITE8_MEMBER(pc6001m2_timer_irqv_w);
DECLARE_READ8_MEMBER(pc6001m2_bank_r0_r);
DECLARE_READ8_MEMBER(pc6001m2_bank_r1_r);
DECLARE_READ8_MEMBER(pc6001m2_bank_w0_r);
DECLARE_READ8_MEMBER(pc6601_fdc_r);
DECLARE_WRITE8_MEMBER(pc6601_fdc_w);
DECLARE_READ8_MEMBER(pc6001sr_bank_rn_r);
DECLARE_WRITE8_MEMBER(pc6001sr_bank_rn_w);
DECLARE_READ8_MEMBER(pc6001sr_bank_wn_r);
DECLARE_WRITE8_MEMBER(pc6001sr_bank_wn_w);
DECLARE_WRITE8_MEMBER(sr_work_ram0_w);
DECLARE_WRITE8_MEMBER(sr_work_ram1_w);
DECLARE_WRITE8_MEMBER(sr_work_ram2_w);
DECLARE_WRITE8_MEMBER(sr_work_ram3_w);
DECLARE_WRITE8_MEMBER(sr_work_ram4_w);
DECLARE_WRITE8_MEMBER(sr_work_ram5_w);
DECLARE_WRITE8_MEMBER(sr_work_ram6_w);
DECLARE_WRITE8_MEMBER(sr_work_ram7_w);
DECLARE_WRITE8_MEMBER(pc6001sr_mode_w);
DECLARE_WRITE8_MEMBER(pc6001sr_vram_bank_w);
DECLARE_WRITE8_MEMBER(pc6001sr_system_latch_w);
DECLARE_WRITE8_MEMBER(necsr_ppi8255_w);
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
DECLARE_PALETTE_INIT(pc6001);
DECLARE_MACHINE_RESET(pc6001m2);
DECLARE_PALETTE_INIT(pc6001m2);
DECLARE_MACHINE_RESET(pc6001sr);
UINT32 screen_update_pc6001(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
UINT32 screen_update_pc6001m2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
UINT32 screen_update_pc6001sr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(pc6001_interrupt);
INTERRUPT_GEN_MEMBER(pc6001sr_interrupt);
TIMER_CALLBACK_MEMBER(audio_callback);
TIMER_DEVICE_CALLBACK_MEMBER(cassette_callback);
TIMER_DEVICE_CALLBACK_MEMBER(keyboard_callback);
DECLARE_READ8_MEMBER(pc6001_8255_porta_r);
DECLARE_WRITE8_MEMBER(pc6001_8255_porta_w);
DECLARE_READ8_MEMBER(pc6001_8255_portb_r);
DECLARE_WRITE8_MEMBER(pc6001_8255_portb_w);
DECLARE_WRITE8_MEMBER(pc6001_8255_portc_w);
DECLARE_READ8_MEMBER(pc6001_8255_portc_r);
IRQ_CALLBACK_MEMBER(pc6001_irq_callback);
protected:
required_device<cpu_device> m_maincpu;
optional_device<cassette_image_device> m_cassette;
optional_device<generic_slot_device> m_cas_hack;
required_device<generic_slot_device> m_cart;
required_memory_region m_region_maincpu;
required_memory_region m_region_gfx1;
required_ioport m_io_mode4_dsw;
required_ioport m_io_p1;
required_ioport m_io_p2;
required_ioport m_io_key1;
required_ioport m_io_key2;
required_ioport m_io_key3;
required_ioport m_io_key_modifiers;
required_memory_bank m_bank1;
optional_memory_bank m_bank2;
optional_memory_bank m_bank3;
optional_memory_bank m_bank4;
optional_memory_bank m_bank5;
optional_memory_bank m_bank6;
optional_memory_bank m_bank7;
optional_memory_bank m_bank8;
required_device<palette_device> m_palette;
memory_region *m_cart_rom;
void draw_gfx_mode4(bitmap_ind16 &bitmap,const rectangle &cliprect,int attr);
void draw_bitmap_2bpp(bitmap_ind16 &bitmap,const rectangle &cliprect, int attr);
void draw_tile_3bpp(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int tile,int attr);
void draw_tile_text(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int tile,int attr,int has_mc6847);
void draw_border(bitmap_ind16 &bitmap,const rectangle &cliprect,int attr,int has_mc6847);
void pc6001_screen_draw(bitmap_ind16 &bitmap,const rectangle &cliprect, int has_mc6847);
UINT8 check_joy_press();
UINT8 check_keyboard_press();
void vram_bank_change(UINT8 vram_bank);
};
/* PC6001mk2 specific */
/* PC6001SR specific */
#define IRQ_LOG (0)
void pc6001_state::video_start()
{
#if 0
m6847_config cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.type = M6847_VERSION_M6847T1_NTSC;
cfg.get_attributes = pc6001_get_attributes;
cfg.get_video_ram = pc6001_get_video_ram;
cfg.get_char_rom = pc6001_get_char_rom;
m6847_init(machine(), &cfg);
#endif
m_video_ram = auto_alloc_array(machine(), UINT8, 0x4000);
}
/* this is known as gfx mode 4 */
void pc6001_state::draw_gfx_mode4(bitmap_ind16 &bitmap,const rectangle &cliprect,int attr)
{
int x,y,xi;
int fgcol,color;
int col_setting;
static const UINT8 pen_gattr[4][4] = {
{ 0, 1, 6, 2 }, //Red / Blue
{ 0, 6, 1, 2 }, //Blue / Red
{ 0, 5, 2, 2 }, //Pink / Green
{ 0, 2, 5, 2 }, //Green / Pink
};
static const UINT8 pen_wattr[4][4] = {
{ 0, 1, 6, 7 }, //Red / Blue
{ 0, 6, 1, 7 }, //Blue / Red
{ 0, 5, 2, 7 }, //Pink / Green
{ 0, 2, 5, 7 }, //Green / Pink
};
col_setting = m_io_mode4_dsw->read() & 7;
if((attr & 0x0c) != 0x0c)
popmessage("Mode 4 vram attr != 0x0c, contact MESSdev");
for(y=0;y<192;y++)
{
for(x=0;x<32;x++)
{
int tile = m_video_ram[(x+(y*32))+0x200];
if(col_setting == 0x00) //monochrome
{
for(xi=0;xi<8;xi++)
{
fgcol = (attr & 2) ? 7 : 2;
color = ((tile)>>(7-xi) & 1) ? fgcol : 0;
bitmap.pix16((y+24), (x*8+xi)+32) = m_palette->pen(color);
}
}
else
{
for(xi=0;xi<4;xi++)
{
fgcol = ((tile)>>(6-(xi*2)) & 3);
color = (attr & 2) ? (pen_wattr[col_setting-1][fgcol]) : (pen_gattr[col_setting-1][fgcol]);
bitmap.pix16((y+24), ((x*8+xi*2)+0)+32) = m_palette->pen(color);
bitmap.pix16((y+24), ((x*8+xi*2)+1)+32) = m_palette->pen(color);
}
}
}
}
}
void pc6001_state::draw_bitmap_2bpp(bitmap_ind16 &bitmap,const rectangle &cliprect, int attr)
{
int color,x,y,xi,yi;
int shrink_x = 2*4;
int shrink_y = (attr & 8) ? 1 : 2;
int w = (shrink_x == 8) ? 32 : 16;
int col_bank = ((attr & 2)<<1);
if(attr & 4)
{
for(y=0;y<(192/shrink_y);y++)
{
for(x=0;x<w;x++)
{
int tile = m_video_ram[(x+(y*32))+0x200];
for(yi=0;yi<shrink_y;yi++)
{
for(xi=0;xi<shrink_x;xi++)
{
int i;
i = (shrink_x == 8) ? (xi & 0x06) : (xi & 0x0c)>>1;
color = ((tile >> i) & 3)+8;
color+= col_bank;
bitmap.pix16(((y*shrink_y+yi)+24), (x*shrink_x+((shrink_x-1)-xi))+32) = m_palette->pen(color);
}
}
}
}
}
else /* TODO: clean this up */
{
for(y=0;y<(192/shrink_y);y+=3)
{
for(x=0;x<w;x++)
{
int tile = m_video_ram[(x+((y/3)*32))+0x200];
for(yi=0;yi<shrink_y;yi++)
{
for(xi=0;xi<shrink_x;xi++)
{
int i;
i = (shrink_x == 8) ? (xi & 0x06) : (xi & 0x0c)>>1;
color = ((tile >> i) & 3)+8;
color+= col_bank;
bitmap.pix16((((y+0)*shrink_y+yi)+24), (x*shrink_x+((shrink_x-1)-xi))+32) = m_palette->pen(color);
bitmap.pix16((((y+1)*shrink_y+yi)+24), (x*shrink_x+((shrink_x-1)-xi))+32) = m_palette->pen(color);
bitmap.pix16((((y+2)*shrink_y+yi)+24), (x*shrink_x+((shrink_x-1)-xi))+32) = m_palette->pen(color);
}
}
}
}
}
}
void pc6001_state::draw_tile_3bpp(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int tile,int attr)
{
int color,pen,xi,yi;
if(attr & 0x10) //2x2 squares on a single cell
pen = (tile & 0x70)>>4;
else //2x3
pen = (tile & 0xc0) >> 6 | (attr & 2)<<1;
for(yi=0;yi<12;yi++)
{
for(xi=0;xi<8;xi++)
{
int i;
i = (xi & 4)>>2; //x-axis
if(attr & 0x10) //2x2
{
i+= (yi >= 6) ? 2 : 0; //y-axis
}
else //2x3
{
i+= (yi & 4)>>1; //y-axis 1
i+= (yi & 8)>>1; //y-axis 2
}
color = ((tile >> i) & 1) ? pen+8 : 0;
bitmap.pix16(((y*12+(11-yi))+24), (x*8+(7-xi))+32) = m_palette->pen(color);
}
}
}
void pc6001_state::draw_tile_text(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int tile,int attr,int has_mc6847)
{
int xi,yi,pen,fgcol,color;
UINT8 *gfx_data = m_region_gfx1->base();
for(yi=0;yi<12;yi++)
{
for(xi=0;xi<8;xi++)
{
pen = gfx_data[(tile*0x10)+yi]>>(7-xi) & 1;
if(has_mc6847)
{
fgcol = (attr & 2) ? 0x12 : 0x10;
if(attr & 1)
color = pen ? (fgcol+0) : (fgcol+1);
else
color = pen ? (fgcol+1) : (fgcol+0);
}
else
{
fgcol = (attr & 2) ? 2 : 7;
if(attr & 1)
color = pen ? 0 : fgcol;
else
color = pen ? fgcol : 0;
}
bitmap.pix16(((y*12+yi)+24), (x*8+xi)+32) = m_palette->pen(color);
}
}
}
void pc6001_state::draw_border(bitmap_ind16 &bitmap,const rectangle &cliprect,int attr,int has_mc6847)
{
int x,y,color;
for(y=0;y<240;y++)
{
for(x=0;x<320;x++)
{
if(!has_mc6847) //mk2 border color is always black
color = 0;
else if((attr & 0x90) == 0x80) //2bpp
color = ((attr & 2)<<1) + 8;
else if((attr & 0x90) == 0x90) //1bpp
color = (attr & 2) ? 7 : 2;
else
color = 0; //FIXME: other modes not yet checked
bitmap.pix16(y, x) = m_palette->pen(color);
}
}
}
void pc6001_state::pc6001_screen_draw(bitmap_ind16 &bitmap,const rectangle &cliprect, int has_mc6847)
{
int x,y;
int tile,attr;
attr = m_video_ram[0];
draw_border(bitmap,cliprect,attr,has_mc6847);
if(attr & 0x80) // gfx mode
{
if(attr & 0x10) // 256x192x1 mode (FIXME: might be a different trigger)
{
draw_gfx_mode4(bitmap,cliprect,attr);
}
else // 128x192x2 mode
{
draw_bitmap_2bpp(bitmap,cliprect,attr);
}
}
else // text mode
{
for(y=0;y<16;y++)
{
for(x=0;x<32;x++)
{
tile = m_video_ram[(x+(y*32))+0x200];
attr = m_video_ram[(x+(y*32)) & 0x1ff];
if(attr & 0x40)
{
draw_tile_3bpp(bitmap,cliprect,x,y,tile,attr);
}
else
{
draw_tile_text(bitmap,cliprect,x,y,tile,attr,has_mc6847);
}
}
}
}
}
UINT32 pc6001_state::screen_update_pc6001(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
pc6001_screen_draw(bitmap,cliprect,1);
return 0;
}
UINT32 pc6001_state::screen_update_pc6001m2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int x,y,tile,attr;
/* note: bitmap mode have priority over everything else, check American Truck */
if(m_exgfx_bitmap_mode)
{
int count,color,i;
count = 0;
for(y=0;y<200;y++)
{
for(x=0;x<160;x+=4)
{
for(i=0;i<4;i++)
{
int pen[2];
#if 0
/* palette reference: */
static const UINT8 pal_num[] = { 0x00, 0x04, 0x01, 0x05,
0x02, 0x06, 0x03, 0x07,
0x08, 0x0c, 0x09, 0x0d,
0x0a, 0x0e, 0x0b, 0x0f };
color |= pal_num[(pen[0] & 3) | ((pen[1] & 3) << 2)];
#endif
pen[0] = m_video_ram[count+0x0000] >> (6-i*2) & 3;
pen[1] = m_video_ram[count+0x2000] >> (6-i*2) & 3;
color = 0x10;
color |= ((pen[0] & 1) << 2);
color |= ((pen[0] & 2) >> 1);
color |= ((pen[1] & 1) << 1);
color |= ((pen[1] & 2) << 2);
if (cliprect.contains((x+i)*2+0, y))
bitmap.pix16(y, (x+i)*2+0) = m_palette->pen(color);
if (cliprect.contains((x+i)*2+1, y))
bitmap.pix16(y, (x+i)*2+1) = m_palette->pen(color);
}
count++;
}
}
}
else if(m_exgfx_2bpp_mode)
{
int count,color,i;
count = 0;
for(y=0;y<200;y++)
{
for(x=0;x<320;x+=8)
{
for(i=0;i<8;i++)
{
int pen[2];
#if 0
/* palette reference: */
static const UINT8 pal_num[] = { 0x00, 0x04, 0x01, 0x05 };
color |= pal_num[(pen[0] & 1) | ((pen[1] & 1) << 1)];
#endif
pen[0] = m_video_ram[count+0x0000] >> (7-i) & 1;
pen[1] = m_video_ram[count+0x2000] >> (7-i) & 1;
if(m_bgcol_bank & 4) //PC-6001 emulation mode
{
color = 0x08;
color |= (pen[0]) | (pen[1]<<1);
color |= (m_bgcol_bank & 1) << 2;
}
else //Mk-2 mode
{
color = 0x10;
color |= ((pen[0] & 1) << 2);
color |= ((pen[1] & 1) >> 0);
color |= ((m_bgcol_bank & 1) << 1);
color |= ((m_bgcol_bank & 2) << 2);
}
if (cliprect.contains(x+i, y))
bitmap.pix16(y, (x+i)) = m_palette->pen(color);
}
count++;
}
}
}
else if(m_exgfx_text_mode)
{
int xi,yi,pen,fgcol,bgcol,color;
UINT8 *gfx_data = m_region_gfx1->base();
for(y=0;y<20;y++)
{
for(x=0;x<40;x++)
{
/*
exgfx attr format:
x--- ---- rom bank select
-xxx ---- bg color
---- xxxx fg color
Note that the exgfx banks a different gfx ROM
*/
tile = m_video_ram[(x+(y*40))+0x400] + 0x200;
attr = m_video_ram[(x+(y*40)) & 0x3ff];
tile+= ((attr & 0x80) << 1);
for(yi=0;yi<12;yi++)
{
for(xi=0;xi<8;xi++)
{
pen = gfx_data[(tile*0x10)+yi]>>(7-xi) & 1;
fgcol = (attr & 0x0f) + 0x10;
bgcol = ((attr & 0x70) >> 4) + 0x10 + ((m_bgcol_bank & 2) << 2);
color = pen ? fgcol : bgcol;
if (cliprect.contains(x*8+xi, y*12+yi))
bitmap.pix16(((y*12+yi)), (x*8+xi)) = m_palette->pen(color);
}
}
}
}
}
else
{
attr = m_video_ram[0];
pc6001_screen_draw(bitmap,cliprect,0);
}
return 0;
}
UINT32 pc6001_state::screen_update_pc6001sr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int x,y,tile,attr;
int xi,yi,pen,fgcol,bgcol,color;
UINT8 *gfx_data = m_region_gfx1->base();
if(m_sr_video_mode & 8) // text mode
{
for(y=0;y<20;y++)
{
for(x=0;x<40;x++)
{
tile = m_video_ram[(x+(y*40))*2+0];
attr = m_video_ram[(x+(y*40))*2+1];
tile+= ((attr & 0x80) << 1);
for(yi=0;yi<12;yi++)
{
for(xi=0;xi<8;xi++)
{
pen = gfx_data[(tile*0x10)+yi]>>(7-xi) & 1;
fgcol = (attr & 0x0f) + 0x10;
bgcol = ((attr & 0x70) >> 4) + 0x10 + ((m_bgcol_bank & 2) << 2);
color = pen ? fgcol : bgcol;
if (cliprect.contains(x*8+xi, y*12+yi))
bitmap.pix16(((y*12+yi)), (x*8+xi)) = m_palette->pen(color);
}
}
}
}
}
else //4bpp bitmap mode (TODO)
{
int count;
count = 0;
for(y=0;y<200;y+=2)
{
for(x=0;x<320;x+=4)
{
color = m_video_ram[count] & 0x0f;
if (cliprect.contains(x+0, y+0))
bitmap.pix16((y+0), (x+0)) = m_palette->pen(color+0x10);
color = (m_video_ram[count] & 0xf0) >> 4;
if (cliprect.contains(x+1, y+0))
bitmap.pix16((y+0), (x+1)) = m_palette->pen(color+0x10);
color = m_video_ram[count+1] & 0x0f;
if (cliprect.contains(x+2, y+0))
bitmap.pix16((y+0), (x+2)) = m_palette->pen(color+0x10);
color = (m_video_ram[count+1] & 0xf0) >> 4;
if (cliprect.contains(x+3, y+0))
bitmap.pix16((y+0), (x+3)) = m_palette->pen(color+0x10);
color = m_video_ram[count+2] & 0x0f;
if (cliprect.contains(x+0, y+1))
bitmap.pix16((y+1), (x+0)) = m_palette->pen(color+0x10);
color = (m_video_ram[count+2] & 0xf0) >> 4;
if (cliprect.contains(x+1, y+1))
bitmap.pix16((y+1), (x+1)) = m_palette->pen(color+0x10);
color = m_video_ram[count+3] & 0x0f;
if (cliprect.contains(x+2, y+1))
bitmap.pix16((y+1), (x+2)) = m_palette->pen(color+0x10);
color = (m_video_ram[count+3] & 0xf0) >> 4;
if (cliprect.contains(x+3, y+1))
bitmap.pix16((y+1), (x+3)) = m_palette->pen(color+0x10);
count+=4;
}
}
}
return 0;
}
WRITE8_MEMBER(pc6001_state::pc6001_system_latch_w)
{
static const UINT16 startaddr[] = {0xC000, 0xE000, 0x8000, 0xA000 };
m_video_ram = m_ram + startaddr[(data >> 1) & 0x03] - 0x8000;
if((!(m_sys_latch & 8)) && data & 0x8) //PLAY tape cmd
{
m_cas_switch = 1;
//m_cassette->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_PLAY,CASSETTE_MASK_UISTATE);
}
if((m_sys_latch & 8) && ((data & 0x8) == 0)) //STOP tape cmd
{
m_cas_switch = 0;
//m_cassette->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_STOPPED,CASSETTE_MASK_UISTATE);
//m_irq_vector = 0x00;
//m_maincpu->set_input_line(0, ASSERT_LINE);
}
m_sys_latch = data;
m_timer_irq_mask = data & 1;
//printf("%02x\n",data);
}
#if 0
ATTR_CONST pc6001_state::UINT8 pc6001_get_attributes(UINT8 c,int scanline, int pos)
{
UINT8 result = 0x00;
UINT8 val = m_video_ram [(scanline / 12) * 0x20 + pos];
if (val & 0x01) {
result |= M6847_INV;
}
if (val & 0x40)
result |= M6847_AG | M6847_GM1; //TODO
result |= M6847_INTEXT; // always use external ROM
return result;
}
const pc6001_state::UINT8 *pc6001_get_video_ram(int scanline)
{
return m_video_ram +0x0200+ (scanline / 12) * 0x20;
}
UINT8 pc6001_state::pc6001_get_char_rom(UINT8 ch, int line)
{
UINT8 *gfx = m_region_gfx1->base();
return gfx[ch*16+line];
}
#endif
READ8_MEMBER(pc6001_state::nec_ppi8255_r)
{
if (offset==2)
return m_port_c_8255;
else if(offset==0)
{
UINT8 res;
res = m_cur_keycode;
//m_cur_keycode = 0;
return res;
}
return m_ppi->read(space, offset);
}
WRITE8_MEMBER(pc6001_state::nec_ppi8255_w)
{
if (offset==3)
{
if(data & 1)
m_port_c_8255 |= 1<<((data>>1)&0x07);
else
m_port_c_8255 &= ~(1<<((data>>1)&0x07));
switch(data) {
case 0x08: m_port_c_8255 |= 0x88; break;
case 0x09: m_port_c_8255 &= 0xf7; break;
case 0x0c: m_port_c_8255 |= 0x28; break;
case 0x0d: m_port_c_8255 &= 0xf7; break;
default: break;
}
m_port_c_8255 |= 0xa8;
{
//printf("%02x\n",data);
if ((data & 0x0f) == 0x05 && m_cart_rom)
m_bank1->set_base(m_cart_rom->base() + 0x2000);
if ((data & 0x0f) == 0x04)
m_bank1->set_base(m_region_gfx1->base());
}
}
m_ppi->write(space,offset,data);
}
static ADDRESS_MAP_START(pc6001_map, AS_PROGRAM, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x3fff) AM_ROM AM_WRITENOP
//AM_RANGE(0x4000, 0x5fff) // mapped by the cartslot
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank1")
AM_RANGE(0x8000, 0xffff) AM_RAM AM_SHARE("ram")
ADDRESS_MAP_END
static ADDRESS_MAP_START( pc6001_io , AS_IO, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x80, 0x80) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
AM_RANGE(0x81, 0x81) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
AM_RANGE(0x90, 0x93) AM_MIRROR(0x0c) AM_READWRITE(nec_ppi8255_r, nec_ppi8255_w)
AM_RANGE(0xa0, 0xa0) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, address_w)
AM_RANGE(0xa1, 0xa1) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, data_w)
AM_RANGE(0xa2, 0xa2) AM_MIRROR(0x0c) AM_DEVREAD("ay8910", ay8910_device, data_r)
AM_RANGE(0xa3, 0xa3) AM_MIRROR(0x0c) AM_WRITENOP
AM_RANGE(0xb0, 0xb0) AM_MIRROR(0x0f) AM_WRITE(pc6001_system_latch_w)
AM_RANGE(0xd0, 0xd3) AM_MIRROR(0x0c) AM_NOP // disk device
ADDRESS_MAP_END
/*
ROM_REGION( 0x28000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom.62", 0x10000, 0x8000, CRC(950ac401) SHA1(fbf195ba74a3b0f80b5a756befc96c61c2094182) )
ROM_LOAD( "voicerom.62", 0x18000, 0x4000, CRC(49b4f917) SHA1(1a2d18f52ef19dc93da3d65f19d3abbd585628af) )
ROM_LOAD( "cgrom60.62", 0x1c000, 0x2000, CRC(81eb5d95) SHA1(53d8ae9599306ff23bf95208d2f6cc8fed3fc39f) )
ROM_LOAD( "cgrom60m.62", 0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
ROM_LOAD( "kanjirom.62", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
*/
#define BASICROM(_v_) \
0x10000+0x2000*_v_
#define VOICEROM(_v_) \
0x18000+0x2000*_v_
#define TVROM(_v_) \
0x1c000+0x2000*_v_
#define KANJIROM(_v_) \
0x20000+0x2000*_v_
#define WRAM(_v_) \
0x28000+0x2000*_v_
#define EXWRAM(_v_) \
0x38000+0x2000*_v_
#define EXROM(_v_) \
0x48000+0x2000*_v_
#define INVALID(_v_) \
0x4c000+0x2000*_v_
/* FIXME: some comments aren't right */
static const UINT32 banksw_table_r0[0x10*4][4] = {
/* 0 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ TVROM(0), TVROM(1), VOICEROM(0), VOICEROM(1) }, //0x02: tv rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ TVROM(1), BASICROM(1), VOICEROM(0), BASICROM(3) }, //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), TVROM(2), BASICROM(2), VOICEROM(1) }, //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), TVROM(2), EXROM(0), VOICEROM(1) }, //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
{ TVROM(1), EXROM(0), VOICEROM(0), EXROM(0) }, //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(0), WRAM(1), WRAM(2), WRAM(3) }, //0x0d: ram 0 & 1 / ram 2 & 3
{ EXWRAM(0), EXWRAM(1), EXWRAM(2), EXWRAM(3) }, //0x0e: exram 0 & 1 / exram 2 & 3
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 1 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ KANJIROM(0), KANJIROM(1), KANJIROM(0), KANJIROM(1) }, //0x02: tv rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ KANJIROM(0), BASICROM(1), KANJIROM(0), BASICROM(3) }, //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), KANJIROM(1), BASICROM(2), KANJIROM(1) }, //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), KANJIROM(1), EXROM(0), KANJIROM(1) }, //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
{ KANJIROM(0), EXROM(0), KANJIROM(0), EXROM(0) }, //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(0), WRAM(1), WRAM(2), WRAM(3) }, //0x0d: ram 0 & 1 / ram 2 & 3
{ EXWRAM(0), EXWRAM(1), EXWRAM(2), EXWRAM(3) }, //0x0e: exram 0 & 1 / exram 2 & 3
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 2 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ TVROM(0), TVROM(1), VOICEROM(0), VOICEROM(1) }, //0x02: tv rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ TVROM(1), BASICROM(1), VOICEROM(0), BASICROM(3) }, //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), TVROM(2), BASICROM(2), VOICEROM(1) }, //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), TVROM(2), EXROM(0), VOICEROM(1) }, //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
{ TVROM(1), EXROM(0), VOICEROM(0), EXROM(0) }, //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(0), WRAM(1), WRAM(2), WRAM(3) }, //0x0d: ram 0 & 1 / ram 2 & 3
{ EXWRAM(0), EXWRAM(1), EXWRAM(2), EXWRAM(3) }, //0x0e: exram 0 & 1 / exram 2 & 3
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 3 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ KANJIROM(2), KANJIROM(3), KANJIROM(2), KANJIROM(3) }, //0x02: tv rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ KANJIROM(2), BASICROM(1), KANJIROM(2), BASICROM(3) }, //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), KANJIROM(3), BASICROM(2), KANJIROM(3) }, //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), KANJIROM(3), EXROM(0), KANJIROM(3) }, //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
{ KANJIROM(2), EXROM(0), KANJIROM(2), EXROM(0) }, //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(0), WRAM(1), WRAM(2), WRAM(3) }, //0x0d: ram 0 & 1 / ram 2 & 3
{ EXWRAM(0), EXWRAM(1), EXWRAM(2), EXWRAM(3) }, //0x0e: exram 0 & 1 / exram 2 & 3
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) } //0x0f: <invalid setting>
};
static const UINT32 banksw_table_r1[0x10*4][4] = {
/* 0 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ VOICEROM(0), VOICEROM(1), VOICEROM(0), VOICEROM(1) }, //0x02: voice rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ VOICEROM(0), BASICROM(1), VOICEROM(0), BASICROM(3) }, //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), VOICEROM(1), BASICROM(2), VOICEROM(1) }, //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), VOICEROM(1), EXROM(0), VOICEROM(1) }, //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
{ VOICEROM(0), EXROM(0), VOICEROM(0), EXROM(0) }, //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(4), WRAM(5), WRAM(6), WRAM(7) }, //0x0d: ram 4 & 5 / ram 6 & 7
{ EXWRAM(4), EXWRAM(5), EXWRAM(6), EXWRAM(7) }, //0x0e: exram 4 & 5 / exram 6 & 7
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 1 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ KANJIROM(0), KANJIROM(1), KANJIROM(0), KANJIROM(1) }, //0x02: kanji rom 0 & 1 / kanji rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ KANJIROM(0), BASICROM(1), KANJIROM(0), BASICROM(3) }, //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), KANJIROM(1), BASICROM(2), KANJIROM(1) }, //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), KANJIROM(1), EXROM(0), KANJIROM(1) }, //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
{ KANJIROM(0), EXROM(0), KANJIROM(0), EXROM(0) }, //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(4), WRAM(5), WRAM(6), WRAM(7) }, //0x0d: ram 4 & 5 / ram 6 & 7
{ EXWRAM(4), EXWRAM(5), EXWRAM(6), EXWRAM(7) }, //0x0e: exram 4 & 5 / exram 6 & 7
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 2 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ VOICEROM(0), VOICEROM(1), VOICEROM(0), VOICEROM(1) }, //0x02: voice rom 0 & 1 / voice rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ VOICEROM(0), BASICROM(1), VOICEROM(0), BASICROM(3) }, //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), VOICEROM(1), BASICROM(2), VOICEROM(1) }, //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), VOICEROM(1), EXROM(0), VOICEROM(1) }, //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
{ VOICEROM(0), EXROM(0), VOICEROM(0), EXROM(0) }, //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(4), WRAM(5), WRAM(6), WRAM(7) }, //0x0d: ram 4 & 5 / ram 6 & 7
{ EXWRAM(4), EXWRAM(5), EXWRAM(6), EXWRAM(7) }, //0x0e: exram 4 & 5 / exram 6 & 7
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x0f: <invalid setting>
/* 3 */
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) }, //0x00: <invalid setting>
{ BASICROM(0), BASICROM(1), BASICROM(2), BASICROM(3) }, //0x01: basic rom 0 & 1 / basic rom 2 & 3
{ KANJIROM(2), KANJIROM(3), KANJIROM(2), KANJIROM(3) }, //0x02: kanji rom 0 & 1 / kanji rom 0 & 1
{ EXROM(1), EXROM(1), EXROM(1), EXROM(1) }, //0x03: ex rom 1 & 1 / ex rom 1 & 1
{ EXROM(0), EXROM(0), EXROM(0), EXROM(0) }, //0x04: ex rom 0 & 0 / ex rom 0 & 0
{ KANJIROM(2), BASICROM(1), KANJIROM(2), BASICROM(3) }, //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
{ BASICROM(0), KANJIROM(3), BASICROM(2), KANJIROM(3) }, //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
{ EXROM(0), EXROM(1), EXROM(0), EXROM(1) }, //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
{ EXROM(1), EXROM(0), EXROM(1), EXROM(0) }, //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
{ EXROM(1), BASICROM(1), EXROM(1), BASICROM(3) }, //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
{ BASICROM(0), EXROM(1), BASICROM(2), EXROM(1) }, //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
{ EXROM(0), KANJIROM(3), EXROM(0), KANJIROM(3) }, //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
{ KANJIROM(2), EXROM(0), KANJIROM(2), EXROM(0) }, //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
{ WRAM(4), WRAM(5), WRAM(6), WRAM(7) }, //0x0d: ram 4 & 5 / ram 6 & 7
{ EXWRAM(4), EXWRAM(5), EXWRAM(6), EXWRAM(7) }, //0x0e: exram 4 & 5 / exram 6 & 7
{ INVALID(0), INVALID(0), INVALID(0), INVALID(0) } //0x0f: <invalid setting>
};
WRITE8_MEMBER(pc6001_state::pc6001m2_bank_r0_w)
{
UINT8 *ROM = m_region_maincpu->base();
UINT8 *gfx_data = m_region_gfx1->base();
// bankaddress = 0x10000 + (0x4000 * ((data & 0x40)>>6));
// membank(1)->set_base(&ROM[bankaddress]);
m_bank_r0 = data;
// printf("%02x BANK | %02x\n",data,m_bank_opt);
m_bank1->set_base(&ROM[banksw_table_r0[(data & 0xf)+(m_bank_opt*0x10)][0]]);
m_bank2->set_base(&ROM[banksw_table_r0[(data & 0xf)+(m_bank_opt*0x10)][1]]);
m_bank3->set_base(&ROM[banksw_table_r0[((data & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
if(!m_gfx_bank_on)
m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
else
m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
}
WRITE8_MEMBER(pc6001_state::pc6001m2_bank_r1_w)
{
UINT8 *ROM = m_region_maincpu->base();
// bankaddress = 0x10000 + (0x4000 * ((data & 0x40)>>6));
// membank(1)->set_base(&ROM[bankaddress]);
m_bank_r1 = data;
// printf("%02x BANK\n",data);
m_bank5->set_base(&ROM[banksw_table_r1[(data & 0xf)+(m_bank_opt*0x10)][0]]);
m_bank6->set_base(&ROM[banksw_table_r1[(data & 0xf)+(m_bank_opt*0x10)][1]]);
m_bank7->set_base(&ROM[banksw_table_r1[((data & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
m_bank8->set_base(&ROM[banksw_table_r1[((data & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
}
WRITE8_MEMBER(pc6001_state::pc6001m2_bank_w0_w)
{
m_bank_w = data;
}
WRITE8_MEMBER(pc6001_state::pc6001m2_opt_bank_w)
{
UINT8 *ROM = m_region_maincpu->base();
UINT8 *gfx_data = m_region_gfx1->base();
/*
0 - TVROM / VOICE ROM
1 - KANJI ROM bank 0
2 - KANJI ROM bank 1
3 - TVROM / VOICE ROM
*/
m_bank_opt = data & 3;
m_bank1->set_base(&ROM[banksw_table_r0[(m_bank_r0 & 0xf)+(m_bank_opt*0x10)][0]]);
m_bank2->set_base(&ROM[banksw_table_r0[(m_bank_r0 & 0xf)+(m_bank_opt*0x10)][1]]);
m_bank3->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
if(!m_gfx_bank_on)
m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
else
m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
m_bank5->set_base(&ROM[banksw_table_r1[(m_bank_r1 & 0xf)+(m_bank_opt*0x10)][0]]);
m_bank6->set_base(&ROM[banksw_table_r1[(m_bank_r1 & 0xf)+(m_bank_opt*0x10)][1]]);
m_bank7->set_base(&ROM[banksw_table_r1[((m_bank_r1 & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
m_bank8->set_base(&ROM[banksw_table_r1[((m_bank_r1 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
}
WRITE8_MEMBER(pc6001_state::work_ram0_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x01) ? WRAM(0) : EXWRAM(0))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram1_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x01) ? WRAM(1) : EXWRAM(1))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram2_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x04) ? WRAM(2) : EXWRAM(2))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram3_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x04) ? WRAM(3) : EXWRAM(3))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram4_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x10) ? WRAM(4) : EXWRAM(4))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram5_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x10) ? WRAM(5) : EXWRAM(5))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram6_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x40) ? WRAM(6) : EXWRAM(6))] = data;
}
WRITE8_MEMBER(pc6001_state::work_ram7_w)
{
UINT8 *ROM = m_region_maincpu->base();
ROM[offset+((m_bank_w & 0x40) ? WRAM(7) : EXWRAM(7))] = data;
}
WRITE8_MEMBER(pc6001_state::necmk2_ppi8255_w)
{
if (offset==3)
{
if(data & 1)
m_port_c_8255 |= 1<<((data>>1)&0x07);
else
m_port_c_8255 &= ~(1<<((data>>1)&0x07));
switch(data) {
case 0x08: m_port_c_8255 |= 0x88; break;
case 0x09: m_port_c_8255 &= 0xf7; break;
case 0x0c: m_port_c_8255 |= 0x28; break;
case 0x0d: m_port_c_8255 &= 0xf7; break;
default: break;
}
m_port_c_8255 |= 0xa8;
{
UINT8 *ROM = m_region_maincpu->base();
UINT8 *gfx_data = m_region_gfx1->base();
//printf("%02x\n",data);
if((data & 0x0f) == 0x05)
{
m_gfx_bank_on = 0;
m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
}
if((data & 0x0f) == 0x04)
{
m_gfx_bank_on = 1;
m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
}
}
}
m_ppi->write(space,offset,data);
}
void pc6001_state::vram_bank_change(UINT8 vram_bank)
{
UINT8 *work_ram = m_region_maincpu->base();
// popmessage("%02x",vram_bank);
switch(vram_bank & 0x66)
{
case 0x00: m_video_ram = work_ram + 0x8000 + 0x28000; break; //4 color mode
case 0x02: m_video_ram = work_ram + 0xc000 + 0x28000; break;
case 0x04: m_video_ram = work_ram + 0x8000 + 0x28000; break;
case 0x06: m_video_ram = work_ram + 0xc000 + 0x28000; break;
case 0x20: m_video_ram = work_ram + 0xc000 + 0x28000; break; //4 color mode
case 0x22: m_video_ram = work_ram + 0xe000 + 0x28000; break;
case 0x24: m_video_ram = work_ram + 0xc000 + 0x28000; break;
case 0x26: m_video_ram = work_ram + 0xe000 + 0x28000; break;
case 0x40: m_video_ram = work_ram + 0x0000 + 0x28000; break; //4 color mode
case 0x42: m_video_ram = work_ram + 0x8000 + 0x28000; break;
case 0x44: m_video_ram = work_ram + 0x0000 + 0x28000; break;
case 0x46: m_video_ram = work_ram + 0x8000 + 0x28000; break;
case 0x60: m_video_ram = work_ram + 0x4000 + 0x28000; break; //4 color mode
case 0x62: m_video_ram = work_ram + 0xa000 + 0x28000; break;
case 0x64: m_video_ram = work_ram + 0x4000 + 0x28000; break;
case 0x66: m_video_ram = work_ram + 0xa000 + 0x28000; break;
}
}
WRITE8_MEMBER(pc6001_state::pc6001m2_system_latch_w)
{
if((!(m_sys_latch & 8)) && data & 0x8) //PLAY tape cmd
{
m_cas_switch = 1;
//m_cassette->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_PLAY,CASSETTE_MASK_UISTATE);
}
if((m_sys_latch & 8) && ((data & 0x8) == 0)) //STOP tape cmd
{
m_cas_switch = 0;
//m_cassette->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_STOPPED,CASSETTE_MASK_UISTATE);
//m_irq_vector = 0x00;
//m_maincpu->set_input_line(0, ASSERT_LINE);
}
m_sys_latch = data;
m_timer_irq_mask = data & 1;
vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
//printf("%02x B0\n",data);
}
WRITE8_MEMBER(pc6001_state::pc6001m2_vram_bank_w)
{
//static const UINT32 startaddr[] = {WRAM(6), WRAM(6), WRAM(0), WRAM(4) };
m_ex_vram_bank = data;
vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
m_exgfx_text_mode = ((data & 2) == 0);
m_cgrom_bank_addr = (data & 2) ? 0x0000 : 0x2000;
m_exgfx_bitmap_mode = (data & 8);
m_exgfx_2bpp_mode = ((data & 6) == 0);
{
/* Apparently bitmap modes changes the screen res to 320 x 200 */
{
rectangle visarea = machine().first_screen()->visible_area();
int y_height;
y_height = (m_exgfx_bitmap_mode || m_exgfx_2bpp_mode) ? 200 : 240;
visarea.set(0, (320) - 1, 0, (y_height) - 1);
machine().first_screen()->configure(320, 240, visarea, machine().first_screen()->frame_period().attoseconds());
}
}
// popmessage("%02x",data);
// m_video_ram = work_ram + startaddr[(data >> 1) & 0x03];
}
WRITE8_MEMBER(pc6001_state::pc6001m2_col_bank_w)
{
m_bgcol_bank = (data & 7);
}
WRITE8_MEMBER(pc6001_state::pc6001m2_0xf3_w)
{
/*
x--- ---- M1 (?) wait setting
-x-- ---- ROM wait setting
--x- ---- RAM wait setting
---x ---- custom irq 2 address output
---- x--- custom irq 1 address output
---- -x-- timer irq mask 2 (mirror?)
---- --x- custom irq 2 mask
---- ---x custom irq 1 mask
*/
m_timer_irq_mask2 = data & 4;
}
TIMER_CALLBACK_MEMBER(pc6001_state::audio_callback)
{
if(m_cas_switch == 0 && ((m_timer_irq_mask == 0) || (m_timer_irq_mask2 == 0)))
{
if(IRQ_LOG) printf("Timer IRQ called %02x\n",m_timer_irq_vector);
m_irq_vector = m_timer_irq_vector;
m_maincpu->set_input_line(0, ASSERT_LINE);
}
}
WRITE8_MEMBER(pc6001_state::pc6001m2_timer_adj_w)
{
m_timer_hz_div = data;
attotime period = attotime::from_hz((487.5*4)/(m_timer_hz_div+1));
m_timer_irq_timer->adjust(period, 0, period);
}
WRITE8_MEMBER(pc6001_state::pc6001m2_timer_irqv_w)
{
m_timer_irq_vector = data;
}
READ8_MEMBER(pc6001_state::pc6001m2_bank_r0_r)
{
return m_bank_r0;
}
READ8_MEMBER(pc6001_state::pc6001m2_bank_r1_r)
{
return m_bank_r1;
}
READ8_MEMBER(pc6001_state::pc6001m2_bank_w0_r)
{
return m_bank_w;
}
static ADDRESS_MAP_START(pc6001m2_map, AS_PROGRAM, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x1fff) AM_ROMBANK("bank1") AM_WRITE(work_ram0_w)
AM_RANGE(0x2000, 0x3fff) AM_ROMBANK("bank2") AM_WRITE(work_ram1_w)
AM_RANGE(0x4000, 0x5fff) AM_ROMBANK("bank3") AM_WRITE(work_ram2_w)
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank4") AM_WRITE(work_ram3_w)
AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("bank5") AM_WRITE(work_ram4_w)
AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank6") AM_WRITE(work_ram5_w)
AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("bank7") AM_WRITE(work_ram6_w)
AM_RANGE(0xe000, 0xffff) AM_ROMBANK("bank8") AM_WRITE(work_ram7_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( pc6001m2_io , AS_IO, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x80, 0x80) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
AM_RANGE(0x81, 0x81) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
AM_RANGE(0x90, 0x93) AM_MIRROR(0x0c) AM_READWRITE(nec_ppi8255_r, necmk2_ppi8255_w)
AM_RANGE(0xa0, 0xa0) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, address_w)
AM_RANGE(0xa1, 0xa1) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, data_w)
AM_RANGE(0xa2, 0xa2) AM_MIRROR(0x0c) AM_DEVREAD("ay8910", ay8910_device, data_r)
AM_RANGE(0xa3, 0xa3) AM_MIRROR(0x0c) AM_NOP
AM_RANGE(0xb0, 0xb0) AM_MIRROR(0x0f) AM_WRITE(pc6001m2_system_latch_w)
AM_RANGE(0xc0, 0xc0) AM_WRITE(pc6001m2_col_bank_w)
AM_RANGE(0xc1, 0xc1) AM_WRITE(pc6001m2_vram_bank_w)
AM_RANGE(0xc2, 0xc2) AM_WRITE(pc6001m2_opt_bank_w)
AM_RANGE(0xd0, 0xd3) AM_MIRROR(0x0c) AM_NOP // disk device
AM_RANGE(0xe0, 0xe3) AM_MIRROR(0x0c) AM_DEVREADWRITE("upd7752", upd7752_device, read, write)
AM_RANGE(0xf0, 0xf0) AM_READWRITE(pc6001m2_bank_r0_r,pc6001m2_bank_r0_w)
AM_RANGE(0xf1, 0xf1) AM_READWRITE(pc6001m2_bank_r1_r,pc6001m2_bank_r1_w)
AM_RANGE(0xf2, 0xf2) AM_READWRITE(pc6001m2_bank_w0_r,pc6001m2_bank_w0_w)
AM_RANGE(0xf3, 0xf3) AM_WRITE(pc6001m2_0xf3_w)
// AM_RANGE(0xf4
// AM_RANGE(0xf5
AM_RANGE(0xf6, 0xf6) AM_WRITE(pc6001m2_timer_adj_w)
AM_RANGE(0xf7, 0xf7) AM_WRITE(pc6001m2_timer_irqv_w)
ADDRESS_MAP_END
/* disk device placeholder (TODO: identify & hook-up this) */
READ8_MEMBER(pc6001_state::pc6601_fdc_r)
{
return machine().rand();
}
WRITE8_MEMBER(pc6001_state::pc6601_fdc_w)
{
}
static ADDRESS_MAP_START( pc6601_io , AS_IO, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x80, 0x80) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
AM_RANGE(0x81, 0x81) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
AM_RANGE(0x90, 0x93) AM_MIRROR(0x0c) AM_READWRITE(nec_ppi8255_r, necmk2_ppi8255_w)
AM_RANGE(0xa0, 0xa0) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, address_w)
AM_RANGE(0xa1, 0xa1) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, data_w)
AM_RANGE(0xa2, 0xa2) AM_MIRROR(0x0c) AM_DEVREAD("ay8910", ay8910_device, data_r)
AM_RANGE(0xa3, 0xa3) AM_MIRROR(0x0c) AM_NOP
AM_RANGE(0xb0, 0xb0) AM_WRITE(pc6001m2_system_latch_w)
/* these are disk related */
// AM_RANGE(0xb1
// AM_RANGE(0xb2
// AM_RANGE(0xb3
AM_RANGE(0xc0, 0xc0) AM_WRITE(pc6001m2_col_bank_w)
AM_RANGE(0xc1, 0xc1) AM_WRITE(pc6001m2_vram_bank_w)
AM_RANGE(0xc2, 0xc2) AM_WRITE(pc6001m2_opt_bank_w)
AM_RANGE(0xd0, 0xdf) AM_READWRITE(pc6601_fdc_r,pc6601_fdc_w) // disk device
AM_RANGE(0xe0, 0xe3) AM_MIRROR(0x0c) AM_DEVREADWRITE("upd7752", upd7752_device, read, write)
AM_RANGE(0xf0, 0xf0) AM_READWRITE(pc6001m2_bank_r0_r,pc6001m2_bank_r0_w)
AM_RANGE(0xf1, 0xf1) AM_READWRITE(pc6001m2_bank_r1_r,pc6001m2_bank_r1_w)
AM_RANGE(0xf2, 0xf2) AM_READWRITE(pc6001m2_bank_w0_r,pc6001m2_bank_w0_w)
AM_RANGE(0xf3, 0xf3) AM_WRITE(pc6001m2_0xf3_w)
// AM_RANGE(0xf4
// AM_RANGE(0xf5
AM_RANGE(0xf6, 0xf6) AM_WRITE(pc6001m2_timer_adj_w)
AM_RANGE(0xf7, 0xf7) AM_WRITE(pc6001m2_timer_irqv_w)
ADDRESS_MAP_END
/* PC-6001 SR */
#define SR_SYSROM_1(_v_) \
0x10000+(0x1000*_v_)
#define SR_SYSROM_2(_v_) \
0x20000+(0x1000*_v_)
#define SR_CGROM1(_v_) \
0x30000+(0x1000*_v_)
#define SR_EXROM0(_v_) \
0x40000+(0x1000*_v_)
#define SR_EXROM1(_v_) \
0x50000+(0x1000*_v_)
#define SR_EXRAM0(_v_) \
0x60000+(0x1000*_v_)
#define SR_WRAM0(_v_) \
0x70000+(0x1000*_v_)
#define SR_NULL(_v_) \
0x80000+(0x1000*_v_)
READ8_MEMBER(pc6001_state::pc6001sr_bank_rn_r)
{
return m_sr_bank_r[offset];
}
WRITE8_MEMBER(pc6001_state::pc6001sr_bank_rn_w)
{
memory_bank *bank[8] = { m_bank1, m_bank2, m_bank3, m_bank4, m_bank5, m_bank6, m_bank7, m_bank8 };
UINT8 *ROM = m_region_maincpu->base();
UINT8 bank_num;
m_sr_bank_r[offset] = data;
bank_num = data & 0x0f;
switch(data & 0xf0)
{
case 0xf0: bank[offset]->set_base(&ROM[SR_SYSROM_1(bank_num)]); break;
case 0xe0: bank[offset]->set_base(&ROM[SR_SYSROM_2(bank_num)]); break;
case 0xd0: bank[offset]->set_base(&ROM[SR_CGROM1(bank_num)]); break;
case 0xc0: bank[offset]->set_base(&ROM[SR_EXROM0(bank_num)]); break;
case 0xb0: bank[offset]->set_base(&ROM[SR_EXROM1(bank_num)]); break;
case 0x20: bank[offset]->set_base(&ROM[SR_EXRAM0(bank_num)]); break;
case 0x00: bank[offset]->set_base(&ROM[SR_WRAM0(bank_num)]); break;
default: bank[offset]->set_base(&ROM[SR_NULL(bank_num)]); break;
}
}
READ8_MEMBER(pc6001_state::pc6001sr_bank_wn_r)
{
return m_sr_bank_w[offset];
}
WRITE8_MEMBER(pc6001_state::pc6001sr_bank_wn_w)
{
m_sr_bank_w[offset] = data;
}
#define SR_WRAM_BANK_W(_v_) \
{ \
UINT8 *ROM = m_region_maincpu->base(); \
UINT8 bank_num; \
bank_num = m_sr_bank_w[_v_] & 0x0f; \
if((m_sr_bank_w[_v_] & 0xf0) != 0x20) \
ROM[offset+(SR_WRAM0(bank_num))] = data; \
else \
ROM[offset+(SR_EXRAM0(bank_num))] = data; \
}
WRITE8_MEMBER(pc6001_state::sr_work_ram0_w){ SR_WRAM_BANK_W(0); }
WRITE8_MEMBER(pc6001_state::sr_work_ram1_w){ SR_WRAM_BANK_W(1); }
WRITE8_MEMBER(pc6001_state::sr_work_ram2_w){ SR_WRAM_BANK_W(2); }
WRITE8_MEMBER(pc6001_state::sr_work_ram3_w){ SR_WRAM_BANK_W(3); }
WRITE8_MEMBER(pc6001_state::sr_work_ram4_w){ SR_WRAM_BANK_W(4); }
WRITE8_MEMBER(pc6001_state::sr_work_ram5_w){ SR_WRAM_BANK_W(5); }
WRITE8_MEMBER(pc6001_state::sr_work_ram6_w){ SR_WRAM_BANK_W(6); }
WRITE8_MEMBER(pc6001_state::sr_work_ram7_w){ SR_WRAM_BANK_W(7); }
WRITE8_MEMBER(pc6001_state::pc6001sr_mode_w)
{
m_sr_video_mode = data;
if(data & 1)
assert("PC-6001SR in Mk-2 compatibility mode not yet supported!\n");
}
WRITE8_MEMBER(pc6001_state::pc6001sr_vram_bank_w)
{
UINT8 *work_ram = m_region_maincpu->base();
m_video_ram = work_ram + 0x70000 + ((data & 0x0f)*0x1000);
}
WRITE8_MEMBER(pc6001_state::pc6001sr_system_latch_w)
{
if((!(m_sys_latch & 8)) && data & 0x8) //PLAY tape cmd
{
m_cas_switch = 1;
//m_cassette->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_PLAY,CASSETTE_MASK_UISTATE);
}
if((m_sys_latch & 8) && ((data & 0x8) == 0)) //STOP tape cmd
{
m_cas_switch = 0;
//m_cassette->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
//m_cassette->change_state(CASSETTE_STOPPED,CASSETTE_MASK_UISTATE);
//m_irq_vector = 0x00;
//m_maincpu->set_input_line(0, ASSERT_LINE);
}
m_sys_latch = data;
m_timer_irq_mask = data & 1;
//vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
//printf("%02x B0\n",data);
}
WRITE8_MEMBER(pc6001_state::necsr_ppi8255_w)
{
if (offset==3)
{
if(data & 1)
m_port_c_8255 |= 1<<((data>>1)&0x07);
else
m_port_c_8255 &= ~(1<<((data>>1)&0x07));
switch(data) {
case 0x08: m_port_c_8255 |= 0x88; break;
case 0x09: m_port_c_8255 &= 0xf7; break;
case 0x0c: m_port_c_8255 |= 0x28; break;
case 0x0d: m_port_c_8255 &= 0xf7; break;
default: break;
}
m_port_c_8255 |= 0xa8;
if(0)
{
//printf("%02x\n",data);
if ((data & 0x0f) == 0x05 && m_cart_rom)
m_bank1->set_base(m_cart_rom->base() + 0x2000);
if ((data & 0x0f) == 0x04)
m_bank1->set_base(m_region_gfx1->base());
}
}
m_ppi->write(space,offset,data);
}
static ADDRESS_MAP_START(pc6001sr_map, AS_PROGRAM, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x1fff) AM_ROMBANK("bank1") AM_WRITE(sr_work_ram0_w)
AM_RANGE(0x2000, 0x3fff) AM_ROMBANK("bank2") AM_WRITE(sr_work_ram1_w)
AM_RANGE(0x4000, 0x5fff) AM_ROMBANK("bank3") AM_WRITE(sr_work_ram2_w)
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank4") AM_WRITE(sr_work_ram3_w)
AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("bank5") AM_WRITE(sr_work_ram4_w)
AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank6") AM_WRITE(sr_work_ram5_w)
AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("bank7") AM_WRITE(sr_work_ram6_w)
AM_RANGE(0xe000, 0xffff) AM_ROMBANK("bank8") AM_WRITE(sr_work_ram7_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( pc6001sr_io , AS_IO, 8, pc6001_state )
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x60, 0x67) AM_READWRITE(pc6001sr_bank_rn_r,pc6001sr_bank_rn_w)
AM_RANGE(0x68, 0x6f) AM_READWRITE(pc6001sr_bank_wn_r,pc6001sr_bank_wn_w)
AM_RANGE(0x80, 0x80) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
AM_RANGE(0x81, 0x81) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
AM_RANGE(0x90, 0x93) AM_MIRROR(0x0c) AM_READWRITE(nec_ppi8255_r, necsr_ppi8255_w)
AM_RANGE(0xa0, 0xa0) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, address_w)
AM_RANGE(0xa1, 0xa1) AM_MIRROR(0x0c) AM_DEVWRITE("ay8910", ay8910_device, data_w)
AM_RANGE(0xa2, 0xa2) AM_MIRROR(0x0c) AM_DEVREAD("ay8910", ay8910_device, data_r)
AM_RANGE(0xa3, 0xa3) AM_MIRROR(0x0c) AM_NOP
AM_RANGE(0xb0, 0xb0) AM_WRITE(pc6001sr_system_latch_w)
/* these are disk related */
// AM_RANGE(0xb1
// AM_RANGE(0xb2
// AM_RANGE(0xb3
// AM_RANGE(0xc0, 0xc0) AM_WRITE(pc6001m2_col_bank_w)
// AM_RANGE(0xc1, 0xc1) AM_WRITE(pc6001m2_vram_bank_w)
// AM_RANGE(0xc2, 0xc2) AM_WRITE(pc6001m2_opt_bank_w)
AM_RANGE(0xc8, 0xc8) AM_WRITE(pc6001sr_mode_w)
AM_RANGE(0xc9, 0xc9) AM_WRITE(pc6001sr_vram_bank_w)
AM_RANGE(0xd0, 0xdf) AM_READWRITE(pc6601_fdc_r,pc6601_fdc_w) // disk device
AM_RANGE(0xe0, 0xe3) AM_MIRROR(0x0c) AM_DEVREADWRITE("upd7752", upd7752_device, read, write)
// AM_RANGE(0xf0, 0xf0) AM_READWRITE(pc6001m2_bank_r0_r,pc6001m2_bank_r0_w)
// AM_RANGE(0xf1, 0xf1) AM_READWRITE(pc6001m2_bank_r1_r,pc6001m2_bank_r1_w)
// AM_RANGE(0xf2, 0xf2) AM_READWRITE(pc6001m2_bank_w0_r,pc6001m2_bank_w0_w)
AM_RANGE(0xf3, 0xf3) AM_WRITE(pc6001m2_0xf3_w)
// AM_RANGE(0xf4
// AM_RANGE(0xf5
AM_RANGE(0xf6, 0xf6) AM_WRITE(pc6001m2_timer_adj_w)
AM_RANGE(0xf7, 0xf7) AM_WRITE(pc6001m2_timer_irqv_w)
ADDRESS_MAP_END
/* Input ports */
static INPUT_PORTS_START( pc6001 )
PORT_START("MODE4_DSW") //TODO: is this really a DSW? bit arrangement is also unknown if so.
PORT_DIPNAME( 0x07, 0x00, "Mode 4 GFX colors" )
PORT_DIPSETTING( 0x00, "Monochrome" )
PORT_DIPSETTING( 0x01, "Red/Blue" )
PORT_DIPSETTING( 0x02, "Blue/Red" )
PORT_DIPSETTING( 0x03, "Pink/Green" )
PORT_DIPSETTING( 0x04, "Green/Pink" )
//5-6-7 is presumably invalid
/* TODO: these two are unchecked */
PORT_START("P1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("P2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("key1") //0x00-0x1f
PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_UNUSED) //0x00 null
PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_UNUSED) //0x01 soh
PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_UNUSED) //0x02 stx
PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_UNUSED) //0x03 etx
PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_UNUSED) //0x04 etx
PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_UNUSED) //0x05 eot
PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_UNUSED) //0x06 enq
PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_UNUSED) //0x07 ack
PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0a
PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0b lf
PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0c vt
PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(27)
PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0e cr
PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0f so
PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x10 si
PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x11 dle
PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x12 dc1
PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x13 dc2
PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x14 dc3
PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x15 dc4
PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x16 nak
PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x17 syn
PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x18 etb
PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x19 cancel
PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1a em
PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1b sub
PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_TILDE) PORT_CHAR(27)
PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1d fs
PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1e gs
PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1f us
PORT_START("key2") //0x20-0x3f
PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_UNUSED) //0x21 !
PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_UNUSED) //0x22 "
PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_UNUSED) //0x23 #
PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_UNUSED) //0x24 $
PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_UNUSED) //0x25 %
PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_UNUSED) //0x26 &
PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_UNUSED) //0x27 '
PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_UNUSED) //0x28 (
PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_UNUSED) //0x29 )
PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("*") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR('*')
PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("+") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR('+')
PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') //0x2c
PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') //0x2e
PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') //0x2f
PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3a :
PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3b ;
PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3c <
PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3d =
PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3e >
PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3f ?
PORT_START("key3") //0x40-0x5f
PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@')
PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G')
PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H')
PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I')
PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J')
PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K')
PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L')
PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M')
PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N')
PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O')
PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P')
PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R')
PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S')
PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T')
PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U')
PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V')
PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W')
PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_UNUSED)
PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("_")
PORT_START("key_modifiers")
PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_RCONTROL) PORT_TOGGLE
PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CAPS") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("GRPH") PORT_CODE(KEYCODE_LALT)
PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("STOP") PORT_CODE(KEYCODE_ESC)
INPUT_PORTS_END
INTERRUPT_GEN_MEMBER(pc6001_state::pc6001_interrupt)
{
m_cur_keycode = check_joy_press();
if(IRQ_LOG) printf("Stick IRQ called 0x16\n");
m_irq_vector = 0x16;
device.execute().set_input_line(0, ASSERT_LINE);
}
INTERRUPT_GEN_MEMBER(pc6001_state::pc6001sr_interrupt)
{
m_kludge^= 1;
m_cur_keycode = check_joy_press();
if(IRQ_LOG) printf("VRTC IRQ called 0x16\n");
m_irq_vector = (m_kludge) ? 0x22 : 0x16;
device.execute().set_input_line(0, ASSERT_LINE);
}
IRQ_CALLBACK_MEMBER(pc6001_state::pc6001_irq_callback)
{
device.execute().set_input_line(0, CLEAR_LINE);
return m_irq_vector;
}
READ8_MEMBER(pc6001_state::pc6001_8255_porta_r)
{
return 0;
}
WRITE8_MEMBER(pc6001_state::pc6001_8255_porta_w)
{
// if(data != 0x06)
// printf("pc6001_8255_porta_w %02x\n",data);
}
READ8_MEMBER(pc6001_state::pc6001_8255_portb_r)
{
return 0;
}
WRITE8_MEMBER(pc6001_state::pc6001_8255_portb_w)
{
//printf("pc6001_8255_portb_w %02x\n",data);
}
WRITE8_MEMBER(pc6001_state::pc6001_8255_portc_w)
{
//printf("pc6001_8255_portc_w %02x\n",data);
}
READ8_MEMBER(pc6001_state::pc6001_8255_portc_r)
{
return 0x88;
}
UINT8 pc6001_state::check_keyboard_press()
{
ioport_port *ports[3] = { m_io_key1, m_io_key2, m_io_key3 };
int i,port_i,scancode;
UINT8 shift_pressed,caps_lock;
scancode = 0;
shift_pressed = (m_io_key_modifiers->read() & 2)>>1;
caps_lock = (m_io_key_modifiers->read() & 8)>>3;
for(port_i=0;port_i<3;port_i++)
{
for(i=0;i<32;i++)
{
if((ports[port_i]->read()>>i) & 1)
{
if((shift_pressed != caps_lock) && scancode >= 0x41 && scancode <= 0x5f)
scancode+=0x20;
if(shift_pressed && scancode >= 0x31 && scancode <= 0x39)
scancode-=0x10;
if(shift_pressed && scancode == 0x30) // '0' / '='
scancode = 0x3d;
if(shift_pressed && scancode == 0x2c) // ',' / ';'
scancode = 0x3b;
if(shift_pressed && scancode == 0x2f) // '/' / '?'
scancode = 0x3f;
if(shift_pressed && scancode == 0x2e) // '.' / ':'
scancode = 0x3a;
return scancode;
}
scancode++;
}
}
return 0;
}
UINT8 pc6001_state::check_joy_press()
{
UINT8 p1_key = m_io_p1->read() ^ 0xff;
UINT8 shift_key = m_io_key_modifiers->read() & 0x02;
UINT8 space_key = m_io_key2->read() & 0x01;
UINT8 joy_press;
/*
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
*/
joy_press = 0;
switch(p1_key & 0xf)
{
case 0x01: joy_press = 0x04; break; //up
case 0x02: joy_press = 0x08; break; //down
case 0x04: joy_press = 0x20; break;
case 0x05: joy_press = 0x24; break; //up-left
case 0x06: joy_press = 0x28; break; //down-left
case 0x08: joy_press = 0x10; break; //right
case 0x09: joy_press = 0x14; break; //up-right
case 0x0a: joy_press = 0x18; break; //down-right
}
if(p1_key & 0x10 || space_key) { joy_press |= 0x80; } //button 1 (space)
if(p1_key & 0x20 || shift_key) { joy_press |= 0x01; } //button 2 (shift)
return joy_press;
}
TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::cassette_callback)
{
if(m_cas_switch == 1)
{
#if 0
static UINT8 cas_data_i = 0x80,cas_data_poll;
//m_cur_keycode = gfx_data[m_cas_offset++];
if(m_cassette->input() > 0.03)
cas_data_poll|= cas_data_i;
else
cas_data_poll&=~cas_data_i;
if(cas_data_i == 1)
{
m_cur_keycode = cas_data_poll;
cas_data_i = 0x80;
/* data ready, poll irq */
m_irq_vector = 0x08;
m_maincpu->set_input_line(0, ASSERT_LINE);
}
else
cas_data_i>>=1;
#else
address_space &space = m_maincpu->space(AS_PROGRAM);
m_cur_keycode = m_cas_hack->read_rom(space, m_cas_offset++);
popmessage("%04x %04x", m_cas_offset, m_cas_maxsize);
if(m_cas_offset > m_cas_maxsize)
{
m_cas_offset = 0;
m_cas_switch = 0;
if(IRQ_LOG) printf("Tape-E IRQ 0x12\n");
m_irq_vector = 0x12;
m_maincpu->set_input_line(0, ASSERT_LINE);
}
else
{
if(IRQ_LOG) printf("Tape-D IRQ 0x08\n");
m_irq_vector = 0x08;
m_maincpu->set_input_line(0, ASSERT_LINE);
}
#endif
}
}
TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::keyboard_callback)
{
UINT32 key1 = m_io_key1->read();
UINT32 key2 = m_io_key2->read();
UINT32 key3 = m_io_key3->read();
// UINT8 p1_key = m_io_p1->read();
if(m_cas_switch == 0)
{
if((key1 != m_old_key1) || (key2 != m_old_key2) || (key3 != m_old_key3))
{
m_cur_keycode = check_keyboard_press();
if(IRQ_LOG) printf("KEY IRQ 0x02\n");
m_irq_vector = 0x02;
m_maincpu->set_input_line(0, ASSERT_LINE);
m_old_key1 = key1;
m_old_key2 = key2;
m_old_key3 = key3;
}
#if 0
else /* joypad polling */
{
m_cur_keycode = check_joy_press();
if(m_cur_keycode)
{
m_irq_vector = 0x16;
m_maincpu->set_input_line(0, ASSERT_LINE);
}
}
#endif
}
}
void pc6001_state::machine_start()
{
m_timer_hz_div = 3;
{
attotime period = attotime::from_hz((487.5*4)/(m_timer_hz_div+1));
m_timer_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pc6001_state::audio_callback),this));
m_timer_irq_timer->adjust(period, 0, period);
}
}
void pc6001_state::machine_reset()
{
m_video_ram = m_region_maincpu->base() + 0xc000;
if (m_cart->exists())
m_maincpu->space(AS_PROGRAM).install_read_handler(0x4000, 0x5fff, read8_delegate(FUNC(generic_slot_device::read_rom),(generic_slot_device*)m_cart));
std::string region_tag;
m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
m_port_c_8255=0;
m_cas_switch = 0;
m_cas_offset = 0;
m_cas_maxsize = (m_cas_hack->exists()) ? m_cas_hack->get_rom_size() : 0;
m_timer_irq_mask = 1;
m_timer_irq_mask2 = 1;
m_timer_irq_vector = 0x06; // actually vector is fixed in plain PC-6001
m_timer_hz_div = 3;
}
MACHINE_RESET_MEMBER(pc6001_state,pc6001m2)
{
m_video_ram = m_region_maincpu->base() + 0xc000 + 0x28000;
std::string region_tag;
m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
// hackish way to simplify bankswitch handling
if (m_cart_rom)
memcpy(m_region_maincpu->base() + 0x48000, m_cart_rom->base(), 0x4000);
m_port_c_8255=0;
m_cas_switch = 0;
m_cas_offset = 0;
m_cas_maxsize = (m_cas_hack->exists()) ? m_cas_hack->get_rom_size() : 0;
/* set default bankswitch */
{
UINT8 *ROM = m_region_maincpu->base();
m_bank_r0 = 0x71;
m_bank1->set_base(&ROM[BASICROM(0)]);
m_bank2->set_base(&ROM[BASICROM(1)]);
m_bank3->set_base(&ROM[EXROM(0)]);
m_bank4->set_base(&ROM[EXROM(1)]);
m_bank_r1 = 0xdd;
m_bank5->set_base(&ROM[WRAM(4)]);
m_bank6->set_base(&ROM[WRAM(5)]);
m_bank7->set_base(&ROM[WRAM(6)]);
m_bank8->set_base(&ROM[WRAM(7)]);
m_bank_opt = 0x02; //tv rom
m_bank_w = 0x50; //enable write to work ram 4,5,6,7
m_gfx_bank_on = 0;
}
m_timer_irq_mask = 1;
m_timer_irq_mask2 = 1;
m_timer_irq_vector = 0x06;
}
MACHINE_RESET_MEMBER(pc6001_state,pc6001sr)
{
m_video_ram = m_region_maincpu->base() + 0x70000;
std::string region_tag;
m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
// should this be mirrored into the EXROM regions? hard to tell without an actual cart dump...
m_port_c_8255=0;
m_cas_switch = 0;
m_cas_offset = 0;
m_cas_maxsize = (m_cas_hack->exists()) ? m_cas_hack->get_rom_size() : 0;
/* set default bankswitch */
{
UINT8 *ROM = m_region_maincpu->base();
m_sr_bank_r[0] = 0xf8; m_bank1->set_base(&ROM[SR_SYSROM_1(0x08)]);
m_sr_bank_r[1] = 0xfa; m_bank2->set_base(&ROM[SR_SYSROM_1(0x0a)]);
m_sr_bank_r[2] = 0xb0; m_bank3->set_base(&ROM[SR_EXROM1(0x00)]);
m_sr_bank_r[3] = 0xc0; m_bank4->set_base(&ROM[SR_EXROM0(0x00)]);
m_sr_bank_r[4] = 0x08; m_bank5->set_base(&ROM[SR_WRAM0(0x08)]);
m_sr_bank_r[5] = 0x0a; m_bank6->set_base(&ROM[SR_WRAM0(0x0a)]);
m_sr_bank_r[6] = 0x0c; m_bank7->set_base(&ROM[SR_WRAM0(0x0c)]);
m_sr_bank_r[7] = 0x0e; m_bank8->set_base(&ROM[SR_WRAM0(0x0e)]);
// m_bank_opt = 0x02; //tv rom
/* enable default work RAM writes */
m_sr_bank_w[0] = 0x00;
m_sr_bank_w[1] = 0x02;
m_sr_bank_w[2] = 0x04;
m_sr_bank_w[3] = 0x06;
m_sr_bank_w[4] = 0x08;
m_sr_bank_w[5] = 0x0a;
m_sr_bank_w[6] = 0x0c;
m_sr_bank_w[7] = 0x0e;
m_gfx_bank_on = 0;
}
m_timer_irq_mask = 1;
m_timer_irq_mask2 = 1;
m_timer_irq_vector = 0x06;
}
static const rgb_t defcolors[] =
{
rgb_t(0x07, 0xff, 0x00), /* GREEN */
rgb_t(0xff, 0xff, 0x00), /* YELLOW */
rgb_t(0x3b, 0x08, 0xff), /* BLUE */
rgb_t(0xcc, 0x00, 0x3b), /* RED */
rgb_t(0xff, 0xff, 0xff), /* BUFF */
rgb_t(0x07, 0xe3, 0x99), /* CYAN */
rgb_t(0xff, 0x1c, 0xff), /* MAGENTA */
rgb_t(0xff, 0x81, 0x00), /* ORANGE */
/* MC6847 specific */
rgb_t(0x00, 0x7c, 0x00), /* ALPHANUMERIC DARK GREEN */
rgb_t(0x07, 0xff, 0x00), /* ALPHANUMERIC BRIGHT GREEN */
rgb_t(0x91, 0x00, 0x00), /* ALPHANUMERIC DARK ORANGE */
rgb_t(0xff, 0x81, 0x00) /* ALPHANUMERIC BRIGHT ORANGE */
};
static const rgb_t mk2_defcolors[] =
{
rgb_t(0x00, 0x00, 0x00), /* BLACK */
rgb_t(0xff, 0xaf, 0x00), /* ORANGE */
rgb_t(0x00, 0xff, 0xaf), /* tone of GREEN */
rgb_t(0xaf, 0xff, 0x00), /* tone of GREEN */
rgb_t(0xaf, 0x00, 0xff), /* VIOLET */
rgb_t(0xff, 0x00, 0xaf), /* SCARLET */
rgb_t(0x00, 0xaf, 0xff), /* LIGHT BLUE */
rgb_t(0xaf, 0xaf, 0xaf), /* GRAY */
rgb_t(0x00, 0x00, 0x00), /* BLACK */
rgb_t(0xff, 0x00, 0x00), /* RED */
rgb_t(0x00, 0xff, 0x00), /* GREEN */
rgb_t(0xff, 0xff, 0x00), /* YELLOW */
rgb_t(0x00, 0x00, 0xff), /* BLUE */
rgb_t(0xff, 0x00, 0xff), /* PINK */
rgb_t(0x00, 0xff, 0xff), /* CYAN */
rgb_t(0xff, 0xff, 0xff) /* WHITE */
};
PALETTE_INIT_MEMBER(pc6001_state, pc6001)
{
int i;
for(i=0;i<8+4;i++)
palette.set_pen_color(i+8,defcolors[i]);
}
PALETTE_INIT_MEMBER(pc6001_state,pc6001m2)
{
int i;
for(i=0;i<8;i++)
palette.set_pen_color(i+8,defcolors[i]);
for(i=0x10;i<0x20;i++)
palette.set_pen_color(i,mk2_defcolors[i-0x10]);
}
#if 0
static const cassette_interface pc6001_cassette_interface =
{
pc6001_cassette_formats,
nullptr,
(cassette_state)(CASSETTE_STOPPED | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED),
nullptr
};
#endif
static const gfx_layout char_layout =
{
8, 16,
RGN_FRAC(1,1),
1,
{ 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8*16
};
static const gfx_layout kanji_layout =
{
16, 16,
RGN_FRAC(1,2),
1,
{ 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7,
0+RGN_FRAC(1,2), 1+RGN_FRAC(1,2), 2+RGN_FRAC(1,2), 3+RGN_FRAC(1,2), 4+RGN_FRAC(1,2), 5+RGN_FRAC(1,2), 6+RGN_FRAC(1,2), 7+RGN_FRAC(1,2) },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8*16
};
static GFXDECODE_START( pc6001m2 )
GFXDECODE_ENTRY( "gfx1", 0x0000, char_layout, 2, 1 )
GFXDECODE_ENTRY( "gfx2", 0x0000, kanji_layout, 2, 1 )
GFXDECODE_END
#define PC6001_MAIN_CLOCK 7987200
static MACHINE_CONFIG_START( pc6001, pc6001_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu",Z80, PC6001_MAIN_CLOCK / 2) // ~4 Mhz
MCFG_CPU_PROGRAM_MAP(pc6001_map)
MCFG_CPU_IO_MAP(pc6001_io)
MCFG_CPU_VBLANK_INT_DRIVER("screen", pc6001_state, pc6001_interrupt)
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(pc6001_state,pc6001_irq_callback)
// MCFG_CPU_ADD("subcpu", I8049, 7987200)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", pc6001m2)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_UPDATE_DRIVER(pc6001_state, screen_update_pc6001)
MCFG_SCREEN_SIZE(320, 25+192+26)
MCFG_SCREEN_VISIBLE_AREA(0, 319, 0, 239)
MCFG_SCREEN_PALETTE("palette")
MCFG_PALETTE_ADD("palette", 16+4)
MCFG_PALETTE_INIT_OWNER(pc6001_state, pc6001)
MCFG_DEVICE_ADD("ppi8255", I8255, 0)
MCFG_I8255_IN_PORTA_CB(READ8(pc6001_state, pc6001_8255_porta_r))
MCFG_I8255_OUT_PORTA_CB(WRITE8(pc6001_state, pc6001_8255_porta_w))
MCFG_I8255_IN_PORTB_CB(READ8(pc6001_state, pc6001_8255_portb_r))
MCFG_I8255_OUT_PORTB_CB(WRITE8(pc6001_state, pc6001_8255_portb_w))
MCFG_I8255_IN_PORTC_CB(READ8(pc6001_state, pc6001_8255_portc_r))
MCFG_I8255_OUT_PORTC_CB(WRITE8(pc6001_state, pc6001_8255_portc_w))
/* uart */
MCFG_DEVICE_ADD("uart", I8251, 0)
MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "pc6001_cart")
// MCFG_CASSETTE_ADD("cassette", pc6001_cassette_interface)
MCFG_GENERIC_CARTSLOT_ADD("cas_hack", generic_plain_slot, "pc6001_cass")
MCFG_GENERIC_EXTENSIONS("cas,p6")
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ay8910", AY8910, PC6001_MAIN_CLOCK/4)
MCFG_AY8910_PORT_A_READ_CB(IOPORT("P1"))
MCFG_AY8910_PORT_B_READ_CB(IOPORT("P2"))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
// MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
// MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
/* TODO: accurate timing on this */
MCFG_TIMER_DRIVER_ADD_PERIODIC("keyboard_timer", pc6001_state, keyboard_callback, attotime::from_hz(250))
MCFG_TIMER_DRIVER_ADD_PERIODIC("cassette_timer", pc6001_state, cassette_callback, attotime::from_hz(1200/12))
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( pc6001m2, pc6001 )
MCFG_MACHINE_RESET_OVERRIDE(pc6001_state,pc6001m2)
MCFG_SCREEN_MODIFY("screen")
MCFG_SCREEN_UPDATE_DRIVER(pc6001_state, screen_update_pc6001m2)
MCFG_PALETTE_MODIFY("palette")
MCFG_PALETTE_ENTRIES(16+16)
MCFG_PALETTE_INIT_OWNER(pc6001_state,pc6001m2)
/* basic machine hardware */
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(pc6001m2_map)
MCFG_CPU_IO_MAP(pc6001m2_io)
MCFG_GFXDECODE_MODIFY("gfxdecode", pc6001m2)
MCFG_SOUND_ADD("upd7752", UPD7752, PC6001_MAIN_CLOCK/4)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( pc6601, pc6001m2 )
/* basic machine hardware */
MCFG_CPU_REPLACE("maincpu", Z80, PC6001_MAIN_CLOCK / 2)
MCFG_CPU_PROGRAM_MAP(pc6001m2_map)
MCFG_CPU_IO_MAP(pc6601_io)
MCFG_CPU_VBLANK_INT_DRIVER("screen", pc6001_state, pc6001_interrupt)
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(pc6001_state,pc6001_irq_callback)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( pc6001sr, pc6001m2 )
MCFG_MACHINE_RESET_OVERRIDE(pc6001_state,pc6001sr)
MCFG_SCREEN_MODIFY("screen")
MCFG_SCREEN_UPDATE_DRIVER(pc6001_state, screen_update_pc6001sr)
/* basic machine hardware */
MCFG_CPU_REPLACE("maincpu", Z80, XTAL_3_579545MHz) //*Yes*, PC-6001 SR Z80 CPU is actually slower than older models
MCFG_CPU_PROGRAM_MAP(pc6001sr_map)
MCFG_CPU_IO_MAP(pc6001sr_io)
MCFG_CPU_VBLANK_INT_DRIVER("screen", pc6001_state, pc6001sr_interrupt)
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(pc6001_state,pc6001_irq_callback)
MACHINE_CONFIG_END
/* ROM definition */
ROM_START( pc6001 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom.60", 0x0000, 0x4000, CRC(54c03109) SHA1(c622fefda3cdc2b87a270138f24c05828b5c41d2) )
ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
ROM_REGION( 0x2000, "gfx1", 0 )
ROM_LOAD( "cgrom60.60", 0x0000, 0x1000, CRC(b0142d32) SHA1(9570495b10af5b1785802681be94b0ea216a1e26) )
ROM_RELOAD( 0x1000, 0x1000 )
ROM_REGION( 0x8000, "gfx2", ROMREGION_ERASEFF )
ROM_END
ROM_START( pc6001a )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom.60a", 0x0000, 0x4000, CRC(fa8e88d9) SHA1(c82e30050a837e5c8ffec3e0c8e3702447ffd69c) )
ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
ROM_REGION( 0x1000, "gfx1", 0 )
ROM_LOAD( "cgrom60.60a", 0x0000, 0x1000, CRC(49c21d08) SHA1(9454d6e2066abcbd051bad9a29a5ca27b12ec897) )
ROM_REGION( 0x8000, "gfx2", ROMREGION_ERASEFF )
ROM_END
ROM_START( pc6001mk2 )
ROM_REGION( 0x50000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom.62", 0x10000, 0x8000, CRC(950ac401) SHA1(fbf195ba74a3b0f80b5a756befc96c61c2094182) )
ROM_LOAD( "voicerom.62", 0x18000, 0x4000, CRC(49b4f917) SHA1(1a2d18f52ef19dc93da3d65f19d3abbd585628af) )
ROM_LOAD( "cgrom60.62", 0x1c000, 0x2000, CRC(81eb5d95) SHA1(53d8ae9599306ff23bf95208d2f6cc8fed3fc39f) )
ROM_LOAD( "cgrom60m.62", 0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
ROM_LOAD( "kanjirom.62", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
// work ram 0x28000,0x10000
// extended work ram 0x38000,0x10000
// exrom 0x48000, 0x4000
// <invalid> 0x4c000, 0x4000
ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
ROM_REGION( 0x4000, "gfx1", 0 )
ROM_COPY( "maincpu", 0x1c000, 0x00000, 0x4000 )
ROM_REGION( 0x8000, "gfx2", 0 )
ROM_COPY( "maincpu", 0x20000, 0x00000, 0x8000 )
ROM_END
ROM_START( pc6601 ) /* Variant of pc6001m2 */
ROM_REGION( 0x50000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom.66", 0x10000, 0x8000, CRC(c0b01772) SHA1(9240bb6b97fe06f5f07b5d65541c4d2f8758cc2a) )
ROM_LOAD( "voicerom.66", 0x18000, 0x4000, CRC(91d078c1) SHA1(6a93bd7723ef67f461394530a9feee57c8caf7b7) )
ROM_LOAD( "cgrom60.66", 0x1c000, 0x2000, CRC(d2434f29) SHA1(a56d76f5cbdbcdb8759abe601eab68f01b0a8fe8) )
ROM_LOAD( "cgrom66.66", 0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
ROM_LOAD( "kanjirom.66", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
// exrom 0x48000, 0x4000
ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
ROM_REGION( 0x4000, "gfx1", 0 )
ROM_COPY( "maincpu", 0x1c000, 0x00000, 0x4000 )
ROM_REGION( 0x8000, "gfx2", 0 )
ROM_COPY( "maincpu", 0x20000, 0x00000, 0x8000 )
ROM_END
ROM_START( pc6001sr )
ROM_REGION( 0x90000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "systemrom1.64", 0x10000, 0x10000, CRC(b6fc2db2) SHA1(dd48b1eee60aa34780f153359f5da7f590f8dff4) )
ROM_LOAD( "systemrom2.64", 0x20000, 0x10000, CRC(55a62a1d) SHA1(3a19855d290fd4ac04e6066fe4a80ecd81dc8dd7) )
// cgrom 1 0x30000, 0x10000
// exrom 0 0x40000, 0x10000
// exrom 1 0x50000, 0x10000
// exram 0 0x60000, 0x10000
// work ram 0 0x70000, 0x10000
// <invalid> 0x80000, 0x10000
ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
ROM_REGION( 0x4000, "gfx1", 0 )
ROM_LOAD( "cgrom68.64", 0x0000, 0x4000, CRC(73bc3256) SHA1(5f80d62a95331dc39b2fb448a380fd10083947eb) )
ROM_REGION( 0x8000, "gfx2", 0 )
ROM_COPY( "maincpu", 0x28000, 0x00000, 0x8000 )
ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
COMP( 1981, pc6001, 0, 0, pc6001, pc6001, driver_device, 0, "Nippon Electronic Company", "PC-6001 (Japan)", MACHINE_NOT_WORKING )
COMP( 1981, pc6001a, pc6001, 0, pc6001, pc6001, driver_device, 0, "Nippon Electronic Company", "PC-6001A (US)", MACHINE_NOT_WORKING ) // This version is also known as the NEC Trek
COMP( 1983, pc6001mk2,pc6001, 0, pc6001m2, pc6001, driver_device, 0, "Nippon Electronic Company", "PC-6001mkII (Japan)", MACHINE_NOT_WORKING )
COMP( 1983, pc6601, pc6001, 0, pc6601, pc6001, driver_device, 0, "Nippon Electronic Company", "PC-6601 (Japan)", MACHINE_NOT_WORKING )
COMP( 1984, pc6001sr, pc6001, 0, pc6001sr, pc6001, driver_device, 0, "Nippon Electronic Company", "PC-6001mkIISR (Japan)", MACHINE_NOT_WORKING )