Fixed building for new GUS MAX.

Updated copyright dates etc.
This commit is contained in:
waltje
2019-01-13 16:37:10 -05:00
parent e77c159a66
commit 1d1aa927d5
17 changed files with 2965 additions and 2947 deletions

View File

@@ -8,7 +8,7 @@
*
* Instruction timing for i486-class.
*
* Version: @(#)codegen_timing_486.c 1.0.1 2018/02/14
* Version: @(#)codegen_timing_486.c 1.0.2 2018/12/24
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
@@ -319,24 +319,24 @@ static INLINE int COUNT(int *c, int op_32)
return *c;
}
void codegen_timing_486_block_start()
static void codegen_timing_486_block_start(void)
{
regmask_modified = 0;
}
void codegen_timing_486_start()
static void codegen_timing_486_start(void)
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat)
static void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
static void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
{
int **timings;
uint64_t *deps;
@@ -442,7 +442,7 @@ void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
}
void codegen_timing_486_block_end()
static void codegen_timing_486_block_end(void)
{
}

View File

@@ -20,7 +20,7 @@
* - PMMX decode queue
* - MMX latencies
*
* Version: @(#)codegen_timing_pentium.c 1.0.3 2018/09/04
* Version: @(#)codegen_timing_pentium.c 1.0.4 2018/12/24
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
@@ -975,20 +975,20 @@ static INLINE int codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat
}
void codegen_timing_pentium_block_start(void)
static void codegen_timing_pentium_block_start(void)
{
u_pipe_full = decode_delay = decode_delay_offset = 0;
}
void codegen_timing_pentium_start(void)
static void codegen_timing_pentium_start(void)
{
last_prefix = 0;
prefixes = 0;
}
void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat)
static void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat)
{
prefixes++;
if ((prefix & 0xf8) == 0xd8)
@@ -1122,7 +1122,7 @@ static void codegen_instruction(const uint64_t *timings, uint64_t *deps, uint8_t
}
}
void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
static void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
{
const uint64_t *timings;
uint64_t *deps;
@@ -1346,7 +1346,7 @@ nopair:
addr_regmask = 0;
}
void codegen_timing_pentium_block_end()
static void codegen_timing_pentium_block_end(void)
{
if (u_pipe_full)
{

View File

@@ -8,7 +8,7 @@
*
* Code generation timing for IDT WinChip processors.
*
* Version: @(#)codegen_timing_winchip.c 1.0.1 2018/02/14
* Version: @(#)codegen_timing_winchip.c 1.0.2 2018/12/24
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
@@ -51,7 +51,7 @@
#define CYCLES(c) (int *)c
#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8))
static int *opcode_timings[256] =
static const int *opcode_timings[256] =
{
/*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
@@ -74,7 +74,7 @@ static int *opcode_timings[256] =
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_mod3[256] =
static const int *opcode_timings_mod3[256] =
{
/*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
@@ -97,7 +97,7 @@ static int *opcode_timings_mod3[256] =
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_0f[256] =
static const int *opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -119,7 +119,7 @@ static int *opcode_timings_0f[256] =
/*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL,
};
static int *opcode_timings_0f_mod3[256] =
static const int *opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -142,57 +142,57 @@ static int *opcode_timings_0f_mod3[256] =
/*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL,
};
static int *opcode_timings_shift[8] =
static const int *opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static int *opcode_timings_shift_mod3[8] =
static const int *opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static int *opcode_timings_f6[8] =
static const int *opcode_timings_f6[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f6_mod3[8] =
static const int *opcode_timings_f6_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f7[8] =
static const int *opcode_timings_f7[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_f7_mod3[8] =
static const int *opcode_timings_f7_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_ff[8] =
static const int *opcode_timings_ff[8] =
{
&timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_ff_mod3[8] =
static const int *opcode_timings_ff_mod3[8] =
{
&timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_d8[8] =
static const int *opcode_timings_d8[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_d8_mod3[8] =
static const int *opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_d9[8] =
static const int *opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/
CYCLES(2), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3)
};
static int *opcode_timings_d9_mod3[64] =
static const int *opcode_timings_d9_mod3[64] =
{
/*FLD*/
CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
@@ -212,23 +212,23 @@ static int *opcode_timings_d9_mod3[64] =
CYCLES(70), NULL, CYCLES(72), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(474), CYCLES(474)
};
static int *opcode_timings_da[8] =
static const int *opcode_timings_da[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_da_mod3[8] =
static const int *opcode_timings_da_mod3[8] =
{
NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL
};
static int *opcode_timings_db[8] =
static const int *opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil FLDe FSTPe*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), NULL, CYCLES(8)
};
static int *opcode_timings_db_mod3[64] =
static const int *opcode_timings_db_mod3[64] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -241,63 +241,63 @@ static int *opcode_timings_db_mod3[64] =
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int *opcode_timings_dc[8] =
static const int *opcode_timings_dc[8] =
{
/* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/
CYCLES(6), CYCLES(8), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(74), CYCLES(74)
};
static int *opcode_timings_dc_mod3[8] =
static const int *opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/
CYCLES(4), CYCLES(6), NULL, NULL, CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_dd[8] =
static const int *opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/
CYCLES(2), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(5)
};
static int *opcode_timings_dd_mod3[8] =
static const int *opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_de[8] =
static const int *opcode_timings_de[8] =
{
/* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_de_mod3[8] =
static const int *opcode_timings_de_mod3[8] =
{
/* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), NULL, CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_df[8] =
static const int *opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), CYCLES(172), CYCLES(8)
};
static int *opcode_timings_df_mod3[8] =
static const int *opcode_timings_df_mod3[8] =
{
/* FFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_8x[8] =
static const int *opcode_timings_8x[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_8x_mod3[8] =
static const int *opcode_timings_8x_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81[8] =
static const int *opcode_timings_81[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81_mod3[8] =
static const int *opcode_timings_81_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
@@ -306,7 +306,7 @@ static int timing_count;
static uint8_t last_prefix;
static uint32_t regmask_modified;
static INLINE int COUNT(int *c, int op_32)
static INLINE int COUNT(const int *c, int op_32)
{
if ((uintptr_t)c <= 10000)
return (int)(uintptr_t)c;
@@ -319,26 +319,26 @@ static INLINE int COUNT(int *c, int op_32)
return *c;
}
void codegen_timing_winchip_block_start()
static void codegen_timing_winchip_block_start(void)
{
regmask_modified = 0;
}
void codegen_timing_winchip_start()
static void codegen_timing_winchip_start(void)
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat)
static void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
static void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
{
int **timings;
const int **timings;
uint64_t *deps;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
int bit8 = !(opcode & 1);
@@ -442,7 +442,7 @@ void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
}
void codegen_timing_winchip_block_end()
static void codegen_timing_winchip_block_end(void)
{
}

View File

@@ -1,334 +1,360 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Implementation of Cirrus Logic Crystal 423x sound devices.
*
* Version: @(#)snd_cs423x.c 1.0.0 2018/11/27
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018 Fred N. van Kempen.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define dbglog sound_card_log
#include "../../emu.h"
#include "../../io.h"
#include "../../device.h"
#include "../../timer.h"
#include "../system/dma.h"
#include "../system/pic.h"
#include "sound.h"
#include "snd_cs423x.h"
#define CS4231 0x80
#define CS4231A 0xa0
#define CS4232 0xa2
#define CS4232A 0xb2
#define CS4236 0x83
#define CS4236B 0x03
static int cs423x_vols[64];
void cs423x_setirq(cs423x_t *cs423x, int irq_ch)
{
cs423x->irq = irq_ch;
}
void cs423x_setdma(cs423x_t *cs423x, int dma_ch)
{
cs423x->dma = dma_ch;
}
uint8_t cs423x_read(uint16_t addr, void *p)
{
cs423x_t *cs423x = (cs423x_t *)p;
uint8_t temp = 0xff;
if (cs423x->initb)
return 0x80;
switch (addr & 3)
{
case 0: /*Index*/
if (cs423x->mode2)
temp = cs423x->index | cs423x->trd | cs423x->mce | cs423x->ia4 | cs423x->initb;
else
temp = cs423x->index | cs423x->trd | cs423x->mce | cs423x->initb;
break;
case 1:
temp = cs423x->regs[cs423x->index];
if (cs423x->index == 0x0b) {
temp ^= 0x20;
cs423x->regs[cs423x->index] = temp;
}
break;
case 2:
temp = cs423x->status;
break;
case 3: // Todo Capture I/O read
break;
}
return temp;
}
void cs423x_write(uint16_t addr, uint8_t val, void *p)
{
cs423x_t *cs423x = (cs423x_t *)p;
double freq;
switch (addr & 3)
{
case 0: /*Index*/
cs423x->index = val & (cs423x->mode2 ? 0x1F : 0x0F);
cs423x->trd = val & 0x20;
cs423x->mce = val & 0x40;
cs423x->ia4 = val & 0x10;
cs423x->initb = val & 0x80;
break;
case 1:
switch (cs423x->index)
{
case 8:
freq = (double)((val & 1) ? 16934400LL : 24576000LL);
switch ((val >> 1) & 7)
{
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
cs423x->freq = (int64_t)freq;
cs423x->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)cs423x->freq));
break;
case 9:
cs423x->enable = ((val & 0x41) == 0x01);
if (!cs423x->enable)
cs423x->out_l = cs423x->out_r = 0;
break;
case 11:
break;
case 12:
val |= 0x8a;
cs423x->mode2 = (val >> 6) & 1;
break;
case 14:
cs423x->count = cs423x->regs[15] | (val << 8);
break;
case 24:
if (!(val & 0x70))
cs423x->status &= 0xfe;
break;
case 25:
break;
}
cs423x->regs[cs423x->index] = val;
break;
case 2:
cs423x->status &= 0xfe;
break;
case 3: // Todo Playback I/O Write
break;
}
}
void cs423x_speed_changed(cs423x_t *cs423x)
{
cs423x->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)cs423x->freq));
}
void cs423x_update(cs423x_t *cs423x)
{
for (; cs423x->pos < sound_pos_global; cs423x->pos++)
{
cs423x->buffer[cs423x->pos * 2] = cs423x->out_l;
cs423x->buffer[cs423x->pos * 2 + 1] = cs423x->out_r;
}
}
static void cs423x_poll(void *p)
{
cs423x_t *cs423x = (cs423x_t *)p;
if (cs423x->timer_latch)
cs423x->timer_count += cs423x->timer_latch;
else
cs423x->timer_count = TIMER_USEC;
cs423x_update(cs423x);
if (cs423x->enable) {
int32_t temp;
if (!(cs423x->mode2)) {
switch (cs423x->regs[8] & 0x70)
{
case 0x00: /*Mono, 8-bit PCM*/
cs423x->out_l = cs423x->out_r = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
break;
case 0x10: /*Stereo, 8-bit PCM*/
cs423x->out_l = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
cs423x->out_r = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
break;
case 0x40: /*Mono, 16-bit PCM*/
temp = dma_channel_read(cs423x->dma);
cs423x->out_l = cs423x->out_r = (dma_channel_read(cs423x->dma) << 8) | temp;
break;
case 0x50: /*Stereo, 16-bit PCM*/
temp = dma_channel_read(cs423x->dma);
cs423x->out_l = (dma_channel_read(cs423x->dma) << 8) | temp;
temp = dma_channel_read(cs423x->dma);
cs423x->out_r = (dma_channel_read(cs423x->dma) << 8) | temp;
break;
}
}
else {
switch (cs423x->regs[8] & 0xf0)
{
case 0x00: /*Mono, 8-bit PCM*/
cs423x->out_l = cs423x->out_r = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
break;
case 0x10: /*Stereo, 8-bit PCM*/
cs423x->out_l = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
cs423x->out_r = (dma_channel_read(cs423x->dma) ^ 0x80) * 256;
break;
case 0x40: /*Mono, 16-bit PCM*/
case 0xc0: /*Mono, 16-bit PCM Big-Endian should not happen on x86*/
temp = dma_channel_read(cs423x->dma);
cs423x->out_l = cs423x->out_r = (dma_channel_read(cs423x->dma) << 8) | temp;
break;
case 0x50: /*Stereo, 16-bit PCM*/
case 0xd0: /*Stereo, 16-bit PCM Big-Endian. Should not happen on x86*/
temp = dma_channel_read(cs423x->dma);
cs423x->out_l = (dma_channel_read(cs423x->dma) << 8) | temp;
temp = dma_channel_read(cs423x->dma);
cs423x->out_r = (dma_channel_read(cs423x->dma) << 8) | temp;
break;
case 0xa0: /*TODO Mono, ADPCM, 4-bit*/
case 0xb0: /*TODO Stereo, ADPCM, 4-bit*/
break;
}
}
if (cs423x->regs[6] & 0x80) // Mute Left-Channel
cs423x->out_l = 0;
else
cs423x->out_l = (cs423x->out_l * cs423x_vols[cs423x->regs[6] & 0x3f]) >> 16;
if (cs423x->regs[7] & 0x80) // Mute Right-Channel
cs423x->out_r = 0;
else
cs423x->out_r = (cs423x->out_r * cs423x_vols[cs423x->regs[7] & 0x3f]) >> 16;
if (cs423x->regs[26] & 0x40) // Mono Output Mute
cs423x->out_l = cs423x->out_r = 0;
if (cs423x->count < 0) {
cs423x->count = cs423x->regs[15] | (cs423x->regs[14] << 8);
if (!(cs423x->status & 0x01)) {
cs423x->status |= 0x01;
if (cs423x->regs[10] & 2)
picint(1 << cs423x->irq);
}
}
cs423x->count--;
}
else {
cs423x->out_l = cs423x->out_r = 0;
}
}
void cs423x_init(cs423x_t *cs423x)
{
int c;
double attenuation;
cs423x->enable = 0;
cs423x->status = 0xcc;
cs423x->index = cs423x->trd = 0;
cs423x->mce = 0x40;
cs423x->initb = 0;
cs423x->mode2 = 0;
cs423x->regs[0] = cs423x->regs[1] = 0;
cs423x->regs[2] = cs423x->regs[3] = 0x88;
cs423x->regs[4] = cs423x->regs[5] = 0x88;
cs423x->regs[6] = cs423x->regs[7] = 0x80;
cs423x->regs[8] = 0;
cs423x->regs[9] = 0x08;
cs423x->regs[10] = cs423x->regs[11] = 0;
cs423x->regs[12] = 0x8a;
cs423x->regs[13] = 0;
cs423x->regs[14] = cs423x->regs[15] = 0;
cs423x->regs[16] = cs423x->regs[17] = 0;
cs423x->regs[18] = cs423x->regs[19] = 0x88;
cs423x->regs[22] = 0x80;
cs423x->regs[24] = 0;
cs423x->regs[25] = CS4231; //CS4231 for GUS MAX
cs423x->regs[26] = 0x80;
cs423x->regs[29] = 0x80;
cs423x->out_l = 0;
cs423x->out_r = 0;
for (c = 0; c < 64; c++) // DAC and Loopback attenuation
{
attenuation = 0.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
attenuation = pow(10, attenuation / 10);
cs423x_vols[c] = (int)(attenuation * 65536);
}
timer_add(cs423x_poll, &cs423x->timer_count, &cs423x->enable, cs423x);
}
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Implementation of Cirrus Logic Crystal 423x sound devices.
*
* Version: @(#)snd_cs423x.c 1.0.1 2019/01/13
*
* Authors: Altheos, <altheos@varcem.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018,2019 Altheos.
* Copyright 2018,2019 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define dbglog sound_card_log
#include "../../emu.h"
#include "../../io.h"
#include "../../device.h"
#include "../../timer.h"
#include "../system/dma.h"
#include "../system/pic.h"
#include "sound.h"
#include "snd_cs423x.h"
#define CS4231 0x80
#define CS4231A 0xa0
#define CS4232 0xa2
#define CS4232A 0xb2
#define CS4236 0x83
#define CS4236B 0x03
static int cs423x_vols[64];
void
cs423x_setirq(cs423x_t *dev, int irq_ch)
{
dev->irq = irq_ch;
}
void
cs423x_setdma(cs423x_t *dev, int dma_ch)
{
dev->dma = dma_ch;
}
uint8_t
cs423x_read(uint16_t addr, void *priv)
{
cs423x_t *dev = (cs423x_t *)priv;
uint8_t ret = 0xff;
if (dev->initb)
return 0x80;
switch (addr & 3) {
case 0: /*Index*/
if (dev->mode2)
ret = dev->indx | dev->trd | dev->mce | dev->ia4 | dev->initb;
else
ret = dev->indx | dev->trd | dev->mce | dev->initb;
break;
case 1:
ret = dev->regs[dev->indx];
if (dev->indx == 0x0b) {
ret ^= 0x20;
dev->regs[dev->indx] = ret;
}
break;
case 2:
ret = dev->status;
break;
case 3: // Todo Capture I/O read
break;
}
return ret;
}
void
cs423x_write(uint16_t addr, uint8_t val, void *priv)
{
cs423x_t *dev = (cs423x_t *)priv;
double freq;
switch (addr & 3) {
case 0: /*Index*/
dev->indx = val & (dev->mode2 ? 0x1f : 0x0f);
dev->trd = val & 0x20;
dev->mce = val & 0x40;
dev->ia4 = val & 0x10;
dev->initb = val & 0x80;
break;
case 1:
switch (dev->indx) {
case 8:
freq = (double)((val & 1) ? 16934400LL : 24576000LL);
switch ((val >> 1) & 7) {
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
dev->freq = (int64_t)freq;
dev->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)dev->freq));
break;
case 9:
dev->enable = ((val & 0x41) == 0x01);
if (! dev->enable)
dev->out_l = dev->out_r = 0;
break;
case 11:
break;
case 12:
val |= 0x8a;
dev->mode2 = (val >> 6) & 1;
break;
case 14:
dev->count = dev->regs[15] | (val << 8);
break;
case 24:
if (! (val & 0x70))
dev->status &= 0xfe;
break;
case 25:
break;
}
dev->regs[dev->indx] = val;
break;
case 2:
dev->status &= 0xfe;
break;
case 3: // Todo Playback I/O Write
break;
}
}
void
cs423x_update(cs423x_t *dev)
{
for (; dev->pos < sound_pos_global; dev->pos++) {
dev->buffer[dev->pos * 2] = dev->out_l;
dev->buffer[dev->pos * 2 + 1] = dev->out_r;
}
}
static void
cs423x_poll(void *priv)
{
cs423x_t *dev = (cs423x_t *)priv;
int32_t temp;
if (dev->timer_latch)
dev->timer_count += dev->timer_latch;
else
dev->timer_count = TIMER_USEC;
cs423x_update(dev);
if (! dev->enable) {
dev->out_l = dev->out_r = 0;
return;
}
if (! (dev->mode2)) switch (dev->regs[8] & 0x70) {
case 0x00: /*Mono, 8-bit PCM*/
dev->out_l = dev->out_r = (dma_channel_read(dev->dma) ^ 0x80) * 256;
break;
case 0x10: /*Stereo, 8-bit PCM*/
dev->out_l = (dma_channel_read(dev->dma) ^ 0x80) * 256;
dev->out_r = (dma_channel_read(dev->dma) ^ 0x80) * 256;
break;
case 0x40: /*Mono, 16-bit PCM*/
temp = dma_channel_read(dev->dma);
dev->out_l = dev->out_r = (dma_channel_read(dev->dma) << 8) | temp;
break;
case 0x50: /*Stereo, 16-bit PCM*/
temp = dma_channel_read(dev->dma);
dev->out_l = (dma_channel_read(dev->dma) << 8) | temp;
temp = dma_channel_read(dev->dma);
dev->out_r = (dma_channel_read(dev->dma) << 8) | temp;
break;
} else switch (dev->regs[8] & 0xf0) {
case 0x00: /*Mono, 8-bit PCM*/
dev->out_l = dev->out_r = (dma_channel_read(dev->dma) ^ 0x80) * 256;
break;
case 0x10: /*Stereo, 8-bit PCM*/
dev->out_l = (dma_channel_read(dev->dma) ^ 0x80) * 256;
dev->out_r = (dma_channel_read(dev->dma) ^ 0x80) * 256;
break;
case 0x40: /*Mono, 16-bit PCM*/
case 0xc0: /*Mono, 16-bit PCM Big-Endian should not happen on x86*/
temp = dma_channel_read(dev->dma);
dev->out_l = dev->out_r = (dma_channel_read(dev->dma) << 8) | temp;
break;
case 0x50: /*Stereo, 16-bit PCM*/
case 0xd0: /*Stereo, 16-bit PCM Big-Endian. Should not happen on x86*/
temp = dma_channel_read(dev->dma);
dev->out_l = (dma_channel_read(dev->dma) << 8) | temp;
temp = dma_channel_read(dev->dma);
dev->out_r = (dma_channel_read(dev->dma) << 8) | temp;
break;
case 0xa0: /*TODO Mono, ADPCM, 4-bit*/
case 0xb0: /*TODO Stereo, ADPCM, 4-bit*/
break;
}
if (dev->regs[6] & 0x80) // Mute Left-Channel
dev->out_l = 0;
else
dev->out_l = (dev->out_l * cs423x_vols[dev->regs[6] & 0x3f]) >> 16;
if (dev->regs[7] & 0x80) // Mute Right-Channel
dev->out_r = 0;
else
dev->out_r = (dev->out_r * cs423x_vols[dev->regs[7] & 0x3f]) >> 16;
if (dev->regs[26] & 0x40) // Mono Output Mute
dev->out_l = dev->out_r = 0;
if (dev->count < 0) {
dev->count = dev->regs[15] | (dev->regs[14] << 8);
if (! (dev->status & 0x01)) {
dev->status |= 0x01;
if (dev->regs[10] & 2)
picint(1 << dev->irq);
}
}
dev->count--;
}
void
cs423x_init(cs423x_t *dev)
{
double attenuation;
int c;
dev->enable = 0;
dev->status = 0xcc;
dev->indx = dev->trd = 0;
dev->mce = 0x40;
dev->initb = 0;
dev->mode2 = 0;
dev->regs[0] = dev->regs[1] = 0;
dev->regs[2] = dev->regs[3] = 0x88;
dev->regs[4] = dev->regs[5] = 0x88;
dev->regs[6] = dev->regs[7] = 0x80;
dev->regs[8] = 0;
dev->regs[9] = 0x08;
dev->regs[10] = dev->regs[11] = 0;
dev->regs[12] = 0x8a;
dev->regs[13] = 0;
dev->regs[14] = dev->regs[15] = 0;
dev->regs[16] = dev->regs[17] = 0;
dev->regs[18] = dev->regs[19] = 0x88;
dev->regs[22] = 0x80;
dev->regs[24] = 0;
dev->regs[25] = CS4231; //CS4231 for GUS MAX
dev->regs[26] = 0x80;
dev->regs[29] = 0x80;
dev->out_l = 0;
dev->out_r = 0;
for (c = 0; c < 64; c++) { // DAC and Loopback attenuation
attenuation = 0.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
attenuation = pow(10, attenuation / 10);
cs423x_vols[c] = (int)(attenuation * 65536);
}
timer_add(cs423x_poll, &dev->timer_count, &dev->enable, dev);
}
void
cs423x_speed_changed(cs423x_t *dev)
{
dev->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)dev->freq));
}

