From 6b63feb6ac7d4c5f721bbdcefb8053f8e2ebbf70 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 14 Jul 2022 02:31:59 +0200 Subject: [PATCH] Preliminary code for UPI42 integration into 86Box. --- src/upi42.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 328 insertions(+), 4 deletions(-) diff --git a/src/upi42.c b/src/upi42.c index 77d580004..8b8e4b72e 100644 --- a/src/upi42.c +++ b/src/upi42.c @@ -30,6 +30,33 @@ printf(__VA_ARGS__); \ fflush(stdout); \ } +#else +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/timer.h> + + +#ifdef ENABLE_UPI42_LOG +int upi42_do_log = ENABLE_UPI42_LOG; + + +void +upi42_log(const char *fmt, ...) +{ + va_list ap; + + if (upi42_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define upi42_log(fmt, ...) +#endif #endif #define UPI42_REG(upi42, r, op) ((upi42->psw & 0x10) ? (upi42->ram[24 + ((r) &7)] op) : (upi42->ram[(r) &7] op)) @@ -68,6 +95,11 @@ typedef struct _upi42_ { flags : 1, dbf : 1, suspend : 1; /* UPI-42 flags */ int cycs; /* cycle counter */ + +#ifndef UPI42_STANDALONE + uint8_t ram_index; + uint16_t rom_index; +#endif } upi42_t; static inline void @@ -970,11 +1002,9 @@ upi42_reset(upi42_t *upi42) upi42->suspend = 0; /* 80C42 suspend flag */ } -void * -upi42_init(uint32_t type, uint8_t *rom) +void +upi42_do_init(upi32_t type, uint8_t *rom) { - /* Allocate state structure. */ - upi42_t *upi42 = (upi42_t *) malloc(sizeof(upi42_t)); memset(upi42, 0, sizeof(upi42_t)); upi42->rom = rom; @@ -994,6 +1024,18 @@ upi42_init(uint32_t type, uint8_t *rom) upi42->ops[0xe2] = NULL; /* SUSPEND */ } + memset(upi42_t->ports_in, 0xff, 0x08); + upi42_t->t0 = 1; + upi42_t->t1 = 1; +} + +void * +upi42_init(uint32_t type, uint8_t *rom) +{ + /* Allocate state structure. */ + upi42_t *upi42 = (upi42_t *) malloc(sizeof(upi42_t)); + upi42_do_init(type, rom); + return upi42; } @@ -1127,4 +1169,286 @@ skip_and_retry: return 0; } +#else +static void +upi42_write(uint16_t port, uint8_t val, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + uint32_t temp_type, uint8_t *temp_rom; + int i; + + switch (port) { + /* Write to data port. */ + case 0x0060: + case 0x0160: + upi42_dbb_write(0, val, upi42); + break; + + /* RAM Index. */ + case 0x0162: + upi42->ram_index = val & upi42->rammask; + break; + + /* RAM. */ + case 0x0163: + upi42->ram[upi42->ram_index & upi42->rammask] = val; + break; + + /* Write to command port. */ + case 0x0064: + case 0x0164: + upi42_cmd_write(0, val, upi42); + break; + + /* Input ports. */ + case 0x0180 ... 0x0187: + upi42->ports_in[addr & 0x0007] = val; + break; + + /* Output ports. */ + case 0x0188 ... 0x018f: + upi42->ports_out[addr & 0x0007] = val; + break; + + /* 4 = T0, 5 = T1. */ + case 0x0194: + upi42->t0 = (val >> 4) & 0x01; + upi42->t1 = (val >> 5) & 0x01; + break; + + /* Program counter. */ + case 0x0196: + upi42->pc = (upi42->pc & 0xff00) | val; + break; + case 0x0197: + upi42->pc = (upi42->pc & 0x00ff) | (val << 8); + break; + + /* Input data buffer. */ + case 0x019a: + upi42->dbb_in = val; + break; + + /* Output data buffer. */ + case 0x019b: + upi42->dbb_out = val; + break; + + /* ROM Index. */ + case 0x01a0: + upi42->rom_index = (upi42->rom_index & 0xff00) | val; + break; + case 0x01a1: + upi42->rom_index = (upi42->rom_index & 0x00ff) | (val << 8); + break; + + /* Hard reset. */ + case 0x01a2: + temp_type = upi42->type; + temp_rom = upi42->rom; + upi42_do_init(temp_type, temp_rom); + break; + + /* Soft reset. */ + case 0x01a3: + upi42_reset(upi42); + break; + + /* ROM. */ + case 0x01a4: + upi42->rom[upi42->rom_index & upi42->rommask] = val; + break; + case 0x01a5: + upi42->rom[(upi42->rom_index + 1) & upi42->rommask] = val; + break; + case 0x01a6: + upi42->rom[(upi42->rom_index + 2) & upi42->rommask] = val; + break; + case 0x01a7: + upi42->rom[(upi42->rom_index + 3) & upi42->rommask] = val; + break; + + /* Pause. */ + case 0x01a8: + break; + + /* Resume. */ + case 0x01a9: + break; + + /* Bus master ROM: 0 = direction (0 = to memory, 1 = from memory). */ + case 0x01aa: + if (val & 0x01) { + for (i = 0; i <= upi42->rommask; i += 4) + *(uint32_t *) &(upi42->rom[i]) = mem_readl_phys(upi42->ram_addr + i); + } else { + for (i = 0; i <= upi42->rommask; i += 4) + mem_writel_phys(upi42->ram_addr + i, *(uint32_t *) &(upi42->rom[i])); + } + upi42->bm_stat = (val & 0x01) | 0x02; + break; + } +} + + +static uint8_t +upi42_read(uint16_t port, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + /* Type. */ + case 0x015c: + ret = upi42->type & 0xff; + break; + case 0x015d: + ret = upi42->type >> 8; + break; + case 0x015e: + ret = upi42->type >> 16; + break; + case 0x015f: + ret = upi42->type >> 24; + break; + + /* Read from data port and reset OBF. */ + case 0x0060: + case 0x0160: + ret = upi42->dbb_out; + upi42->sts &= ~0x01; /* clear OBF */ + break; + + /* RAM Mask. */ + case 0x0161: + ret = upi42->rammask; + break; + + /* RAM Index. */ + case 0x0162: + ret = upi42->ram_index; + break; + + /* RAM. */ + case 0x0163: + ret = upi42->ram[upi42->ram_index & upi42->rammask]; + break; + + /* Read status. */ + case 0x0064: + case 0x0164: + ret = upi42->sts; + break; + + /* Input ports. */ + case 0x0180 ... 0x0187: + ret = upi42->ports_in[addr & 0x0007]; + break; + + /* Output ports. */ + case 0x0188 ... 0x018f: + ret = upi42->ports_out[addr & 0x0007]; + break; + + /* Accumulator. */ + case 0x0190: + ret = upi42->a; + break; + + /* Timer counter. */ + case 0x0191: + ret = upi42->t; + break; + + /* Program status word. */ + case 0x0192: + ret = upi42->psw; + break; + + /* 0-4 = Prescaler, 5 = TF, 6 = Skip Timer Inc, 7 = Run Timer. */ + case 0x0193: + ret = (upi42->prescaler & 0x1f) || ((upi42->tf & 0x01) << 5) || ((upi42->skip_timer_inc & 0x01) << 6) || ((upi42->run_timer & 0x01) << 7); + break; + + /* 0 = I, 1 = I Raise, 2 = TCNTI Raise, 3 = IRQ Mask, 4 = T0, 5 = T1, 6 = Flags, 7 = DBF. */ + case 0x0194: + ret = (upi42->i & 0x01) || ((upi42->i_raise & 0x01) << 1) || ((upi42->tcnti_raise & 0x01) << 2) || ((upi42->irq_mask & 0x01) << 3) || + ((upi42->t0 & 0x01) << 4) || ((upi42->t1 & 0x01) << 5) || ((upi42->flags & 0x01) << 6) || ((upi42->dbf & 0x01) << 7); + break; + + /* 0 = Suspend. */ + case 0x0195: + ret = (upi42->suspend & 0x01); + break; + + /* Program counter. */ + case 0x0196: + ret = upi42->pc & 0xff; + break; + case 0x0197: + ret = upi42->pc >> 8; + break; + + /* ROM Mask. */ + case 0x0198: + ret = upi42->rommask & 0xff; + break; + case 0x0199: + ret = upi42->rommask >> 8; + break; + + /* Input data buffer. */ + case 0x019a: + ret = upi42->dbb_in; + break; + + /* Output data buffer. */ + case 0x019b: + ret = upi42->dbb_out; + break; + + /* Cycle counter. */ + case 0x019c: + ret = upi42->cycs & 0xff; + break; + case 0x019d: + ret = upi42->cycs >> 8; + break; + case 0x019e: + ret = upi42->cycs >> 16; + break; + case 0x019f: + ret = upi42->cycs >> 24; + break; + + /* ROM Index. */ + case 0x01a0: + ret = upi42->rom_index & 0xff; + break; + case 0x01a1: + ret = upi42->rom_index >> 8; + break; + + /* ROM. */ + case 0x01a4: + ret = upi42->rom[upi42->rom_index & upi42->rommask]; + break; + case 0x01a5: + ret = upi42->rom[(upi42->rom_index + 1) & upi42->rommask]; + break; + case 0x01a6: + ret = upi42->rom[(upi42->rom_index + 2) & upi42->rommask]; + break; + case 0x01a7: + ret = upi42->rom[(upi42->rom_index + 3) & upi42->rommask]; + break; + + /* Bus master status: 0 = direction, 1 = finished. */ + case 0x01ab: + ret = upi42->bm_stat; + break; + } + + return ret; +} #endif