summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video
diff options
context:
space:
mode:
author prime6809 <36767090+prime6809@users.noreply.github.com>2021-10-10 21:26:32 +0100
committer GitHub <noreply@github.com>2021-10-10 16:26:32 -0400
commita8ffd2235a167702cc9a06d0917d545e7ed14bee (patch)
treebfeeb7b9ed7a4a60d39cbae48c6950833ae2c0fd /src/mame/video
parentfc906d7a1783f93578cedd1c162015d6182d8e3b (diff)
RM Nimbus updates: (#8684)
* Updated mouse handling so it mostly works * Updated SASI/SCSI code so that formatting disks with HDFORM works for ST125N and ST225N. * Added documentation of the video code drawn from the Nimbus Service manual.
Diffstat (limited to 'src/mame/video')
-rw-r--r--src/mame/video/rmnimbus.cpp231
1 files changed, 188 insertions, 43 deletions
diff --git a/src/mame/video/rmnimbus.cpp b/src/mame/video/rmnimbus.cpp
index b779d31bd15..a4e6004c219 100644
--- a/src/mame/video/rmnimbus.cpp
+++ b/src/mame/video/rmnimbus.cpp
@@ -21,7 +21,13 @@
MB61H201 Fujitsu RML 12835 GCV, I have had to determine most of its
operation by disassembling the Nimbus bios and by writing experemental
code on the real machine.
+
+ 2021-09-29, P.Harvey-Smith.
+
+ I now have access to the service manual for the Nimbus, this documents to facilities provided
+ by the video chip, which will hopefully allow a much more accurate implementation.
*/
+
#include "emu.h"
#include "includes/rmnimbus.h"
@@ -30,6 +36,140 @@
#include <functional>
+/*
+ Acording to the service manual the Nimbus should be capable of the following modes :
+
+ 320 x 200 4bpp
+ 640 x 200 2bpp
+ 400 x 200 4bpp
+ 800 x 200 2bpp
+ 320 x 250 4bpp
+ 640 x 250 2bpp
+ 400 x 250 4bpp
+ 800 x 250 2bpp
+*/
+
+/*
+ From the service manual the registers are defined as follows :
+
+Ports 0x00-0x1E are the registers used to update the display RAM thus :
+
+Addr m_x m_y Update memory on write?
+0x00 nop nop no
+0x02 load nop no
+0x04 nop inc no
+0x06 load inc no
+0x08 nop nop no
+0x0A inc nop no
+0x0C nop load no
+0x0E inc load no
+0x10 nop nop yes
+0x12 load nop yes
+0x14 nop inc yes
+0x16 load inc yes
+0x18 nop nop yes
+0x1A inc nop yes
+0x1C nop load yes
+0x1E inc load yes
+
+0x20 scroll port, contains 8 bit scroll address
+
+0x22 Update mode control port (up_mode), controls how data is written to display ram.
+ see UPMODE_ constants below
+
+0x24h Intensity port, provides current logical intensities for update operations
+ bits 0..3 Foreground
+ bits 4..7 Background
+
+0x26 Display mode (m_mode) current display mode and border colour.
+ see MODE_ constants below
+
+For READ.
+Ports 0x28, 0x2A, 0x2C and 0x2E have different read and write functions :
+
+0x28 Timing / status, all bits active high
+ bit 0 line blank
+ bit 1 line display
+ bit 2 frame blank
+ bit 3 frame display
+
+0x2A X address status, returns current value of X counter (m_x)
+
+0x2C Y address status, returns current value of Y counter (m_y)
+
+For Write
+
+0x28, 0x2A, 0x2C, 0x2E Colour look up table :
+
+ Logic colour
+Port Bits Low res High Res
+0x28 0..3 0 0
+0x28 4..7 1 0
+0x28 8..11 2 0
+0x28 12..15 3 0
+
+0x2A 0..3 3 1
+0x2A 4..7 5 1
+0x2A 8..11 6 1
+0x2A 12..15 7 1
+
+0x2C 0..3 8 2
+0x2C 4..7 9 2
+0x2C 8..11 10 2
+0x2C 12..15 11 2
+
+0x2E 0..3 12 3
+0x2E 4..7 13 3
+0x2E 8..11 14 3
+0x2E 12..15 15 3
+
+
+*/
+
+// In following definitions ports are the WORD offset, the RM manual
+// lists them by the byte offset so they are 2* the value
+
+#define P_SCROLL 0x10
+#define P_UPDATE_MODE 0x11
+#define P_INTENSITY 0x12
+#define P_MODE 0x13
+#define P_STATUS 0x14
+#define P_X_COUNT 0x15
+#define P_Y_COUNT 0x16
+
+#define P_COLOUR03 0x14
+#define P_COLOUR47 0x15
+#define P_COLOUR8B 0x16
+#define P_COLOURCF 0x17
+
+// From the service manual, Reg022 update mode constants :
+// The first 8 are NON XOR writes
+#define UPMODE_40_TEXT 0x00 // 40 character text
+#define UPMODE_80_TEXT 0x01 // 80 character text
+#define UPMODE_LO_PIXEL 0x02 // Low res pixel
+#define UPMODE_HI_PIXEL 0x03 // Hi res pixel
+#define UPMODE_ANIMATION 0x04 // Animation (mask + data)
+#define UPMODE_SCROLL 0x05 // Scroll mode
+#define UPMODE_DIRECT 0x06 // Direct write to video ram
+#define UPMODE_ILLEGAL7 0x07
+
+// The second 8 are XOR writes
+#define UPMODE_40_TEXT_X 0x08
+#define UPMODE_80_TEXT_X 0x09
+#define UPMODE_LO_PIXEL_X 0x0A
+#define UPMODE_HI_PIXEL_X 0x0B
+#define UPMODE_ANIMATION_X 0x0C
+#define UPMODE_SCROLL_X 0x0D
+#define UPMODE_DIRECT_X 0x0E
+#define UPMODE_ILLEGALF 0x0F
+
+#define UP_XOR_MASK 0x08
+
+// port 026, display mode (m_mode)
+#define MODE_BORDER 0x0F // bits 0..3, Border colour number
+#define MODE_RESOLUTION 0x10 // bit 4, 0=low res (40 col), high = high res (80 col)
+#define MODE_WIDTH 0x20 // bit 5, 0=narrow, 1=wide
+#define MODE_HEIGHT 0x40 // bit 6, 0=625 lines, 1=562
#define WIDTH_MASK 0x07
@@ -38,8 +178,8 @@
#define SELECT_COL(x,c) (IS_80COL ? ((((x) & 1) ? ((c) << 2) : (c)) & 0xC) : (c))
#define FILL_WORD(c) (((c) << 12) | ((c) << 8) | ((c) << 4) | (c))
-#define IS_80COL (m_mode&0x10)
-#define IS_XOR (m_op&8)
+#define IS_80COL (m_mode & MODE_RESOLUTION)
+#define IS_XOR (m_upmode & UP_XOR_MASK)
#define DEBUG_TEXT 0x01
#define DEBUG_DB 0x02
@@ -66,27 +206,28 @@ uint16_t rmnimbus_state::nimbus_video_io_r(offs_t offset, uint16_t mem_mask)
result = read_pixel_data(++m_x, m_y);
break;
- case 0x10:
+ case P_SCROLL:
result = m_yline;
break;
- case 0x11:
- result = m_op;
+ case P_UPDATE_MODE:
+ result = m_upmode;
break;
- case 0x12:
+ case P_INTENSITY:
result = m_colours;
break;
- case 0x13:
+ case P_MODE:
result = m_mode;
break;
- case 0x14:
+ case P_STATUS:
result = m_screen->vpos() % 0xb; // TODO: verify
break;
- case 0x15:
+ case P_X_COUNT:
result = m_x;
break;
- case 0x16:
+ case P_Y_COUNT:
result = m_y;
break;
+
default:
logerror("nimbus: unknown video reg read %02x\n", offset);
break;
@@ -139,11 +280,11 @@ uint16_t rmnimbus_state::read_pixel_data(uint16_t x, uint16_t y)
uint16_t result=0;
if(DEBUG_SET(DEBUG_TEXT | DEBUG_PIXEL))
- logerror("read_pixel_data(x=%d, y=%d), reg022=%04X\n",x,y,m_op);
+ logerror("read_pixel_data(x=%d, y=%d), reg022=%04X\n",x,y,m_upmode);
if(IS_80COL)
{
- switch (m_op & WIDTH_MASK)
+ switch (m_upmode & WIDTH_MASK)
{
case 0x00 : break;
@@ -168,7 +309,7 @@ uint16_t rmnimbus_state::read_pixel_data(uint16_t x, uint16_t y)
}
else /* 40 Col */
{
- switch (m_op & WIDTH_MASK)
+ switch (m_upmode & WIDTH_MASK)
{
case 0x00 : break;
@@ -260,27 +401,27 @@ void rmnimbus_state::nimbus_video_io_w(offs_t offset, uint16_t data, uint16_t me
m_x++;
break;
- case 0x10:
+ case P_SCROLL:
m_yline = data;
return;
- case 0x11:
- m_op = data;
+ case P_UPDATE_MODE:
+ m_upmode = data;
return;
- case 0x12:
+ case P_INTENSITY:
m_colours = data;
return;
- case 0x13:
+ case P_MODE:
/*
bits 0..3 of reg026 contain the border colour.
bit 5 contains the 40/80 column (320/640 pixel) flag.
*/
m_mode = data;
return;
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- change_palette(offset - 0x14, data);
+ case P_COLOUR03:
+ case P_COLOUR47:
+ case P_COLOUR8B:
+ case P_COLOURCF:
+ change_palette(offset - P_COLOUR03, data);
return;
default:
@@ -382,84 +523,88 @@ void rmnimbus_state::move_pixel_line(uint16_t x, uint16_t y, uint8_t pixels)
void rmnimbus_state::write_pixel_data(uint16_t x, uint16_t y, uint16_t data)
{
if(DEBUG_SET(DEBUG_TEXT | DEBUG_PIXEL))
- logerror("write_pixel_data(x=%d, y=%d, data=%04X), reg022=%04X\n",x,y,data,m_op);
+ logerror("write_pixel_data(x=%d, y=%d, data=%04X), reg022=%04X\n",x,y,data,m_upmode);
if(IS_80COL)
{
- switch (m_op & WIDTH_MASK)
+ switch (m_upmode & WIDTH_MASK)
{
- case 0x00:
+ case UPMODE_40_TEXT:
write_pixel_line(x,y,data,16,1);
break;
- case 0x01:
+ case UPMODE_80_TEXT:
write_pixel_line(x,y,data,8,1);
break;
- case 0x02:
+ case UPMODE_LO_PIXEL:
write_pixel_line(x,y,data,8,1);
break;
- case 0x03:
+ case UPMODE_HI_PIXEL:
set_pixel(x,y,SELECT_COL(x, FG_COLOUR));
break;
- case 0x04:
+ case UPMODE_ANIMATION:
write_pixel_line(x,y,(((data & 0xFF00)>>8) & (data & 0xFF)) | (~((data & 0xFF00)>>8) & read_pixel_line(x,y,4,2)),4,2);
break;
- case 0x05:
+ case UPMODE_SCROLL:
move_pixel_line(x,y,16);
break;
- case 0x06:
+ case UPMODE_DIRECT:
write_pixel_line(x,y,data,8,2);
break;
- case 0x07:
+ case UPMODE_ILLEGAL7:
set_pixel(x,y,SELECT_COL(x, FG_COLOUR));
break;
}
}
else /* 40 Col */
{
- switch (m_op & WIDTH_MASK)
+ switch (m_upmode & WIDTH_MASK)
{
- case 0x00:
+ case UPMODE_40_TEXT:
write_pixel_line(x,y,data,8,1);
break;
- case 0x01:
+ case UPMODE_80_TEXT:
write_pixel_line(x,y,data,4,2);
break;
- case 0x02:
+ case UPMODE_LO_PIXEL:
set_pixel40(x,y,FG_COLOUR);
break;
- case 0x03:
+ case UPMODE_HI_PIXEL:
set_pixel(x,y,FG_COLOUR);
break;
- case 0x04:
+ case UPMODE_ANIMATION:
write_pixel_line(x,y,(((data & 0xFF00)>>8) & (data & 0xFF)) | (~((data & 0xFF00)>>8) & read_pixel_line(x,y,2,4)),2,4);
break;
- case 0x05:
+ case UPMODE_SCROLL:
move_pixel_line(x,y,16);
break;
- case 0x06:
+ case UPMODE_DIRECT:
write_pixel_line(x,y,data,4,4);
break;
- case 0x07:
+ case UPMODE_ILLEGAL7:
set_pixel(x,y,FG_COLOUR);
break;
}
}
}
+// Colours are encoded as follows :
+// Each nibble contains a colour encoded as igrb
+// so we shift through the specified colours and extract the bits, to set the palette.
+//
void rmnimbus_state::change_palette(uint8_t bank, uint16_t colours)
{
// loop over changing colours
@@ -507,7 +652,7 @@ void rmnimbus_state::video_reset()
m_mode = 0;
m_x = 0;
m_y = 0;
- m_op = 0;
+ m_upmode = 0;
m_yline = 0;
}