Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

PC-98 GDC and LIO drawing support #3508

Merged
merged 6 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ HQ2X and HQ3X render scaler (ScummVM, Maxim Stepin; GPLv2+) src/gui/render_templ

PC-98 FM board emulation (Neko Project II; BSD 3-clause) src/hardware/snd_pc98/*

PC-98 GDC and LIO drawing support (Neko Project II; BSD 3-clause) src/hardware/vga_pc98_gdc_draw.cpp src/ints/pc98_lio.cpp

QCOW image support (Michael Greger; GPLv2+) src/ints/qcow2_disk.cpp

JEGA and DOS/V support (nanshiki, Wengier; GPLv2+) include/jfont.h src/ints/int_dosv.cpp
Expand Down
55 changes: 54 additions & 1 deletion include/pc98_gdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ struct PC98_GDC_state {
void take_reset_sync_parameters(void);
void cursor_advance(void);

void draw_reset(void);
void vectw(unsigned char bi);
void exec(uint8_t command);
void prepare(void);
void draw_dot(uint16_t x, uint16_t y);
void pset(void);
void line(void);
void text(void);
void circle(void);
void box(void);
void set_vectl(int x1, int y1, int x2, int y2);
void set_mode(uint8_t mode);
void set_csrw(uint32_t ead, uint8_t dad);
void set_textw(uint16_t pattern);
void set_textw(uint8_t *tile, uint8_t len);

void begin_frame(void);
void next_line(void);

Expand All @@ -60,13 +76,50 @@ struct PC98_GDC_state {
bool fifo_empty(void);
uint16_t read_fifo(void);

enum {
RT_MULBIT = 15,
RT_TABLEBIT = 12,
RT_TABLEMAX = (1 << RT_TABLEBIT)
};
struct VECTDIR {
int16_t x;
int16_t y;
int16_t x2;
int16_t y2;
};
static const VECTDIR vectdir[16];
static const PhysPt gram_base[4];
static uint16_t gdc_rt[RT_TABLEMAX + 1];

struct GDC_DRAW {
PhysPt base;
uint32_t ead;
uint16_t dc;
uint16_t d;
uint16_t d1;
uint16_t d2;
uint16_t dm;
uint16_t pattern;
uint16_t x;
uint16_t y;
uint8_t tx[8];
uint8_t dad;
uint8_t ope;
uint8_t dir;
uint8_t dgd;
uint8_t wg;
uint8_t dots;
uint8_t mode;
uint8_t zoom;
} draw;

/* NTS:
*
* We're following the Neko Project II method of FIFO emulation BUT
* I wonder if the GDC maintains two FIFOs and allows stacking params
* in one and commands in another....? */

uint8_t cmd_parm_tmp[8]; /* temp storage before accepting params */
uint8_t cmd_parm_tmp[11]; /* temp storage before accepting params */

