diff options
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 |
commit | a8ffd2235a167702cc9a06d0917d545e7ed14bee (patch) | |
tree | bfeeb7b9ed7a4a60d39cbae48c6950833ae2c0fd /src/mame/video | |
parent | fc906d7a1783f93578cedd1c162015d6182d8e3b (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.cpp | 231 |
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; } |