View File

@@ -1,73 +1,94 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Definitions for the Crystal CS423x driver.
*
* Version: @(#)snd_cs423x.h 1.0.0 2018/11/27
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018 Fred N. van Kempen.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
typedef struct cs423x_t
{
int index;
uint8_t regs[32];
uint8_t status;
int trd;
int mce;
int ia4;
int mode2;
int initb;
int count;
int16_t out_l, out_r;
int64_t enable;
int irq, dma;
int64_t freq;
int64_t timer_count, timer_latch;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
} cs423x_t;
void cs423x_setirq(cs423x_t *cs423x, int irq);
void cs423x_setdma(cs423x_t *cs423x, int dma);
uint8_t cs423x_read(uint16_t addr, void *p);
void cs423x_write(uint16_t addr, uint8_t val, void *p);
void cs423x_update(cs423x_t *cs423x);
void cs423x_speed_changed(cs423x_t *cs423x);
void cs423x_init(cs423x_t *cs423x);
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Definitions for the Crystal CS423x driver.
*
* Version: @(#)snd_cs423x.h 1.0.1 2019/01/13
*
* Authors: Altheos, <altheos@varcem.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018,2019 Altheos.
* Copyright 2018,2019 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SND_CS423X_H
# define SND_CS423X_H
typedef struct {
int indx;
uint8_t regs[32];
uint8_t status;
int trd;
int mce;
int ia4;
int mode2;
int initb;
int count;
int16_t out_l, out_r;
int64_t enable;
int irq, dma;
int64_t freq;
int64_t timer_count,
timer_latch;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
} cs423x_t;
extern void cs423x_setirq(cs423x_t *, int irq);
extern void cs423x_setdma(cs423x_t *, int dma);
extern uint8_t cs423x_read(uint16_t addr, void *priv);
extern void cs423x_write(uint16_t addr, uint8_t val, void *priv);
extern void cs423x_update(cs423x_t *);
extern void cs423x_speed_changed(cs423x_t *);
extern void cs423x_init(cs423x_t *);
#endif /*SND_CS423X_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,13 @@
*
* Sound devices support module.
*
* Version: @(#)sound_dev.c 1.0.11 2018/11/27
* Version: @(#)sound_dev.c 1.0.12 2019/01/13
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*

View File

@@ -8,11 +8,11 @@
*
* Implement a generic NVRAM/CMOS/RTC device.
*
* Version: @(#)nvr.c 1.0.13 2018/11/01
* Version: @(#)nvr.c 1.0.14 2019/01/03
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2017-2019 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
@@ -60,7 +60,9 @@
int nvr_dosave; /* NVR is dirty, needs saved */
static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
static const int8_t days_in_month[12] = {
31,28,31,30,31,30,31,31,30,31,30,31
};
static struct tm intclk;
static nvr_t *saved_nvr = NULL;

View File

@@ -8,7 +8,7 @@
*
* Main emulator module where most things are controlled.
*
* Version: @(#)pc.c 1.0.61 2018/11/13
* Version: @(#)pc.c 1.0.62 2018/11/22
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -873,9 +873,6 @@ pc_init(void)
codegen_init();
#endif
#ifdef WALTJE_SERIAL
serial_init();
#endif
keyboard_init();
joystick_init();
video_init();

View File

@@ -8,7 +8,7 @@
*
* Define the various platform support functions.
*
* Version: @(#)plat.h 1.0.21 2018/11/20
* Version: @(#)plat.h 1.0.22 2018/11/24
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -191,7 +191,6 @@ extern int plat_midi_write(uint8_t val);
extern int plat_midi_get_num_devs();
extern void plat_midi_get_dev_name(int num, char *s);
/* Thread support. */
typedef void thread_t;
typedef void event_t;

View File

@@ -8,7 +8,7 @@
#
# Supported Languages database.
#
# Version: @(#)VARCem.lang 1.0.5 2018/10/27
# Version: @(#)VARCem.lang 1.0.6 2018/12/08
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
@@ -51,6 +51,7 @@ DU,0413,LANG_DUTCH,SUBLANG_DUTCH,Dutch
ES,040a,LANG_SPANISH,SUBLANG_SPANISH,Spanish
FI,040b,LANG_FINNISH,SUBLANG_FINNISH_FINLAND,Finnish
FR,040c,LANG_FRENCH,SUBLANG_FRENCH,French
HE,040d,LANG_HEBREW,SUBLANG_HEBREW,Hebrew
IT,0410,LANG_ITALIAN,SUBLANG_ITALIAN,Italian
JP,0411,LANG_JAPANESE,SUBLANG_JAPANESE_JAPAN,Japanese
KR,0412,LANG_KOREAN,SUBLANG_KOREAN,Korean

View File

@@ -8,11 +8,11 @@
*
* Application resource script for Windows.
*
* Version: @(#)VARCem.rc 1.0.35 2018/11/05
* Version: @(#)VARCem.rc 1.0.36 2019/01/13
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2017-2019 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
@@ -226,7 +226,7 @@ VS_VERSION_INFO VERSIONINFO
VALUE "FileDescription", "Virtual ARchaeological Computer EMulator"
VALUE "FileVersion", EMU_VERSION
VALUE "InternalName", EMU_NAME
VALUE "LegalCopyright", "Copyright Fred N. van Kempen and others, 2007-2018, Released under a mixed BSD 3-Clause and GPL License"
VALUE "LegalCopyright", "Copyright Fred N. van Kempen and others, 2007-2019, Released under a mixed BSD 3-Clause and GPL License"
VALUE "OriginalFilename", "VARCem.exe"
VALUE "ProductName", "VARCem Emulator"
VALUE "ProductVersion", EMU_VERSION

View File

@@ -10,11 +10,11 @@
* which require some weird processing. This file allows us
* to use a single master for all those languages.
*
* Version: @(#)VARCem.rpp 1.0.3 2018/11/05
* Version: @(#)VARCem.rpp 1.0.4 2019/01/13
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018 Fred N. van Kempen.
* Copyright 2018,2019 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
@@ -98,7 +98,7 @@ VS_VERSION_INFO VERSIONINFO
VALUE "FileDescription", "VARCem Language Module"
VALUE "FileVersion", STR(STR_VERSION)
VALUE "InternalName", EMU_NAME
VALUE "LegalCopyright", "Copyright 2018 The VARCem Team"
VALUE "LegalCopyright", "Copyright 2018,2019 The VARCem Team"
VALUE "OriginalFilename", DLLNAME(LANG)
VALUE "ProductName", "VARCem Emulator"
VALUE "ProductVersion", EMU_VERSION

View File

@@ -8,11 +8,11 @@
#
# Makefile for Windows systems using the MinGW32 environment.
#
# Version: @(#)Makefile.mingw 1.0.70 2018/11/30
# Version: @(#)Makefile.mingw 1.0.71 2019/01/13
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2017,2018 Fred N. van Kempen.
# Copyright 2017-2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
@@ -140,6 +140,9 @@ endif
ifndef PAS16
PAS16 := n
endif
ifndef GUSMAX
GUSMAX := n
endif
ifndef XL24
XL24 := n
endif
@@ -152,9 +155,6 @@ endif
ifndef HOSTCD
HOSTCD := n
endif
ifndef GUSMAX
GUSMAX := n
endif
# Name of the executable.
@@ -186,10 +186,10 @@ ifeq ($(DEV_BUILD), y)
PORTABLE3 := y
I686 := y
PAS16 := y
GUSMAX := y
XL24 := y
WONDER := y
HOSTCD := y
GUSMAX := y
endif
@@ -558,6 +558,11 @@ ifeq ($(DEV_BRANCH), y)
DEVBROBJ += snd_pas16.o
endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
DEVBROBJ += snd_cs423x.o
endif
ifeq ($(WONDER), y)
OPTS += -DUSE_WONDER
endif
@@ -575,10 +580,6 @@ ifeq ($(DEV_BRANCH), y)
OPTS += -DUSE_HOST_CDROM
endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
DEVBROBJ += snd_cs423x.o
endif
endif
@@ -740,7 +741,7 @@ VIDOBJ := video.o \
PLATOBJ := win.o \
win_lang.o win_dynld.o win_opendir.o win_thread.o \
win_cdrom.o win_keyboard.o win_mouse.o win_joystick.o \
win_midi.o
win_serial.o win_midi.o
ifeq ($(CRASHDUMP), y)
PLATOBJ += win_crashdump.o
endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
* Windows and UNIX systems, with support for FTDI and Prolific
* USB ports. Support for these has been removed.
*
* Version: @(#)win_serial.c 1.0.4 2018/10/07
* Version: @(#)win_serial.c 1.0.5 2018/11/22
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -53,79 +53,88 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLAT_SERIAL_C
#include "../emu.h"
#include "../plat.h"
#include "../devices/ports/serial.h"
typedef struct {
char name[80]; /* name of open port */
void (*rd_done)(void *, int);
void *rd_arg;
HANDLE handle;
OVERLAPPED rov, /* READ and WRITE events */
wov;
int tmo; /* current timeout value */
DCB dcb, /* terminal settings */
odcb;
thread_t *tid; /* pointer to receiver thread */
char buff[1024];
int icnt, ihead, itail;
} serial_t;
/* Handle the receiving of data from the host port. */
static void
bhtty_reader(void *arg)
reader_thread(void *arg)
{
BHTTY *pp = (BHTTY *)arg;
unsigned char b;
serial_t *dev = (serial_t *)arg;
uint8_t b;
DWORD n;
pclog("%s: thread started\n", pp->name);
INFO("%s: thread started\n", dev->name);
/* As long as the channel is open.. */
while (pp->tid != NULL) {
while (dev->tid != NULL) {
/* Post a READ on the device. */
n = 0;
if (ReadFile(pp->handle, &b, (DWORD)1, &n, &pp->rov) == FALSE) {
if (ReadFile(dev->handle, &b, (DWORD)1, &n, &dev->rov) == FALSE) {
n = GetLastError();
if (n != ERROR_IO_PENDING) {
/* Not good, we got an error. */
pclog("%s: I/O error %d in read!\n", pp->name, n);
ERRLOG("%s: I/O error %i in read!\n", dev->name, n);
break;
}
/* The read is pending, wait for it.. */
if (GetOverlappedResult(pp->handle, &pp->rov, &n, TRUE) == FALSE) {
if (GetOverlappedResult(dev->handle, &dev->rov, &n, TRUE) == FALSE) {
n = GetLastError();
pclog("%s: I/O error %d in read!\n", pp->name, n);
ERRLOG("%s: I/O error %i in read!\n", dev->name, n);
break;
}
}
pclog("%s: got %d bytes of data\n", pp->name, n);
pclog(0,"%s: got %i bytes of data\n", dev->name, n);
if (n == 1) {
/* We got data, update stuff. */
if (pp->icnt < sizeof(pp->buff)) {
pclog("%s: queued byte %02x (%d)\n", pp->name, b, pp->icnt+1);
pp->buff[pp->ihead++] = b;
pp->ihead &= (sizeof(pp->buff)-1);
pp->icnt++;
if (dev->icnt < sizeof(dev->buff)) {
pclog(0,"%s: queued byte %02x (%i)\n", dev->name, b, dev->icnt+1);
dev->buff[dev->ihead++] = b;
dev->ihead &= (sizeof(dev->buff)-1);
dev->icnt++;
/* Do a callback to let them know. */
if (pp->rd_done != NULL)
pp->rd_done(pp->rd_arg, n);
if (dev->rd_done != NULL)
dev->rd_done(dev->rd_arg, n);
} else {
pclog("%s: RX buffer overrun!\n", pp->name);
ERRLOG("%s: RX buffer overrun!\n", dev->name);
}
}
}
/* Error or done, clean up. */
pp->tid = NULL;
pclog("%s: thread stopped.\n", pp->name);
dev->tid = NULL;
INFO("%s: thread stopped.\n", dev->name);
}
/* Set the state of a port. */
int
bhtty_sstate(BHTTY *pp, void *arg)
static int
set_state(serial_t *dev, void *arg)
{
/* Make sure we can do this. */
if (arg == NULL) {
pclog("%s: invalid argument\n", pp->name);
return(-1);
}
if (SetCommState(pp->handle, (DCB *)arg) == FALSE) {
/* Mark an error. */
pclog("%s: set state: %d\n", pp->name, GetLastError());
if (SetCommState(dev->handle, (DCB *)arg) == FALSE) {
/* Mark as error. */
ERRLOG("%s: set state: %i\n", dev->name, GetLastError());
return(-1);
}
@@ -134,18 +143,12 @@ bhtty_sstate(BHTTY *pp, void *arg)
/* Fetch the state of a port. */
int
bhtty_gstate(BHTTY *pp, void *arg)
static int
get_state(serial_t *dev, void *arg)
{
/* Make sure we can do this. */
if (arg == NULL) {
pclog("%s: invalid argument\n", pp->name);
return(-1);
}
if (GetCommState(pp->handle, (DCB *)arg) == FALSE) {
/* Mark an error. */
pclog("%s: get state: %d\n", pp->name, GetLastError());
if (GetCommState(dev->handle, (DCB *)arg) == FALSE) {
/* Mark as error. */
ERRLOG("%s: get state: %i\n", dev->name, GetLastError());
return(-1);
}
@@ -154,42 +157,42 @@ bhtty_gstate(BHTTY *pp, void *arg)
/* Enable or disable RTS/CTS mode (hardware handshaking.) */
int
bhtty_crtscts(BHTTY *pp, char yesno)
static int
set_crtscts(serial_t *dev, int8_t yes)
{
/* Get the current mode. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
if (get_state(dev, &dev->dcb) < 0) return(-1);
switch(yesno) {
switch (yes) {
case 0: /* disable CRTSCTS */
pp->dcb.fOutxDsrFlow = 0; /* disable DSR/DCD mode */
pp->dcb.fDsrSensitivity = 0;
dev->dcb.fOutxDsrFlow = 0; /* disable DSR/DCD mode */
dev->dcb.fDsrSensitivity = 0;
pp->dcb.fOutxCtsFlow = 0; /* disable RTS/CTS mode */
dev->dcb.fOutxCtsFlow = 0; /* disable RTS/CTS mode */
pp->dcb.fTXContinueOnXoff = 0; /* disable XON/XOFF mode */
pp->dcb.fOutX = 0;
pp->dcb.fInX = 0;
dev->dcb.fTXContinueOnXoff = 0; /* disable XON/XOFF mode */
dev->dcb.fOutX = 0;
dev->dcb.fInX = 0;
break;
case 1: /* enable CRTSCTS */
pp->dcb.fOutxDsrFlow = 0; /* disable DSR/DCD mode */
pp->dcb.fDsrSensitivity = 0;
dev->dcb.fOutxDsrFlow = 0; /* disable DSR/DCD mode */
dev->dcb.fDsrSensitivity = 0;
pp->dcb.fOutxCtsFlow = 1; /* enable RTS/CTS mode */
dev->dcb.fOutxCtsFlow = 1; /* enable RTS/CTS mode */
pp->dcb.fTXContinueOnXoff = 0; /* disable XON/XOFF mode */
pp->dcb.fOutX = 0;
pp->dcb.fInX = 0;
dev->dcb.fTXContinueOnXoff = 0; /* disable XON/XOFF mode */
dev->dcb.fOutX = 0;
dev->dcb.fInX = 0;
break;
default:
pclog("%s: invalid parameter '%d'!\n", pp->name, yesno);
ERRLOG("%s: invalid parameter '%i'!\n", dev->name, yes);
return(-1);
}
/* Set new mode. */
if (bhtty_sstate(pp, &pp->dcb) < 0) return(-1);
if (set_state(dev, &dev->dcb) < 0) return(-1);
return(0);
}
@@ -197,13 +200,15 @@ bhtty_crtscts(BHTTY *pp, char yesno)
/* Set the port parameters. */
int
bhtty_params(BHTTY *pp, char dbit, char par, char sbit)
plat_serial_params(void *arg, char dbit, char par, char sbit)
{
serial_t *dev = (serial_t *)arg;
/* Get the current mode. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
if (get_state(dev, &dev->dcb) < 0) return(-1);
/* Set the desired word length. */
switch((int)dbit) {
switch ((int)dbit) {
case -1: /* no change */
break;
@@ -214,36 +219,36 @@ bhtty_params(BHTTY *pp, char dbit, char par, char sbit)
case 7:
case 8:
pp->dcb.ByteSize = dbit;
dev->dcb.ByteSize = dbit;
break;
default:
pclog("%s: invalid parameter '%d'!\n", pp->name, dbit);
ERRLOG("%s: invalid parameter '%i'!\n", dev->name, dbit);
return(-1);
}
/* Set the type of parity encoding. */
switch((int)par) {
switch ((int)par) {
case -1: /* no change */
case ' ':
break;
case 0:
case 'N':
pp->dcb.fParity = FALSE;
pp->dcb.Parity = NOPARITY;
dev->dcb.fParity = FALSE;
dev->dcb.Parity = NOPARITY;
break;
case 1:
case 'O':
pp->dcb.fParity = TRUE;
pp->dcb.Parity = ODDPARITY;
dev->dcb.fParity = TRUE;
dev->dcb.Parity = ODDPARITY;
break;
case 2:
case 'E':
pp->dcb.fParity = TRUE;
pp->dcb.Parity = EVENPARITY;
dev->dcb.fParity = TRUE;
dev->dcb.Parity = EVENPARITY;
break;
case 3:
@@ -253,30 +258,30 @@ bhtty_params(BHTTY *pp, char dbit, char par, char sbit)
break;
default:
pclog("%s: invalid parameter '%c'!\n", pp->name, par);
ERRLOG("%s: invalid parameter '%c'!\n", dev->name, par);
return(-1);
}
/* Set the number of stop bits. */
switch((int)sbit) {
switch ((int)sbit) {
case -1: /* no change */
break;
case 1:
pp->dcb.StopBits = ONESTOPBIT;
dev->dcb.StopBits = ONESTOPBIT;
break;
case 2:
pp->dcb.StopBits = TWOSTOPBITS;
dev->dcb.StopBits = TWOSTOPBITS;
break;
default:
pclog("%s: invalid parameter '%d'!\n", pp->name, sbit);
ERRLOG("%s: invalid parameter '%i'!\n", dev->name, sbit);
return(-1);
}
/* Set new mode. */
if (bhtty_sstate(pp, &pp->dcb) < 0) return(-1);
if (set_state(dev, &dev->dcb) < 0) return(-1);
return(0);
}
@@ -284,13 +289,14 @@ bhtty_params(BHTTY *pp, char dbit, char par, char sbit)
/* Put a port in transparent ("raw") state. */
void
bhtty_raw(BHTTY *pp, void *arg)
plat_serial_raw(void *arg, void *data)
{
DCB *dcb = (DCB *)arg;
serial_t *dev = (serial_t *)arg;
DCB *dcb = (DCB *)data;
/* Make sure we can do this. */
if (arg == NULL) {
pclog("%s: invalid parameter\n", pp->name);
if (dcb == NULL) {
ERRLOG("%s: invalid parameter\n", dev->name);
return;
}
@@ -328,10 +334,12 @@ bhtty_raw(BHTTY *pp, void *arg)
/* Set the port speed. */
int
bhtty_speed(BHTTY *pp, long speed)
plat_serial_speed(void *arg, long speed)
{
serial_t *dev = (serial_t *)arg;
/* Get the current mode and speed. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
if (get_state(dev, &dev->dcb) < 0) return(-1);
/*
* Set speed.
@@ -340,10 +348,10 @@ bhtty_speed(BHTTY *pp, long speed)
* with DCB_xxx speed values here, but we removed that
* and just hardcode the speed value into DCB. --FvK
*/
pp->dcb.BaudRate = speed;
dev->dcb.BaudRate = speed;
/* Set new speed. */
if (bhtty_sstate(pp, &pp->dcb) < 0) return(-1);
if (set_state(dev, &dev->dcb) < 0) return(-1);
return(0);
}
@@ -351,25 +359,26 @@ bhtty_speed(BHTTY *pp, long speed)
/* Clean up and flush. */
int
bhtty_flush(BHTTY *pp)
plat_serial_flush(void *arg)
{
serial_t *dev = (serial_t *)arg;
DWORD dwErrs;
COMSTAT cst;
/* First, clear any errors. */
(void)ClearCommError(pp->handle, &dwErrs, &cst);
(void)ClearCommError(dev->handle, &dwErrs, &cst);
/* Now flush all buffers. */
if (PurgeComm(pp->handle,
if (PurgeComm(dev->handle,
(PURGE_RXABORT | PURGE_TXABORT | \
PURGE_RXCLEAR | PURGE_TXCLEAR)) == FALSE) {
pclog("%s: flush: %d\n", pp->name, GetLastError());
ERRLOG("%s: flush: %i\n", dev->name, GetLastError());
return(-1);
}
/* Re-clear any errors. */
if (ClearCommError(pp->handle, &dwErrs, &cst) == FALSE) {
pclog("%s: clear errors: %d\n", pp->name, GetLastError());
if (ClearCommError(dev->handle, &dwErrs, &cst) == FALSE) {
ERRLOG("%s: clear errors: %i\n", dev->name, GetLastError());
return(-1);
}
@@ -377,80 +386,76 @@ bhtty_flush(BHTTY *pp)
}
/* Close an open serial port. */
/* API: close an open serial port. */
void
bhtty_close(BHTTY *pp)
plat_serial_close(void *arg)
{
serial_t *dev = (serial_t *)arg;
/* If the polling thread is running, stop it. */
(void)bhtty_active(pp, 0);
plat_serial_active(arg, 0);
/* Close the event handles. */
if (pp->rov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(pp->rov.hEvent);
if (pp->wov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(pp->wov.hEvent);
if (dev->rov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(dev->rov.hEvent);
if (dev->wov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(dev->wov.hEvent);
if (pp->handle != INVALID_HANDLE_VALUE) {
pclog("%s: closing host port\n", pp->name);
if (dev->handle != INVALID_HANDLE_VALUE) {
INFO("%s: closing host port\n", dev->name);
/* Restore the previous port state, if any. */
(void)bhtty_sstate(pp, &pp->odcb);
set_state(dev, &dev->odcb);
/* Close the port. */
CloseHandle(pp->handle);
pp->handle = INVALID_HANDLE_VALUE;
CloseHandle(dev->handle);
}
/* Release the control block. */
free(pp);
free(dev);
}
/* Open a host serial port for I/O. */
BHTTY *
bhtty_open(char *port, int tmo)
/* API: open a host serial port for I/O. */
void *
plat_serial_open(const char *port, int tmo)
{
char temp[84];
COMMTIMEOUTS to;
COMMCONFIG conf;
BHTTY *pp;
serial_t *dev;
DWORD d;
/* First things first... create a control block. */
if ((pp = (BHTTY *)mem_alloc(sizeof(BHTTY))) == NULL) {
pclog("%s: out of memory!\n", port);
if ((dev = (serial_t *)mem_alloc(sizeof(serial_t))) == NULL) {
ERRLOG("%s: out of memory!\n", port);
return(NULL);
}
memset(pp, 0x00, sizeof(BHTTY));
strncpy(pp->name, port, sizeof(pp->name)-1);
memset(dev, 0x00, sizeof(serial_t));
strncpy(dev->name, port, sizeof(dev->name)-1);
/* Try a regular Win32 serial port. */
sprintf(temp, "\\\\.\\%s", pp->name);
if ((pp->handle = CreateFile(temp,
(GENERIC_READ|GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0)) == INVALID_HANDLE_VALUE) {
pclog("%s: open port: %d\n", pp->name, GetLastError());
free(pp);
sprintf(temp, "\\\\.\\%s", dev->name);
if ((dev->handle = CreateFile(temp,
(GENERIC_READ|GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0)) == INVALID_HANDLE_VALUE) {
ERRLOG("%s: open port: %i\n", dev->name, GetLastError());
free(dev);
return(NULL);
}
/* Create event handles. */
pp->rov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pp->wov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
dev->rov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
dev->wov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/* Set up buffer size of the port. */
if (SetupComm(pp->handle, 32768L, 32768L) == FALSE) {
/* This fails on FTDI-based devices. */
pclog("%s: set buffers: %d\n", pp->name, GetLastError());
#if 0
CloseHandle(pp->handle);
free(pp);
return(NULL);
#endif
if (SetupComm(dev->handle, 32768L, 32768L) == FALSE) {
/* This fails on FTDI-based devices, so, not fatal. */
ERRLOG("%s: set buffers: %i\n", dev->name, GetLastError());
}
/* Grab default config for the driver and set it. */
@@ -461,48 +466,44 @@ bhtty_open(char *port, int tmo)
/* Change config here... */
/* Set new configuration. */
if (SetCommConfig(pp->handle, &conf, d) == FALSE) {
/* This fails on FTDI-based devices. */
pclog("%s: set configuration: %d\n", pp->name, GetLastError());
#if 0
CloseHandle(pp->handle);
free(pp);
return(NULL);
#endif
if (SetCommConfig(dev->handle, &conf, d) == FALSE) {
/* This fails on FTDI-based devices, so, not fatal. */
ERRLOG("%s: set config: %i\n", dev->name, GetLastError());
}
}
pclog("%s: host port '%s' open\n", pp->name, temp);
ERRLOG("%s: host port '%s' open\n", dev->name, temp);
/*
* We now have an open port. To allow for clean exit
* of the application, we first retrieve the port's
* current settings, and save these for later.
*/
if (bhtty_gstate(pp, &pp->odcb) < 0) {
(void)bhtty_close(pp);
if (get_state(dev, &dev->odcb) < 0) {
plat_serial_close(dev);
return(NULL);
}
memcpy(&pp->dcb, &pp->odcb, sizeof(DCB));
memcpy(&dev->dcb, &dev->odcb, sizeof(DCB));
/* Force the port to BINARY mode. */
bhtty_raw(pp, &pp->dcb);
plat_serial_raw(dev, &dev->dcb);
/* Set new state of this port. */
if (bhtty_sstate(pp, &pp->dcb) < 0) {
(void)bhtty_close(pp);
if (set_state(dev, &dev->dcb) < 0) {
plat_serial_close(dev);
return(NULL);
}
/* Just to make sure.. disable RTS/CTS mode. */
(void)bhtty_crtscts(pp, 0);
set_crtscts(dev, 0);
/* Set new timeout values. */
if (GetCommTimeouts(pp->handle, &to) == FALSE) {
pclog("%s: error %d while getting current TO\n",
pp->name, GetLastError());
(void)bhtty_close(pp);
if (GetCommTimeouts(dev->handle, &to) == FALSE) {
ERRLOG("%s: error %i while getting current TO\n",
dev->name, GetLastError());
plat_serial_close(dev);
return(NULL);
}
if (tmo < 0) {
/* No timeout, immediate return. */
to.ReadIntervalTimeout = MAXDWORD;
@@ -517,34 +518,36 @@ bhtty_open(char *port, int tmo)
to.ReadTotalTimeoutMultiplier = MAXDWORD;
to.ReadTotalTimeoutConstant = tmo;
}
if (SetCommTimeouts(pp->handle, &to) == FALSE) {
pclog("%s: error %d while setting TO\n", pp->name, GetLastError());
(void)bhtty_close(pp);
if (SetCommTimeouts(dev->handle, &to) == FALSE) {
ERRLOG("%s: error %i while setting TO\n", dev->name, GetLastError());
plat_serial_close(dev);
return(NULL);
}
/* Clear all errors and flush all buffers. */
if (bhtty_flush(pp) < 0) {
(void)bhtty_close(pp);
if (plat_serial_flush(dev) < 0) {
plat_serial_close(dev);
return(NULL);
}
return(pp);
return(dev);
}
/* Activate the I/O for this port. */
/* API: activate the I/O for this port. */
int
bhtty_active(BHTTY *pp, int flg)
plat_serial_active(void *arg, int flg)
{
serial_t *dev = (serial_t *)arg;
if (flg) {
pclog("%s: starting thread..\n", pp->name);
pp->tid = thread_create(bhtty_reader, pp);
INFO("%s: starting thread..\n", dev->name);
dev->tid = thread_create(reader_thread, dev);
} else {
if (pp->tid != NULL) {
pclog("%s: stopping thread..\n", pp->name);
thread_kill(pp->tid);
pp->tid = NULL;
if (dev->tid != NULL) {
INFO("%s: stopping thread..\n", dev->name);
thread_kill(dev->tid);
dev->tid = NULL;
}
}
@@ -552,25 +555,26 @@ bhtty_active(BHTTY *pp, int flg)
}
/* Try to write data to an open port. */
/* API: try to write data to an open port. */
int
bhtty_write(BHTTY *pp, unsigned char val)
plat_serial_write(void *arg, unsigned char val)
{
serial_t *dev = (serial_t *)arg;
DWORD n = 0;
pclog("%s: writing byte %02x\n", pp->name, val);
if (WriteFile(pp->handle, &val, 1, &n, &pp->wov) == FALSE) {
pclog(0,"%s: writing byte %02x\n", dev->name, val);
if (WriteFile(dev->handle, &val, 1, &n, &dev->wov) == FALSE) {
n = GetLastError();
if (n != ERROR_IO_PENDING) {
/* Not good, we got an error. */
pclog("%s: I/O error %d in write!\n", pp->name, n);
ERRLOG("%s: I/O error %i in write!\n", dev->name, n);
return(-1);
}
/* The write is pending, wait for it.. */
if (GetOverlappedResult(pp->handle, &pp->wov, &n, TRUE) == FALSE) {
if (GetOverlappedResult(dev->handle, &dev->wov, &n, TRUE) == FALSE) {
n = GetLastError();
pclog("%s: I/O error %d in write!\n", pp->name, n);
ERRLOG("%s: I/O error %i in write!\n", dev->name, n);
return(-1);
}
}
@@ -580,22 +584,24 @@ pclog("%s: writing byte %02x\n", pp->name, val);
/*
* Try to read data from an open port.
* API: try to read data from an open port.
*
* For now, we will use one byte per call. Eventually,
* we should go back to loading a buffer full of data,
* just to speed things up a bit. --FvK
*/
int
bhtty_read(BHTTY *pp, unsigned char *bufp, int max)
plat_serial_read(void *arg, unsigned char *bufp, int max)
{
if (pp->icnt == 0) return(0);
serial_t *dev = (serial_t *)arg;
if (dev->icnt == 0) return(0);
while (max-- > 0) {
*bufp++ = pp->buff[pp->itail++];
pclog("%s: dequeued byte %02x (%d)\n", pp->name, *(bufp-1), pp->icnt);
pp->itail &= (sizeof(pp->buff)-1);
if (--pp->icnt == 0) break;
*bufp++ = dev->buff[dev->itail++];
pclog(0,"%s: dequeued byte %02x (%i)\n", dev->name, *(bufp-1), dev->icnt);
dev->itail &= (sizeof(dev->buff)-1);
if (--dev->icnt == 0) break;
}
return(max);