uint8_t rfifo[PC98_GDC_FIFO_SIZE];
uint8_t rfifo_read,rfifo_write;
Expand Down
10 changes: 10 additions & 0 deletions include/pc98_gdc_const.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ enum {
GDC_CMD_RESET = 0x00, // 0 0 0 0 0 0 0 0
GDC_CMD_DISPLAY_BLANK = 0x0C, // 0 0 0 0 1 1 0 DE
GDC_CMD_SYNC = 0x0E, // 0 0 0 0 1 1 1 DE
GDC_CMD_MODE_REPLACE = 0x20, // 0 0 1 0 0 0 0 0
GDC_CMD_MODE_COMPLEMENT = 0x21, // 0 0 1 0 0 0 0 1
GDC_CMD_MODE_CLEAR = 0x22, // 0 0 1 0 0 0 1 0
GDC_CMD_MODE_SET = 0x23, // 0 0 1 0 0 0 1 1
GDC_CMD_CURSOR_POSITION = 0x49, // 0 1 0 0 1 0 0 1
GDC_CMD_CSRW = 0x49, // 0 1 0 0 1 0 0 1
GDC_CMD_CURSOR_CHAR_SETUP = 0x4B, // 0 1 0 0 1 0 1 1
GDC_CMD_ZOOM = 0x46, // 0 1 0 0 0 1 1 0
GDC_CMD_PITCH_SPEC = 0x47, // 0 1 0 0 0 1 1 1
GDC_CMD_VECTW = 0x4C, // 0 1 0 0 1 1 0 0
GDC_CMD_TEXTE = 0x68, // 0 1 1 0 1 0 0 0
GDC_CMD_START_DISPLAY = 0x6B, // 0 1 1 0 1 0 1 1
GDC_CMD_VECTE = 0x6c, // 0 1 1 0 1 1 0 0
GDC_CMD_VERTICAL_SYNC_MODE = 0x6E, // 0 1 1 0 1 1 1 M
GDC_CMD_PARAMETER_RAM_LOAD = 0x70, // 0 1 1 1 S S S S S[3:0] = starting address in parameter RAM
GDC_CMD_TEXTW = 0x78, // 0 1 1 1 1 0 0 0
GDC_CMD_CURSOR_ADDRESS_READ = 0xE0 // 1 1 1 0 0 0 0 0
};
2 changes: 1 addition & 1 deletion src/hardware/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \
cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp ne2000.cpp hardopl.cpp dbopl.cpp innova.cpp dongle.cpp \
voodoo.cpp voodoo_interface.cpp voodoo_emu.cpp ps1_sound.cpp sn76496.h ide.cpp floppy.cpp voodoo_vogl.cpp voodoo_opengl.cpp nukedopl.cpp pc98.cpp vga_pc98_gdc.cpp vga_pc98_dac.cpp vga_pc98_crtc.cpp vga_pc98_cg.cpp vga_pc98_egc.cpp pc98_fm.cpp glide.cpp \
voodoo.cpp voodoo_interface.cpp voodoo_emu.cpp ps1_sound.cpp sn76496.h ide.cpp floppy.cpp voodoo_vogl.cpp voodoo_opengl.cpp nukedopl.cpp pc98.cpp vga_pc98_gdc.cpp vga_pc98_gdc_draw.cpp vga_pc98_dac.cpp vga_pc98_crtc.cpp vga_pc98_cg.cpp vga_pc98_egc.cpp pc98_fm.cpp glide.cpp \
snd_pc98/sound/opngenc.c snd_pc98/sound/opngeng.c snd_pc98/sound/pcm86c.c snd_pc98/sound/pcm86g.c \
snd_pc98/sound/tms3631c.c snd_pc98/sound/tms3631g.c snd_pc98/sound/psggenc.c snd_pc98/sound/psggeng.c \
snd_pc98/common/parts.c snd_pc98/generic/keydisp.c snd_pc98/sound/adpcmc.c snd_pc98/sound/adpcmg.c \
Expand Down
2 changes: 1 addition & 1 deletion src/hardware/vga_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1706,7 +1706,7 @@ class VGA_PC98_PageHandler : public PageHandler {
* 0 = shifter input is VRAM data */
if (pc98_egc_compare_lead) {
if (!pc98_egc_shiftinput)
return *((AWT*)(pc98_egc_src[pc98_egc_lead_plane&3].b));
return *((AWT*)(pc98_egc_src[pc98_egc_lead_plane&3].b+(vramoff&1)));
else
return *((AWT*)(pc98_pgraph_current_cpu_page+vramoff+((pc98_egc_lead_plane&3)*PC98_VRAM_BITPLANE_SIZE)));
}
Expand Down
2 changes: 1 addition & 1 deletion src/hardware/vga_pc98_crtc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void pc98_crtc_write(Bitu port,Bitu val,Bitu iolen) {
pc98_text_row_scanline_blank_at = (unsigned char)val & 0x1F;
break;
case 0x06:
pc98_text_row_scroll_lines = (unsigned char)val & 0x1F;
pc98_text_row_scroll_lines = (unsigned char)val & 0x0F;
break;
case 0x08:
pc98_text_row_scroll_count_start = (unsigned char)val & 0x1F;
Expand Down
69 changes: 60 additions & 9 deletions src/hardware/vga_pc98_gdc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ PC98_GDC_state::PC98_GDC_state() {
vertical_back_porch_width = 0;
reset_fifo();
reset_rfifo();
draw_reset();
}

size_t PC98_GDC_state::fifo_can_read(void) {
Expand Down Expand Up @@ -247,17 +248,31 @@ void PC98_GDC_state::take_cursor_pos(unsigned char bi) {
* 0 = [3:2] = 0
* EAD(H) = [1:0] = address[17:16] */
if (bi == 1) {
vga.config.cursor_start &= ~(0xFFu << 0u);
vga.config.cursor_start |= cmd_parm_tmp[0] << 0u;
if(master_sync) {
vga.config.cursor_start &= ~(0xFFu << 0u);
vga.config.cursor_start |= cmd_parm_tmp[0] << 0u;
} else {
draw.ead = cmd_parm_tmp[0];
}
}
else if (bi == 2) {
vga.config.cursor_start &= ~(0xFFu << 8u);
vga.config.cursor_start |= (unsigned int)cmd_parm_tmp[1] << 8u;
if(master_sync) {
vga.config.cursor_start &= ~(0xFFu << 8u);
vga.config.cursor_start |= (unsigned int)cmd_parm_tmp[1] << 8u;
} else {
draw.ead |= (uint32_t)cmd_parm_tmp[1] << 8;
}
}
else if (bi == 3) {
vga.config.cursor_start &= ~(0x03u << 16u);
vga.config.cursor_start |= (cmd_parm_tmp[2] & 3u) << 16u;

if(master_sync) {
vga.config.cursor_start &= ~(0x03u << 16u);
vga.config.cursor_start |= (cmd_parm_tmp[2] & 3u) << 16u;
} else {
draw.ead |= (uint32_t)(cmd_parm_tmp[2] & 0x03) << 16;
draw.dad = (uint8_t)(cmd_parm_tmp[2] >> 4);
draw.base = gram_base[(draw.ead >> 14) & 3];
draw.wg = cmd_parm_tmp[2] & 0x08;
}
// TODO: "dot address within the word"
}
}
Expand Down Expand Up @@ -322,6 +337,7 @@ void PC98_GDC_state::idle_proc(void) {
idle = true;
reset_fifo();
reset_rfifo();
draw_reset();
break;
case GDC_CMD_DISPLAY_BLANK: // 0x0C 0 0 0 0 1 1 0 DE
case GDC_CMD_DISPLAY_BLANK+1:// 0x0D DE=display enable
Expand All @@ -334,6 +350,14 @@ void PC98_GDC_state::idle_proc(void) {
current_command &= ~1;
LOG_MSG("GDC: sync");
break;
case GDC_CMD_MODE_REPLACE: // 0x20 0 0 1 0 0 0 0 0
case GDC_CMD_MODE_COMPLEMENT: // 0x21 0 0 1 0 0 0 0 1
case GDC_CMD_MODE_CLEAR: // 0x22 0 0 1 0 0 0 1 0
case GDC_CMD_MODE_SET: // 0x23 0 0 1 0 0 0 1 1
draw.mode = current_command & 0x03;
break;
case GDC_CMD_ZOOM: // 0x46 0 1 0 0 0 1 1 0
break;
case GDC_CMD_PITCH_SPEC: // 0x47 0 1 0 0 0 1 1 1
break;
case GDC_CMD_CURSOR_POSITION: // 0x49 0 1 0 0 1 0 0 1
Expand All @@ -342,6 +366,14 @@ void PC98_GDC_state::idle_proc(void) {
case GDC_CMD_CURSOR_CHAR_SETUP: // 0x4B 0 1 0 0 1 0 1 1
// LOG_MSG("GDC: cursor setup");
break;
case GDC_CMD_VECTW:
break;
case GDC_CMD_TEXTE: // 0x68 0 1 1 0 1 0 0 0
case GDC_CMD_VECTE: // 0x6C 0 1 1 0 1 1 0 0
if(!master_sync) {
exec(current_command);
}
break;
case GDC_CMD_START_DISPLAY: // 0x6B 0 1 1 0 1 0 1 1
display_enable = true;
idle = false;
Expand All @@ -368,8 +400,10 @@ void PC98_GDC_state::idle_proc(void) {
case GDC_CMD_PARAMETER_RAM_LOAD+13:// 0x7D S=starting byte in parameter RAM
case GDC_CMD_PARAMETER_RAM_LOAD+14:// 0x7E S=starting byte in parameter RAM
case GDC_CMD_PARAMETER_RAM_LOAD+15:// 0x7F S=starting byte in parameter RAM
param_ram_wptr = current_command & 0xF;
current_command = GDC_CMD_PARAMETER_RAM_LOAD;
if(master_sync || current_command != GDC_CMD_TEXTW) {
param_ram_wptr = current_command & 0xF;
current_command = GDC_CMD_PARAMETER_RAM_LOAD;
}
break;
case GDC_CMD_CURSOR_ADDRESS_READ: // 0xE0 1 1 1 0 0 0 0 0
write_rfifo((unsigned char)( vga.config.cursor_start & 0xFFu));
Expand All @@ -396,6 +430,12 @@ void PC98_GDC_state::idle_proc(void) {
}
}
break;
case GDC_CMD_ZOOM:
if(proc_step < 1) {
draw.zoom = (uint8_t)(val & 0x0f);
proc_step++;
}
break;
case GDC_CMD_PITCH_SPEC:
if (proc_step < 1)
display_pitch = (val != 0) ? val : 0x100;
Expand All @@ -406,6 +446,17 @@ void PC98_GDC_state::idle_proc(void) {
take_cursor_pos(proc_step);
}
break;
case GDC_CMD_VECTW:
if(proc_step < 11) {
cmd_parm_tmp[proc_step++] = (uint8_t)val;
vectw(proc_step);
}
break;
case GDC_CMD_TEXTW:
if(proc_step < 8) {
draw.tx[proc_step++] = (uint8_t)val;
}
break;
case GDC_CMD_CURSOR_CHAR_SETUP:
if (proc_step < 3) {
cmd_parm_tmp[proc_step++] = (uint8_t)val;
Expand Down
Loading