Previous 199869 Revisions Next

r23880 Sunday 23rd June, 2013 at 14:44:29 UTC by Fabio Priuli
(MESS) gameboy: converted the various LCD types (DMG, MGB, CGB...) to be devices. [Fabio Priuli]
[src/mess/drivers]gb.c
[src/mess/includes]gb.h
[src/mess/machine]gb.c
[src/mess/video]gb.c

trunk/src/mess/includes/gb.h
r23879r23880
4040
4141#define _NR_GB_VID_REGS     0x40
4242
43struct layer_struct {
44   UINT8  enabled;
45   UINT8  *bg_tiles;
46   UINT8  *bg_map;
47   UINT8  xindex;
48   UINT8  xshift;
49   UINT8  xstart;
50   UINT8  xend;
51   /* GBC specific */
52   UINT8  *gbc_map;
53   INT16  bgline;
54};
5543
56struct gb_lcd_t {
57   int window_lines_drawn;
5844
59   UINT8   gb_vid_regs[_NR_GB_VID_REGS];
60   UINT8   bg_zbuf[160];
6145
62   UINT16  cgb_bpal[32];   /* CGB current background palette table */
63   UINT16  cgb_spal[32];   /* CGB current sprite palette table */
64
65   UINT8   gb_bpal[4];     /* Background palette */
66   UINT8   gb_spal0[4];    /* Sprite 0 palette */
67   UINT8   gb_spal1[4];    /* Sprite 1 palette */
68
69   /* Things used to render current line */
70   int current_line;       /* Current line */
71   int cmp_line;           /* Compare line */
72   int sprCount;           /* Number of sprites on current line */
73   int sprite[10];         /* References to sprites to draw on current line */
74   int previous_line;      /* Previous line we've drawn in */
75   int start_x;            /* Pixel to start drawing from (inclusive) */
76   int end_x;              /* Pixel to end drawing (exclusive) */
77   int mode;               /* Keep track of internal STAT mode */
78   int state;              /* Current state of the video state machine */
79   int lcd_irq_line;
80   int triggering_line_irq;
81   int line_irq;
82   int triggering_mode_irq;
83   int mode_irq;
84   int delayed_line_irq;
85   int sprite_cycles;
86   int scrollx_adjust;
87   int oam_locked;
88   int vram_locked;
89   int pal_locked;
90   int hdma_enabled;
91   int hdma_possible;
92   struct layer_struct layer[2];
93   emu_timer *lcd_timer;
94   int gbc_mode;
95
96   UINT8   *gb_vram;     // Pointer to VRAM
97   UINT8   *gb_oam;      // Pointer to OAM memory
98   UINT8   gb_tile_no_mod;
99   UINT32  gb_chrgen_offs;     // GB Character generator
100   UINT32  gb_bgdtab_offs;     // GB Background character table
101   UINT32  gb_wndtab_offs;     // GB Window character table
102   UINT32  gbc_chrgen_offs;    // CGB Character generator
103   UINT32  gbc_bgdtab_offs;    // CGB Background character table
104   UINT32  gbc_wndtab_offs;    // CGB Window character table
105   int     gb_vram_bank;
106};
107
108
109
11046class gb_state : public driver_device
11147{
11248public:
r23879r23880
12056      m_inputs(*this, "INPUTS"),
12157      m_ram(*this, RAM_TAG) { }
12258
123   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
124
125   UINT16 m_sgb_pal_data[4096];
126   UINT8 m_sgb_pal_map[20][18];
127   UINT16 m_sgb_pal[128];
128   UINT8 *m_sgb_tile_data;
129   UINT8 m_sgb_tile_map[2048];
130   UINT8 m_sgb_window_mask;
13159   //gb_state driver_data;
13260   UINT8       m_gb_io[0x10];
13361
r23879r23880
14371   emu_timer   *m_gb_serial_timer;
14472
14573   /* SGB variables */
146   UINT8       m_sgb_atf_data[4050];       /* (SGB) Attributes files */
14774   INT8 m_sgb_packets;
14875   UINT8 m_sgb_bitcount;
14976   UINT8 m_sgb_bytecount;
r23879r23880
15279   UINT8 m_sgb_controller_no;
15380   UINT8 m_sgb_controller_mode;
15481   UINT8 m_sgb_data[0x100];
155   UINT32 m_sgb_atf;
15682
15783   /* CGB variables */
15884   UINT8       *m_gbc_rammap[8];           /* (CGB) Addresses of internal RAM banks */
15985   UINT8       m_gbc_rambank;          /* (CGB) Current CGB RAM bank */
16086
161
162   gb_lcd_t m_lcd;
163   void (gb_state::*update_scanline) ();
16487   int m_bios_disable;
16588
166   bitmap_ind16 m_bitmap;
16789   DECLARE_WRITE8_MEMBER(gb_io_w);
16890   DECLARE_WRITE8_MEMBER(gb_io2_w);
16991   DECLARE_WRITE8_MEMBER(sgb_io_w);
r23879r23880
17294   DECLARE_READ8_MEMBER(gb_io_r);
17395   DECLARE_WRITE8_MEMBER(gbc_io2_w);
17496   DECLARE_READ8_MEMBER(gbc_io2_r);
175   DECLARE_READ8_MEMBER(gb_video_r);
176   DECLARE_READ8_MEMBER(gb_vram_r);
177   DECLARE_WRITE8_MEMBER(gb_vram_w);
178   DECLARE_READ8_MEMBER(gb_oam_r);
179   DECLARE_WRITE8_MEMBER(gb_oam_w);
180   DECLARE_WRITE8_MEMBER(gb_video_w);
181   DECLARE_READ8_MEMBER(gbc_video_r);
182   DECLARE_WRITE8_MEMBER(gbc_video_w);
18397   DECLARE_MACHINE_START(gb);
18498   DECLARE_MACHINE_RESET(gb);
18599   DECLARE_PALETTE_INIT(gb);
r23879r23880
194108   DECLARE_PALETTE_INIT(gbc);
195109   INTERRUPT_GEN_MEMBER(gb_scanline_interrupt);
196110   TIMER_CALLBACK_MEMBER(gb_serial_timer_proc);
197   TIMER_CALLBACK_MEMBER(gb_video_init_vbl);
198   TIMER_CALLBACK_MEMBER(gb_lcd_timer_proc);
199   TIMER_CALLBACK_MEMBER(gbc_lcd_timer_proc);
200111   DECLARE_WRITE8_MEMBER(gb_timer_callback);
201112
202113   DECLARE_READ8_MEMBER(gb_cart_r);
r23879r23880
220131   void gb_timer_check_irq();
221132   void gb_init();
222133   void gb_init_regs();
223   void gb_select_sprites();
224   void gb_update_sprites();
225   void gb_update_scanline();
226   void sgb_update_sprites();
227   void sgb_refresh_border();
228   void sgb_update_scanline();
229   void cgb_update_sprites();
230   void cgb_update_scanline();
231134   void gb_video_reset(int mode);
232135   void gb_video_start(int mode);
233   void gbc_hdma(UINT16 length);
234   void gb_increment_scanline();
235   void gb_lcd_switch_on();
236   inline void gb_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
237136
238137   void save_gb_base();
239   void save_gb_video();
240138   void save_gbc_only();
241139   void save_sgb_only();
242   void gb_videoptr_restore();
243   void gbc_videoptr_restore();
244140};
245141
246142
r23879r23880
288184};
289185
290186
187struct layer_struct {
188   UINT8  enabled;
189   UINT8  *bg_tiles;
190   UINT8  *bg_map;
191   UINT8  xindex;
192   UINT8  xshift;
193   UINT8  xstart;
194   UINT8  xend;
195   /* GBC specific */
196   UINT8  *gbc_map;
197   INT16  bgline;
198};
199
200
201class gb_lcd_device : public device_t
202{
203public:
204   gb_lcd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
205   gb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
206
207   
208   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
209
210   DECLARE_READ8_MEMBER(vram_r);
211   DECLARE_WRITE8_MEMBER(vram_w);
212   DECLARE_READ8_MEMBER(oam_r);
213   DECLARE_WRITE8_MEMBER(oam_w);
214   virtual DECLARE_READ8_MEMBER(video_r);
215   virtual DECLARE_WRITE8_MEMBER(video_w);
216
217   // FIXME: remove it when proper sgb support is added
218   void set_sgb_hack(bool val) { m_sgb_border_hack = val ? 1 : 0; }
219   
220protected:
221   inline void plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
222   
223   void select_sprites();
224   virtual void update_sprites();
225   virtual void update_scanline();
226
227   // device-level overrides
228   virtual void device_start();
229   virtual void device_reset();
230   void common_start();
231   void common_reset();
232
233   // pointer to the main system
234   cpu_device *m_maincpu;
235   screen_device *m_screen;
236   
237   // state variables
238   bitmap_ind16 m_bitmap;
239
240   UINT8 m_sgb_atf_data[4050];       /* (SGB) Attributes files */
241   UINT32 m_sgb_atf;
242   UINT16 m_sgb_pal_data[4096];
243   UINT8 m_sgb_pal_map[20][18];
244   UINT16 m_sgb_pal[128];
245   UINT8 *m_sgb_tile_data;
246   UINT8 m_sgb_tile_map[2048];
247   UINT8 m_sgb_window_mask;
248   
249   // this is temporarily needed for a bunch of games which draw the border differently...
250   int m_sgb_border_hack;
251   
252   int m_window_lines_drawn;
253   
254   UINT8   m_vid_regs[_NR_GB_VID_REGS];
255   UINT8   m_bg_zbuf[160];
256   
257   UINT16  m_cgb_bpal[32];   /* CGB current background palette table */
258   UINT16  m_cgb_spal[32];   /* CGB current sprite palette table */
259   
260   UINT8   m_gb_bpal[4];     /* Background palette */
261   UINT8   m_gb_spal0[4];    /* Sprite 0 palette */
262   UINT8   m_gb_spal1[4];    /* Sprite 1 palette */
263   
264   /* Things used to render current line */
265   int m_current_line;       /* Current line */
266   int m_cmp_line;           /* Compare line */
267   int m_sprCount;           /* Number of sprites on current line */
268   int m_sprite[10];         /* References to sprites to draw on current line */
269   int m_previous_line;      /* Previous line we've drawn in */
270   int m_start_x;            /* Pixel to start drawing from (inclusive) */
271   int m_end_x;              /* Pixel to end drawing (exclusive) */
272   int m_mode;               /* Keep track of internal STAT mode */
273   int m_state;              /* Current state of the video state machine */
274   int m_lcd_irq_line;
275   int m_triggering_line_irq;
276   int m_line_irq;
277   int m_triggering_mode_irq;
278   int m_mode_irq;
279   int m_delayed_line_irq;
280   int m_sprite_cycles;
281   int m_scrollx_adjust;
282   int m_oam_locked;
283   int m_vram_locked;
284   int m_pal_locked;
285   int m_hdma_enabled;
286   int m_hdma_possible;
287   struct layer_struct m_layer[2];
288   emu_timer *m_lcd_timer;
289   int m_gbc_mode;
290   
291   UINT8   *m_vram;     // Pointer to VRAM
292   UINT8   *m_oam;      // Pointer to OAM memory
293   UINT8   m_gb_tile_no_mod;
294   UINT32  m_gb_chrgen_offs;     // GB Character generator
295   UINT32  m_gb_bgdtab_offs;     // GB Background character table
296   UINT32  m_gb_wndtab_offs;     // GB Window character table
297   UINT32  m_gbc_chrgen_offs;    // CGB Character generator
298   UINT32  m_gbc_bgdtab_offs;    // CGB Background character table
299   UINT32  m_gbc_wndtab_offs;    // CGB Window character table
300   int     m_vram_bank;
301
302   TIMER_CALLBACK_MEMBER(video_init_vbl);
303   virtual TIMER_CALLBACK_MEMBER(lcd_timer_proc);
304   virtual void videoptr_restore();
305   void save_gb_video();
306   void increment_scanline();
307   void lcd_switch_on();
308};
309
310
311class mgb_lcd_device : public gb_lcd_device
312{
313public:
314   mgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
315
316protected:
317   
318   // device-level overrides
319   virtual void device_start();
320   virtual void device_reset();
321};
322
323
324class sgb_lcd_device : public gb_lcd_device
325{
326public:
327   sgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
328   
329   void sgb_io_write_pal(int offs, UINT8 *data);
330
331protected:
332   
333   // device-level overrides
334   virtual void device_start();
335   virtual void device_reset();
336   
337   virtual void update_sprites();
338   virtual void update_scanline();
339   void refresh_border();
340};
341
342
343class cgb_lcd_device : public gb_lcd_device
344{
345public:
346   cgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
347   
348   virtual DECLARE_READ8_MEMBER(video_r);
349   virtual DECLARE_WRITE8_MEMBER(video_w);
350
351protected:
352   
353   // device-level overrides
354   virtual void device_start();
355   virtual void device_reset();
356   
357   virtual void update_sprites();
358   virtual void update_scanline();
359
360   virtual TIMER_CALLBACK_MEMBER(lcd_timer_proc);
361   virtual void videoptr_restore();
362   void hdma_trans(UINT16 length);
363};
364
365
366extern const device_type GB_LCD_DMG;
367extern const device_type GB_LCD_MGB;
368extern const device_type GB_LCD_SGB;
369extern const device_type GB_LCD_CGB;
370
371
372#define MCFG_GB_LCD_DMG_ADD(_tag ) \
373      MCFG_DEVICE_ADD( _tag, GB_LCD_DMG, 0 )
374
375#define MCFG_GB_LCD_MGB_ADD(_tag ) \
376      MCFG_DEVICE_ADD( _tag, GB_LCD_MGB, 0 )
377
378#define MCFG_GB_LCD_SGB_ADD(_tag ) \
379      MCFG_DEVICE_ADD( _tag, GB_LCD_SGB, 0 )
380
381#define MCFG_GB_LCD_CGB_ADD(_tag ) \
382      MCFG_DEVICE_ADD( _tag, GB_LCD_CGB, 0 )
383
384
291385#endif /* GB_H_ */
trunk/src/mess/video/gb.c
r23879r23880
1818#include "cpu/lr35902/lr35902.h"
1919#include "includes/gb.h"
2020
21#define LCDCONT     m_lcd.gb_vid_regs[0x00]  /* LCD control register                       */
22#define LCDSTAT     m_lcd.gb_vid_regs[0x01]  /* LCD status register                        */
23#define SCROLLY     m_lcd.gb_vid_regs[0x02]  /* Starting Y position of the background      */
24#define SCROLLX     m_lcd.gb_vid_regs[0x03]  /* Starting X position of the background      */
25#define CURLINE     m_lcd.gb_vid_regs[0x04]  /* Current screen line being scanned          */
26#define CMPLINE     m_lcd.gb_vid_regs[0x05]  /* Gen. int. when scan reaches this line      */
27#define BGRDPAL     m_lcd.gb_vid_regs[0x07]  /* Background palette                         */
28#define SPR0PAL     m_lcd.gb_vid_regs[0x08]  /* Sprite palette #0                          */
29#define SPR1PAL     m_lcd.gb_vid_regs[0x09]  /* Sprite palette #1                          */
30#define WNDPOSY     m_lcd.gb_vid_regs[0x0A]  /* Window Y position                          */
31#define WNDPOSX     m_lcd.gb_vid_regs[0x0B]  /* Window X position                          */
32#define KEY1        m_lcd.gb_vid_regs[0x0D]  /* Prepare speed switch                       */
33#define HDMA1       m_lcd.gb_vid_regs[0x11]  /* HDMA source high byte                      */
34#define HDMA2       m_lcd.gb_vid_regs[0x12]  /* HDMA source low byte                       */
35#define HDMA3       m_lcd.gb_vid_regs[0x13]  /* HDMA destination high byte                 */
36#define HDMA4       m_lcd.gb_vid_regs[0x14]  /* HDMA destination low byte                  */
37#define HDMA5       m_lcd.gb_vid_regs[0x15]  /* HDMA length/mode/start                     */
38#define GBCBCPS     m_lcd.gb_vid_regs[0x28]  /* Backgound palette spec                     */
39#define GBCBCPD     m_lcd.gb_vid_regs[0x29]  /* Backgound palette data                     */
40#define GBCOCPS     m_lcd.gb_vid_regs[0x2A]  /* Object palette spec                        */
41#define GBCOCPD     m_lcd.gb_vid_regs[0x2B]  /* Object palette data                        */
21#define LCDCONT     m_vid_regs[0x00]  /* LCD control register                       */
22#define LCDSTAT     m_vid_regs[0x01]  /* LCD status register                        */
23#define SCROLLY     m_vid_regs[0x02]  /* Starting Y position of the background      */
24#define SCROLLX     m_vid_regs[0x03]  /* Starting X position of the background      */
25#define CURLINE     m_vid_regs[0x04]  /* Current screen line being scanned          */
26#define CMPLINE     m_vid_regs[0x05]  /* Gen. int. when scan reaches this line      */
27#define BGRDPAL     m_vid_regs[0x07]  /* Background palette                         */
28#define SPR0PAL     m_vid_regs[0x08]  /* Sprite palette #0                          */
29#define SPR1PAL     m_vid_regs[0x09]  /* Sprite palette #1                          */
30#define WNDPOSY     m_vid_regs[0x0A]  /* Window Y position                          */
31#define WNDPOSX     m_vid_regs[0x0B]  /* Window X position                          */
32#define KEY1        m_vid_regs[0x0D]  /* Prepare speed switch                       */
33#define HDMA1       m_vid_regs[0x11]  /* HDMA source high byte                      */
34#define HDMA2       m_vid_regs[0x12]  /* HDMA source low byte                       */
35#define HDMA3       m_vid_regs[0x13]  /* HDMA destination high byte                 */
36#define HDMA4       m_vid_regs[0x14]  /* HDMA destination low byte                  */
37#define HDMA5       m_vid_regs[0x15]  /* HDMA length/mode/start                     */
38#define GBCBCPS     m_vid_regs[0x28]  /* Backgound palette spec                     */
39#define GBCBCPD     m_vid_regs[0x29]  /* Backgound palette data                     */
40#define GBCOCPS     m_vid_regs[0x2A]  /* Object palette spec                        */
41#define GBCOCPD     m_vid_regs[0x2B]  /* Object palette data                        */
4242
4343enum {
4444   UNLOCKED=0,
r23879r23880
4646};
4747
4848
49enum {
50   GB_LCD_STATE_LYXX_M3=1,
51   GB_LCD_STATE_LYXX_PRE_M0,
52   GB_LCD_STATE_LYXX_M0,
53   GB_LCD_STATE_LYXX_M0_SCX3,
54   GB_LCD_STATE_LYXX_M0_GBC_PAL,
55   GB_LCD_STATE_LYXX_M0_PRE_INC,
56   GB_LCD_STATE_LYXX_M0_INC,
57   GB_LCD_STATE_LY00_M2,
58   GB_LCD_STATE_LYXX_M2,
59   GB_LCD_STATE_LY9X_M1,
60   GB_LCD_STATE_LY9X_M1_INC,
61   GB_LCD_STATE_LY00_M1,
62   GB_LCD_STATE_LY00_M1_1,
63   GB_LCD_STATE_LY00_M1_2,
64   GB_LCD_STATE_LY00_M0
65};
66
67
4968static const unsigned char palette[] =
5069{
5170/* Simple black and white palette */
r23879r23880
7291};
7392
7493/* Initialise the palettes */
75PALETTE_INIT_MEMBER(gb_state,gb)
94PALETTE_INIT_MEMBER(gb_state, gb)
7695{
77   int ii;
78   for( ii = 0; ii < 4; ii++)
96   for (int i = 0; i < 4; i++)
97      palette_set_color_rgb(machine(), i, palette[i * 3 + 0], palette[i * 3 + 1], palette[i * 3 + 2]);
98}
99
100PALETTE_INIT_MEMBER(gb_state, gbp)
101{
102   for (int i = 0; i < 4; i++)
103      palette_set_color_rgb(machine(), i, palette[(i + 4) * 3 + 0], palette[(i + 4) * 3 + 1], palette[(i + 4) * 3 + 2]);
104}
105
106PALETTE_INIT_MEMBER(gb_state, sgb)
107{
108   int r, g, b;
109   
110   for (int i = 0; i < 32768; i++)
79111   {
80      palette_set_color_rgb(machine(), ii, palette[ii*3+0], palette[ii*3+1], palette[ii*3+2]);
112      r = (i & 0x1F) << 3;
113      g = ((i >> 5) & 0x1F) << 3;
114      b = ((i >> 10) & 0x1F) << 3;
115      palette_set_color_rgb(machine(), i, r, g, b);
81116   }
82117}
83118
84PALETTE_INIT_MEMBER(gb_state,gbp)
119PALETTE_INIT_MEMBER(gb_state, gbc)
85120{
86   int ii;
87   for( ii = 0; ii < 4; ii++)
121   int r, g, b;
122
123   for (int i = 0; i < 32768; i++)
88124   {
89      palette_set_color_rgb(machine(), ii, palette[(ii + 4)*3+0], palette[(ii + 4)*3+1], palette[(ii + 4)*3+2]);
125      r = (i & 0x1F) << 3;
126      g = ((i >> 5) & 0x1F) << 3;
127      b = ((i >> 10) & 0x1F) << 3;
128      palette_set_color_rgb(machine(), i, r, g, b);
90129   }
91130}
92131
93PALETTE_INIT_MEMBER(gb_state,sgb)
132PALETTE_INIT_MEMBER(megaduck_state, megaduck)
94133{
95   int ii, r, g, b;
134   for (int i = 0; i < 4; i++)
135      palette_set_color_rgb(machine(), i, palette_megaduck[i * 3 + 0], palette_megaduck[i * 3 + 1], palette_megaduck[i * 3 + 2]);
136}
96137
97   for( ii = 0; ii < 32768; ii++ )
138
139/* OAM contents on power up.
140 
141 The OAM area seems contain some kind of unit fingerprint. On each boot
142 the data is almost always the same. Some random bits are flipped between
143 different boots. It is currently unknown how much these fingerprints
144 differ between different units.
145 
146 OAM fingerprints taken from Wilbert Pol's own unit.
147 */
148
149static const UINT8 dmg_oam_fingerprint[0x100] = {
150   0xD8, 0xE6, 0xB3, 0x89, 0xEC, 0xDE, 0x11, 0x62, 0x0B, 0x7E, 0x48, 0x9E, 0xB9, 0x6E, 0x26, 0xC9,
151   0x36, 0xF4, 0x7D, 0xE4, 0xD9, 0xCE, 0xFA, 0x5E, 0xA3, 0x77, 0x60, 0xFC, 0x1C, 0x64, 0x8B, 0xAC,
152   0xB6, 0x74, 0x3F, 0x9A, 0x0E, 0xFE, 0xEA, 0xA9, 0x40, 0x3A, 0x7A, 0xB6, 0xF2, 0xED, 0xA8, 0x3E,
153   0xAF, 0x2C, 0xD2, 0xF2, 0x01, 0xE0, 0x5B, 0x3A, 0x53, 0x6A, 0x1C, 0x6C, 0x20, 0xD9, 0x22, 0xB4,
154   0x8C, 0x38, 0x71, 0x69, 0x3E, 0x93, 0xA3, 0x22, 0xCE, 0x76, 0x24, 0xE7, 0x1A, 0x14, 0x6B, 0xB1,
155   0xF9, 0x3D, 0xBF, 0x3D, 0x74, 0x64, 0xCB, 0xF5, 0xDC, 0x9A, 0x53, 0xC6, 0x0E, 0x78, 0x34, 0xCB,
156   0x42, 0xB3, 0xFF, 0x07, 0x73, 0xAE, 0x6C, 0xA2, 0x6F, 0x6A, 0xA4, 0x66, 0x0A, 0x8C, 0x40, 0xB3,
157   0x9A, 0x3D, 0x39, 0x78, 0xAB, 0x29, 0xE7, 0xC5, 0x7A, 0xDD, 0x51, 0x95, 0x2B, 0xE4, 0x1B, 0xF6,
158   0x31, 0x16, 0x34, 0xFE, 0x11, 0xF2, 0x5E, 0x11, 0xF3, 0x95, 0x66, 0xB9, 0x37, 0xC2, 0xAD, 0x6D,
159   0x1D, 0xA7, 0x79, 0x06, 0xD7, 0xE5, 0x8F, 0xFA, 0x9C, 0x02, 0x0C, 0x31, 0x8B, 0x17, 0x2E, 0x31,
160   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
166};
167
168static const UINT8 mgb_oam_fingerprint[0x100] = {
169   0xB9, 0xE9, 0x0D, 0x69, 0xBB, 0x7F, 0x00, 0x80, 0xE9, 0x7B, 0x79, 0xA2, 0xFD, 0xCF, 0xD8, 0x0A,
170   0x87, 0xEF, 0x44, 0x11, 0xFE, 0x37, 0x10, 0x21, 0xFA, 0xFF, 0x00, 0x17, 0xF6, 0x4F, 0x83, 0x03,
171   0x3A, 0xF4, 0x00, 0x24, 0xBB, 0xAE, 0x05, 0x01, 0xFF, 0xF7, 0x12, 0x48, 0xA7, 0x5E, 0xF6, 0x28,
172   0x5B, 0xFF, 0x2E, 0x10, 0xFF, 0xB9, 0x50, 0xC8, 0xAF, 0x77, 0x2C, 0x1A, 0x62, 0xD7, 0x81, 0xC2,
173   0xFD, 0x5F, 0xA0, 0x94, 0xAF, 0xFF, 0x51, 0x20, 0x36, 0x76, 0x50, 0x0A, 0xFD, 0xF6, 0x20, 0x00,
174   0xFE, 0xF7, 0xA0, 0x68, 0xFF, 0xFC, 0x29, 0x51, 0xA3, 0xFA, 0x06, 0xC4, 0x94, 0xFF, 0x39, 0x0A,
175   0xFF, 0x6C, 0x20, 0x20, 0xF1, 0xAD, 0x0C, 0x81, 0x56, 0xFB, 0x03, 0x82, 0xFF, 0xFF, 0x08, 0x58,
176   0x96, 0x7E, 0x01, 0x4D, 0xFF, 0xE4, 0x82, 0xE3, 0x3D, 0xBB, 0x54, 0x00, 0x3D, 0xF3, 0x04, 0x21,
177   0xB7, 0x39, 0xCC, 0x10, 0xF9, 0x5B, 0x80, 0x50, 0x3F, 0x6A, 0x1C, 0x21, 0x1F, 0xFA, 0xA8, 0x52,
178   0x5F, 0xB3, 0x44, 0xA1, 0x96, 0x1E, 0x00, 0x27, 0x63, 0x77, 0x30, 0x54, 0x37, 0x6F, 0x60, 0x22,
179   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
185};
186
187static const UINT8 cgb_oam_fingerprint[0x100] = {
188   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198   0x74, 0xFF, 0x09, 0x00, 0x9D, 0x61, 0xA8, 0x28, 0x36, 0x1E, 0x58, 0xAA, 0x75, 0x74, 0xA1, 0x42,
199   0x05, 0x96, 0x40, 0x09, 0x41, 0x02, 0x60, 0x00, 0x1F, 0x11, 0x22, 0xBC, 0x31, 0x52, 0x22, 0x54,
200   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
201   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
202   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
203   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04
204};
205
206/*
207 For an AGS in CGB mode this data is: */
208#if 0
209static const UINT8 abs_oam_fingerprint[0x100] = {
210   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220   0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
221   0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
222   0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
223   0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
224   0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
225   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
226};
227#endif
228
229
230const device_type GB_LCD_DMG = &device_creator<gb_lcd_device>;
231const device_type GB_LCD_MGB = &device_creator<mgb_lcd_device>;
232const device_type GB_LCD_SGB = &device_creator<sgb_lcd_device>;
233const device_type GB_LCD_CGB = &device_creator<cgb_lcd_device>;
234
235
236
237gb_lcd_device::gb_lcd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
238            : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
239               m_sgb_border_hack(0)
240{
241}
242
243gb_lcd_device::gb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
244            : device_t(mconfig, GB_LCD_DMG, "DMG LCD", tag, owner, clock, "dmg_lcd", __FILE__),
245               m_sgb_border_hack(0)
246{
247}
248
249mgb_lcd_device::mgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
250            : gb_lcd_device(mconfig, GB_LCD_MGB, "MGB LCD", tag, owner, clock, "mgb_lcd", __FILE__)
251{
252}
253
254sgb_lcd_device::sgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
255            : gb_lcd_device(mconfig, GB_LCD_SGB, "SGB LCD", tag, owner, clock, "sgb_lcd", __FILE__)
256{
257}
258
259cgb_lcd_device::cgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
260            : gb_lcd_device(mconfig, GB_LCD_CGB, "CGB LCD", tag, owner, clock, "cgb_lcd", __FILE__)
261{
262}
263
264
265//-------------------------------------------------
266//  device_start - device-specific startup
267//-------------------------------------------------
268
269void gb_lcd_device::common_start()
270{
271   machine().primary_screen->register_screen_bitmap(m_bitmap);
272   m_oam = auto_alloc_array_clear(machine(), UINT8, 0x100);
273   
274   m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_lcd_device::lcd_timer_proc),this));
275   machine().save().register_postload(save_prepost_delegate(FUNC(gb_lcd_device::videoptr_restore), this));
276
277   m_maincpu = machine().device<cpu_device>("maincpu");
278   m_screen = machine().device<screen_device>("screen");
279
280   save_pointer(NAME(m_oam), 0x100);
281   save_item(NAME(m_window_lines_drawn));
282   save_item(NAME(m_vid_regs));
283   save_item(NAME(m_bg_zbuf));
284   
285   save_item(NAME(m_cgb_bpal));
286   save_item(NAME(m_cgb_spal));
287   
288   save_item(NAME(m_gb_bpal));
289   save_item(NAME(m_gb_spal0));
290   save_item(NAME(m_gb_spal1));
291   
292   save_item(NAME(m_current_line));
293   save_item(NAME(m_cmp_line));
294   save_item(NAME(m_sprCount));
295   save_item(NAME(m_sprite));
296   save_item(NAME(m_previous_line));
297   save_item(NAME(m_start_x));
298   save_item(NAME(m_end_x));
299   save_item(NAME(m_mode));
300   save_item(NAME(m_state));
301   save_item(NAME(m_lcd_irq_line));
302   save_item(NAME(m_triggering_line_irq));
303   save_item(NAME(m_line_irq));
304   save_item(NAME(m_triggering_mode_irq));
305   save_item(NAME(m_mode_irq));
306   save_item(NAME(m_delayed_line_irq));
307   save_item(NAME(m_sprite_cycles));
308   save_item(NAME(m_scrollx_adjust));
309   save_item(NAME(m_oam_locked));
310   save_item(NAME(m_vram_locked));
311   save_item(NAME(m_pal_locked));
312   save_item(NAME(m_hdma_enabled));
313   save_item(NAME(m_hdma_possible));
314   save_item(NAME(m_gbc_mode));
315   save_item(NAME(m_gb_tile_no_mod));
316   save_item(NAME(m_vram_bank));
317   
318   save_item(NAME(m_gb_chrgen_offs));
319   save_item(NAME(m_gb_bgdtab_offs));
320   save_item(NAME(m_gb_wndtab_offs));
321   save_item(NAME(m_gbc_chrgen_offs));
322   save_item(NAME(m_gbc_bgdtab_offs));
323   save_item(NAME(m_gbc_wndtab_offs));
324   
325   save_item(NAME(m_layer[0].enabled));
326   save_item(NAME(m_layer[0].xindex));
327   save_item(NAME(m_layer[0].xshift));
328   save_item(NAME(m_layer[0].xstart));
329   save_item(NAME(m_layer[0].xend));
330   save_item(NAME(m_layer[0].bgline));
331   save_item(NAME(m_layer[1].enabled));
332   save_item(NAME(m_layer[1].xindex));
333   save_item(NAME(m_layer[1].xshift));
334   save_item(NAME(m_layer[1].xstart));
335   save_item(NAME(m_layer[1].xend));
336   save_item(NAME(m_layer[1].bgline));
337}
338
339
340void gb_lcd_device::videoptr_restore()
341{
342   m_layer[0].bg_map = m_vram + m_gb_bgdtab_offs;
343   m_layer[0].bg_tiles = m_vram + m_gb_chrgen_offs;
344   m_layer[1].bg_map = m_vram + m_gb_wndtab_offs;
345   m_layer[1].bg_tiles = m_vram + m_gb_chrgen_offs;
346}
347
348void cgb_lcd_device::videoptr_restore()
349{
350   m_layer[0].bg_map = m_vram + m_gb_bgdtab_offs;
351   m_layer[0].gbc_map = m_vram + m_gbc_bgdtab_offs;
352   m_layer[1].bg_map = m_vram + m_gb_wndtab_offs;
353   m_layer[1].gbc_map = m_vram + m_gbc_wndtab_offs;
354}
355
356
357void gb_lcd_device::device_start()
358{
359   common_start();
360
361   m_vram = auto_alloc_array_clear(machine(), UINT8, 0x2000);
362   save_pointer(NAME(m_vram), 0x2000);
363   
364   memcpy(m_oam, dmg_oam_fingerprint, 0x100);
365}
366
367void mgb_lcd_device::device_start()
368{
369   common_start();
370   
371   m_vram = auto_alloc_array_clear(machine(), UINT8, 0x2000);
372   save_pointer(NAME(m_vram), 0x2000);
373
374   memcpy(m_oam, mgb_oam_fingerprint, 0x100);
375
376   /* Initialize part of VRAM. This code must be deleted when we have added the bios dump */
377   for (int i = 1; i < 0x0d; i++)
98378   {
99      r = (ii & 0x1F) << 3;
100      g = ((ii >> 5) & 0x1F) << 3;
101      b = ((ii >> 10) & 0x1F) << 3;
102      palette_set_color_rgb(machine(),  ii, r, g, b );
379      m_vram[0x1903 + i] = i;
380      m_vram[0x1923 + i] = i + 0x0C;
103381   }
382   m_vram[0x1910] = 0x19;
383}
104384
385void sgb_lcd_device::device_start()
386{
387   common_start();
388   
389   m_vram = auto_alloc_array_clear(machine(), UINT8, 0x2000);
390   save_pointer(NAME(m_vram), 0x2000);
391
392   m_sgb_tile_data = auto_alloc_array_clear(machine(), UINT8, 0x2000);
393   save_pointer(NAME(m_sgb_tile_data), 0x2000);
394   
105395   /* Some default colours for non-SGB games */
106396   m_sgb_pal[0] = 32767;
107397   m_sgb_pal[1] = 21140;
108398   m_sgb_pal[2] = 10570;
109399   m_sgb_pal[3] = 0;
110400   /* The rest of the colortable can be black */
111   for( ii = 4; ii < 8*16; ii++ )
112      m_sgb_pal[ii] = 0;
401   for (int i = 4; i < 8 * 16; i++)
402      m_sgb_pal[i] = 0;
403
404   save_item(NAME(m_sgb_atf_data));
405   save_item(NAME(m_sgb_atf));
406   save_item(NAME(m_sgb_pal_data));
407   save_item(NAME(m_sgb_pal_map));
408   save_item(NAME(m_sgb_pal));
409   save_item(NAME(m_sgb_tile_map));
410   save_item(NAME(m_sgb_window_mask));
113411}
114412
115PALETTE_INIT_MEMBER(gb_state,gbc)
413void cgb_lcd_device::device_start()
116414{
117   int ii, r, g, b;
415   common_start();
416   
417   m_vram = auto_alloc_array_clear(machine(), UINT8, 0x4000);
418   save_pointer(NAME(m_vram), 0x4000);
118419
119   for( ii = 0; ii < 32768; ii++ )
120   {
121      r = (ii & 0x1F) << 3;
122      g = ((ii >> 5) & 0x1F) << 3;
123      b = ((ii >> 10) & 0x1F) << 3;
124      palette_set_color_rgb( machine(), ii, r, g, b );
125   }
420   memcpy(m_oam, cgb_oam_fingerprint, 0x100);
126421
422   
127423   /* Background is initialised as white */
128   for( ii = 0; ii < 32; ii++ )
129      m_lcd.cgb_bpal[ii] = 32767;
424   for (int i = 0; i < 32; i++)
425      m_cgb_bpal[i] = 32767;
130426   /* Sprites are supposed to be uninitialized, but we'll make them black */
131   for( ii = 0; ii < 32; ii++ )
132      m_lcd.cgb_spal[ii] = 0;
427   for (int i = 0; i < 32; i++)
428      m_cgb_spal[i] = 0;
133429}
134430
135PALETTE_INIT_MEMBER(megaduck_state,megaduck)
431
432//-------------------------------------------------
433//  device_reset - device-specific reset
434//-------------------------------------------------
435
436void gb_lcd_device::common_reset()
437{   
438   m_window_lines_drawn = 0;
439   
440   m_current_line = 0;
441   m_cmp_line = 0;
442   m_sprCount = 0;
443   m_previous_line = 0;
444   m_start_x = 0;
445   m_end_x = 0;
446   m_mode = 0;
447   m_state = 0;
448   m_lcd_irq_line = 0;
449   m_triggering_line_irq = 0;
450   m_line_irq = 0;
451   m_triggering_mode_irq = 0;
452   m_mode_irq = 0;
453   m_delayed_line_irq = 0;
454   m_sprite_cycles = 0;
455   m_scrollx_adjust = 0;
456   m_oam_locked = 0;
457   m_vram_locked = 0;
458   m_pal_locked = 0;
459   m_gbc_mode = 0;
460   m_gb_tile_no_mod = 0;
461   m_vram_bank = 0;
462   
463   m_gb_chrgen_offs = 0;
464   m_gb_bgdtab_offs = 0x1c00;
465   m_gb_wndtab_offs = 0x1c00;
466   
467   memset(&m_vid_regs, 0, sizeof(m_vid_regs));
468   memset(&m_bg_zbuf, 0, sizeof(m_bg_zbuf));
469   memset(&m_cgb_bpal, 0, sizeof(m_cgb_bpal));
470   memset(&m_cgb_spal, 0, sizeof(m_cgb_spal));
471   memset(&m_sprite, 0, sizeof(m_sprite));
472   memset(&m_layer[0], 0, sizeof(m_layer[0]));
473   memset(&m_layer[1], 0, sizeof(m_layer[1]));
474   
475   // specific reg initialization
476   m_vid_regs[0x06] = 0xff;
477   
478   for (int i = 0x0c; i < _NR_GB_VID_REGS; i++)
479      m_vid_regs[i] = 0xff;
480   
481   LCDSTAT = 0x80;
482   LCDCONT = 0x00;     /* Video hardware is turned off at boot time */
483   m_current_line = CURLINE = CMPLINE = 0x00;
484   SCROLLX = SCROLLY = 0x00;
485   SPR0PAL = SPR1PAL = 0xFF;
486   WNDPOSX = WNDPOSY = 0x00;
487   
488   // Initialize palette arrays
489   for (int i = 0; i < 4; i++)
490      m_gb_bpal[i] = m_gb_spal0[i] = m_gb_spal1[i] = i;
491   
492}
493
494
495void gb_lcd_device::device_reset()
136496{
137   int ii;
138   for( ii = 0; ii < 4; ii++)
139   {
140      palette_set_color_rgb(machine(), ii, palette_megaduck[ii*3+0], palette_megaduck[ii*3+1], palette_megaduck[ii*3+2]);
141   }
497   common_reset();
498
499   m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
142500}
143501
502void mgb_lcd_device::device_reset()
503{
504   address_space &space = m_maincpu->space(AS_PROGRAM);
505   common_reset();
144506
145inline void gb_state::gb_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color)
507   /* Make sure the VBlank interrupt is set when the first instruction gets executed */
508   machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(1), timer_expired_delegate(FUNC(mgb_lcd_device::video_init_vbl),this));
509   
510   /* Initialize some video registers */
511   video_w(space, 0x0, 0x91);    /* LCDCONT */
512   video_w(space, 0x7, 0xFC);    /* BGRDPAL */
513   video_w(space, 0x8, 0xFC);    /* SPR0PAL */
514   video_w(space, 0x9, 0xFC);    /* SPR1PAL */
515   
516   CURLINE = m_current_line = 0;
517   LCDSTAT = (LCDSTAT & 0xF8) | 0x05;
518   m_mode = 1;
519
520   m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(60), GB_LCD_STATE_LY00_M0);
521}
522
523void sgb_lcd_device::device_reset()
146524{
525   common_reset();
526
527   memset(m_sgb_tile_data, 0, 0x2000);
528
529   m_sgb_window_mask = 0;
530
531   memset(m_sgb_pal_map, 0, sizeof(m_sgb_pal_map));   
532   memset(m_sgb_atf_data, 0, sizeof(m_sgb_atf_data));
533}
534
535void cgb_lcd_device::device_reset()
536{
537   common_reset();
538   
539   m_gbc_chrgen_offs = 0x2000;
540   m_gbc_bgdtab_offs = 0x3c00;
541   m_gbc_wndtab_offs = 0x3c00;
542   
543   /* HDMA disabled */
544   m_hdma_enabled = 0;
545   m_hdma_possible = 0;
546   
547   m_gbc_mode = 1;
548   
549}
550
551
552
553inline void gb_lcd_device::plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color)
554{
147555   bitmap.pix16(y, x) = (UINT16)color;
148556}
149557
r23879r23880
151559  Select which sprites should be drawn for the current scanline and return the
152560  number of sprites selected.
153561 */
154void gb_state::gb_select_sprites()
562void gb_lcd_device::select_sprites()
155563{
156   int i, /*yindex,*/ line, height;
157   UINT8   *oam = m_lcd.gb_oam + 39 * 4;
564   int /*yindex,*/ line, height;
565   UINT8 *oam = m_oam + 39 * 4;
158566
159   m_lcd.sprCount = 0;
567   m_sprCount = 0;
160568
161569   /* If video hardware is enabled and sprites are enabled */
162   if ( ( LCDCONT & 0x80 ) && ( LCDCONT & 0x02 ) )
570   if ((LCDCONT & 0x80) && (LCDCONT & 0x02))
163571   {
164572      /* Check for stretched sprites */
165      if ( LCDCONT & 0x04 )
166      {
573      if (LCDCONT & 0x04)
167574         height = 16;
168      }
169575      else
170      {
171576         height = 8;
172      }
173577
174      //yindex = m_lcd.current_line;
175      line = m_lcd.current_line + 16;
578      //yindex = m_current_line;
579      line = m_current_line + 16;
176580
177      for( i = 39; i >= 0; i-- )
581      for (int i = 39; i >= 0; i--)
178582      {
179         if ( line >= oam[0] && line < ( oam[0] + height ) && oam[1] && oam[1] < 168 )
583         if (line >= oam[0] && line < (oam[0] + height) && oam[1] && oam[1] < 168)
180584         {
181585            /* We limit the sprite count to max 10 here;
182586               proper games should not exceed this... */
183            if ( m_lcd.sprCount < 10 )
587            if (m_sprCount < 10)
184588            {
185               m_lcd.sprite[m_lcd.sprCount] = i;
186               m_lcd.sprCount++;
589               m_sprite[m_sprCount] = i;
590               m_sprCount++;
187591            }
188592         }
189593         oam -= 4;
r23879r23880
191595   }
192596}
193597
194void gb_state::gb_update_sprites()
598void gb_lcd_device::update_sprites()
195599{
196600   bitmap_ind16 &bitmap = m_bitmap;
197601   UINT8 height, tilemask, line, *oam, *vram;
198   int i, yindex;
602   int yindex;
199603
200604   if (LCDCONT & 0x04)
201605   {
r23879r23880
208612      tilemask = 0xFF;
209613   }
210614
211   yindex = m_lcd.current_line;
212   line = m_lcd.current_line + 16;
615   yindex = m_current_line;
616   line = m_current_line + 16;
213617
214   oam = m_lcd.gb_oam + 39 * 4;
215   vram = m_lcd.gb_vram;
216   for (i = 39; i >= 0; i--)
618   oam = m_oam + 39 * 4;
619   vram = m_vram;
620   for (int i = 39; i >= 0; i--)
217621   {
218622      /* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
219623      if (line >= oam[0] && line < (oam[0] + height) && oam[1] && oam[1] < 168)
r23879r23880
222626         UINT8 bit, *spal;
223627         int xindex, adr;
224628
225         spal = (oam[3] & 0x10) ? m_lcd.gb_spal1 : m_lcd.gb_spal0;
629         spal = (oam[3] & 0x10) ? m_gb_spal1 : m_gb_spal0;
226630         xindex = oam[1] - 8;
227631         if (oam[3] & 0x40)         /* flip y ? */
228632         {
r23879r23880
240644            for (bit = 0; bit < 8; bit++, xindex++)
241645            {
242646               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
243               if (colour && !m_lcd.bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
244                  gb_plot_pixel(bitmap, xindex, yindex, spal[colour]);
647               if (colour && !m_bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
648                  plot_pixel(bitmap, xindex, yindex, spal[colour]);
245649               data >>= 1;
246650            }
247651            break;
r23879r23880
250654            {
251655               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
252656               if (colour && xindex >= 0 && xindex < 160)
253                  gb_plot_pixel(bitmap, xindex, yindex, spal[colour]);
657                  plot_pixel(bitmap, xindex, yindex, spal[colour]);
254658               data >>= 1;
255659            }
256660            break;
r23879r23880
258662            for (bit = 0; bit < 8 && xindex < 160; bit++, xindex++)
259663            {
260664               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
261               if (colour && !m_lcd.bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
262                  gb_plot_pixel(bitmap, xindex, yindex, spal[colour]);
665               if (colour && !m_bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
666                  plot_pixel(bitmap, xindex, yindex, spal[colour]);
263667               data <<= 1;
264668            }
265669            break;
r23879r23880
268672            {
269673               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
270674               if (colour && xindex >= 0 && xindex < 160)
271                  gb_plot_pixel(bitmap, xindex, yindex, spal[colour]);
675                  plot_pixel(bitmap, xindex, yindex, spal[colour]);
272676               data <<= 1;
273677            }
274678            break;
r23879r23880
278682   }
279683}
280684
281void gb_state::gb_update_scanline()
685void gb_lcd_device::update_scanline()
282686{
283687   bitmap_ind16 &bitmap = m_bitmap;
284688
285689   g_profiler.start(PROFILER_VIDEO);
286690
287691   /* Make sure we're in mode 3 */
288   if ( ( LCDSTAT & 0x03 ) == 0x03 )
692   if ((LCDSTAT & 0x03) == 0x03)
289693   {
290694      /* Calculate number of pixels to render based on time still left on the timer */
291      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd.lcd_timer->remaining( ) );
695      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd_timer->remaining());
292696      int l = 0;
293697
294      if ( m_lcd.start_x < 0 )
698      if (m_start_x < 0)
295699      {
296700         /* Window is enabled if the hardware says so AND the current scanline is
297701          * within the window AND the window X coordinate is <=166 */
298         m_lcd.layer[1].enabled = ( ( LCDCONT & 0x20 ) && ( m_lcd.current_line >= WNDPOSY ) && ( WNDPOSX <= 166 ) ) ? 1 : 0;
702         m_layer[1].enabled = ((LCDCONT & 0x20) && (m_current_line >= WNDPOSY) && (WNDPOSX <= 166)) ? 1 : 0;
299703
300704         /* BG is enabled if the hardware says so AND (window_off OR (window_on
301         * AND window's X position is >=7 ) ) */
302         m_lcd.layer[0].enabled = ( ( LCDCONT & 0x01 ) && ( ( ! m_lcd.layer[1].enabled ) || ( m_lcd.layer[1].enabled && ( WNDPOSX >= 7 ) ) ) ) ? 1 : 0;
705         * AND window's X position is >=7)) */
706         m_layer[0].enabled = ((LCDCONT & 0x01) && ((!m_layer[1].enabled) || (m_layer[1].enabled && (WNDPOSX >= 7)))) ? 1 : 0;
303707
304         if ( m_lcd.layer[0].enabled )
708         if (m_layer[0].enabled)
305709         {
306            m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
307            m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
308            m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
309            m_lcd.layer[0].xindex = SCROLLX >> 3;
310            m_lcd.layer[0].xshift = SCROLLX & 7;
311            m_lcd.layer[0].xstart = 0;
312            m_lcd.layer[0].xend = 160;
710            m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
711            m_layer[0].bg_map = m_vram + m_gb_bgdtab_offs;
712            m_layer[0].bg_tiles = m_vram + m_gb_chrgen_offs;
713            m_layer[0].xindex = SCROLLX >> 3;
714            m_layer[0].xshift = SCROLLX & 7;
715            m_layer[0].xstart = 0;
716            m_layer[0].xend = 160;
313717         }
314718
315         if ( m_lcd.layer[1].enabled )
719         if (m_layer[1].enabled)
316720         {
317            int xpos;
318
319            xpos = WNDPOSX - 7;             /* Window is offset by 7 pixels */
320            if ( xpos < 0 )
721            int xpos = WNDPOSX - 7;             /* Window is offset by 7 pixels */
722            if (xpos < 0)
321723               xpos = 0;
322724
323            m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
324            m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
325            m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
326            m_lcd.layer[1].xindex = 0;
327            m_lcd.layer[1].xshift = 0;
328            m_lcd.layer[1].xstart = xpos;
329            m_lcd.layer[1].xend = 160;
330            m_lcd.layer[0].xend = xpos;
725            m_layer[1].bgline = m_window_lines_drawn;
726            m_layer[1].bg_map = m_vram + m_gb_wndtab_offs;
727            m_layer[1].bg_tiles = m_vram + m_gb_chrgen_offs;
728            m_layer[1].xindex = 0;
729            m_layer[1].xshift = 0;
730            m_layer[1].xstart = xpos;
731            m_layer[1].xend = 160;
732            m_layer[0].xend = xpos;
331733         }
332         m_lcd.start_x = 0;
734         m_start_x = 0;
333735      }
334736
335      if ( cycles_to_go < 160 )
737      if (cycles_to_go < 160)
336738      {
337         m_lcd.end_x = MIN(160 - cycles_to_go,160);
739         m_end_x = MIN(160 - cycles_to_go, 160);
338740         /* Draw empty pixels when the background is disabled */
339         if ( ! ( LCDCONT & 0x01 ) )
741         if (!(LCDCONT & 0x01))
340742         {
341            rectangle r(m_lcd.start_x, m_lcd.end_x - 1, m_lcd.current_line, m_lcd.current_line);
342            bitmap.fill(m_lcd.gb_bpal[0], r );
743            rectangle r(m_start_x, m_end_x - 1, m_current_line, m_current_line);
744            bitmap.fill(m_gb_bpal[0], r);
343745         }
344         while ( l < 2 )
746         while (l < 2)
345747         {
346            UINT8   xindex, *map, *tiles;
347            UINT16  data;
748            UINT8 xindex, *map, *tiles;
749            UINT16 data;
348750            int i, tile_index;
349751
350            if ( ! m_lcd.layer[l].enabled )
752            if (!m_layer[l].enabled)
351753            {
352754               l++;
353755               continue;
354756            }
355            map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
356            tiles = m_lcd.layer[l].bg_tiles + ( ( m_lcd.layer[l].bgline & 7 ) << 1 );
357            xindex = m_lcd.start_x;
358            if ( xindex < m_lcd.layer[l].xstart )
359               xindex = m_lcd.layer[l].xstart;
360            i = m_lcd.end_x;
361            if ( i > m_lcd.layer[l].xend )
362               i = m_lcd.layer[l].xend;
757            map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
758            tiles = m_layer[l].bg_tiles + ((m_layer[l].bgline & 7) << 1);
759            xindex = m_start_x;
760            if (xindex < m_layer[l].xstart)
761               xindex = m_layer[l].xstart;
762            i = m_end_x;
763            if (i > m_layer[l].xend)
764               i = m_layer[l].xend;
363765            i = i - xindex;
364766
365            tile_index = ( map[ m_lcd.layer[l].xindex ] ^ m_lcd.gb_tile_no_mod ) * 16;
366            data = tiles[ tile_index ] | ( tiles[ tile_index+1 ] << 8 );
367            data <<= m_lcd.layer[l].xshift;
767            tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
768            data = tiles[tile_index] | (tiles[tile_index+1] << 8);
769            data <<= m_layer[l].xshift;
368770
369            while ( i > 0 )
771            while (i > 0)
370772            {
371               while ( ( m_lcd.layer[l].xshift < 8 ) && i )
773               while ((m_layer[l].xshift < 8) && i)
372774               {
373                  register int colour = ( ( data & 0x8000 ) ? 2 : 0 ) | ( ( data & 0x0080 ) ? 1 : 0 );
374                  gb_plot_pixel( bitmap, xindex, m_lcd.current_line, m_lcd.gb_bpal[ colour ] );
375                  m_lcd.bg_zbuf[ xindex ] = colour;
775                  register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
776                  plot_pixel(bitmap, xindex, m_current_line, m_gb_bpal[colour]);
777                  m_bg_zbuf[xindex] = colour;
376778                  xindex++;
377779                  data <<= 1;
378                  m_lcd.layer[l].xshift++;
780                  m_layer[l].xshift++;
379781                  i--;
380782               }
381               if ( m_lcd.layer[l].xshift == 8 )
783               if (m_layer[l].xshift == 8)
382784               {
383785                  /* Take possible changes to SCROLLY into account */
384                  if ( l == 0 )
786                  if (l == 0)
385787                  {
386                     m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
387                     map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
388                     tiles = m_lcd.layer[l].bg_tiles + ( ( m_lcd.layer[l].bgline & 7 ) << 1 );
788                     m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
789                     map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
790                     tiles = m_layer[l].bg_tiles + ((m_layer[l].bgline & 7) << 1);
389791                  }
390792
391                  m_lcd.layer[l].xindex = ( m_lcd.layer[l].xindex + 1 ) & 31;
392                  m_lcd.layer[l].xshift = 0;
393                  tile_index = ( map[ m_lcd.layer[l].xindex ] ^ m_lcd.gb_tile_no_mod ) * 16;
394                  data = tiles[ tile_index ] | ( tiles[ tile_index+1 ] << 8 );
793                  m_layer[l].xindex = (m_layer[l].xindex + 1) & 31;
794                  m_layer[l].xshift = 0;
795                  tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
796                  data = tiles[tile_index] | (tiles[tile_index + 1] << 8);
395797               }
396798            }
397799            l++;
398800         }
399         if ( m_lcd.end_x == 160 && LCDCONT & 0x02 )
801         if (m_end_x == 160 && LCDCONT & 0x02)
400802         {
401            gb_update_sprites();
803            update_sprites();
402804         }
403         m_lcd.start_x = m_lcd.end_x;
805         m_start_x = m_end_x;
404806      }
405807   }
406808   else
407809   {
408      if ( ! ( LCDCONT & 0x80 ) )
810      if (!(LCDCONT & 0x80))
409811      {
410812         /* Draw an empty line when LCD is disabled */
411         if ( m_lcd.previous_line != m_lcd.current_line )
813         if (m_previous_line != m_current_line)
412814         {
413            if ( m_lcd.current_line < 144 )
815            if (m_current_line < 144)
414816            {
415817               screen_device *screen = machine().first_screen();
416818               const rectangle &r = screen->visible_area();
417               rectangle r1(r.min_x, r.max_x, m_lcd.current_line, m_lcd.current_line);
418               bitmap.fill(0, r1 );
819               rectangle r1(r.min_x, r.max_x, m_current_line, m_current_line);
820               bitmap.fill(0, r1);
419821            }
420            m_lcd.previous_line = m_lcd.current_line;
822            m_previous_line = m_current_line;
421823         }
422824      }
423825   }
r23879r23880
427829
428830/* --- Super Game Boy Specific --- */
429831
430void gb_state::sgb_update_sprites()
832void sgb_lcd_device::update_sprites()
431833{
432834   bitmap_ind16 &bitmap = m_bitmap;
433835   UINT8 height, tilemask, line, *oam, *vram, pal;
434   INT16 i, yindex;
836   INT16 yindex;
435837
436838   if (LCDCONT & 0x04)
437839   {
r23879r23880
445847   }
446848
447849   /* Offset to center of screen */
448   yindex = m_lcd.current_line + SGB_YOFFSET;
449   line = m_lcd.current_line + 16;
850   yindex = m_current_line + SGB_YOFFSET;
851   line = m_current_line + 16;
450852
451   oam = m_lcd.gb_oam + 39 * 4;
452   vram = m_lcd.gb_vram;
453   for (i = 39; i >= 0; i--)
853   oam = m_oam + 39 * 4;
854   vram = m_vram;
855   for (int i = 39; i >= 0; i--)
454856   {
455857      /* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
456858      if (line >= oam[0] && line < (oam[0] + height) && oam[1] && oam[1] < 168)
r23879r23880
460862         INT16 xindex;
461863         int adr;
462864
463         spal = (oam[3] & 0x10) ? m_lcd.gb_spal1 : m_lcd.gb_spal0;
865         spal = (oam[3] & 0x10) ? m_gb_spal1 : m_gb_spal0;
464866         xindex = oam[1] - 8;
465867         if (oam[3] & 0x40)         /* flip y ? */
466868         {
467            adr = (oam[2] & tilemask) * 16 + (height -1 - line + oam[0]) * 2;
869            adr = (oam[2] & tilemask) * 16 + (height - 1 - line + oam[0]) * 2;
468870         }
469871         else
470872         {
r23879r23880
484886            for (bit = 0; bit < 8; bit++, xindex++)
485887            {
486888               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
487               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour && !m_lcd.bg_zbuf[xindex - SGB_XOFFSET])
488                  gb_plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
889               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour && !m_bg_zbuf[xindex - SGB_XOFFSET])
890                  plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
489891               data >>= 1;
490892            }
491893            break;
r23879r23880
494896            {
495897               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
496898               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour)
497                  gb_plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
899                  plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
498900               data >>= 1;
499901            }
500902            break;
r23879r23880
502904            for (bit = 0; bit < 8; bit++, xindex++)
503905            {
504906               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
505               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour && !m_lcd.bg_zbuf[xindex - SGB_XOFFSET])
506                  gb_plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
907               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour && !m_bg_zbuf[xindex - SGB_XOFFSET])
908                  plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
507909               data <<= 1;
508910            }
509911            break;
r23879r23880
512914            {
513915               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
514916               if ((xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160) && colour)
515                  gb_plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
917                  plot_pixel(bitmap, xindex, yindex, m_sgb_pal[pal + spal[colour]]);
516918               data <<= 1;
517919            }
518920            break;
r23879r23880
523925}
524926
525927
526void gb_state::sgb_refresh_border()
928void sgb_lcd_device::refresh_border()
527929{
528930   UINT16 data, data2;
529931   UINT8 *tiles, *tiles2;
530932
531   for( UINT16 yidx = 0; yidx < 224; yidx++ )
933   for (UINT16 yidx = 0; yidx < 224; yidx++)
532934   {
533      UINT8 *map = m_sgb_tile_map + ( ( yidx >> 3 ) * 64 );
935      UINT8 *map = m_sgb_tile_map + ((yidx >> 3) * 64);
534936      UINT16 xindex = 0;
535937
536      for( UINT16 xidx = 0; xidx < 64; xidx+=2 )
938      for (UINT16 xidx = 0; xidx < 64; xidx += 2)
537939      {
538         if( map[xidx+1] & 0x80 ) /* Vertical flip */
539            tiles = m_sgb_tile_data + ( ( 7 - ( yidx % 8 ) ) << 1 );
940         if (map[xidx + 1] & 0x80) /* Vertical flip */
941            tiles = m_sgb_tile_data + ((7 - (yidx % 8)) << 1);
540942         else /* No vertical flip */
541            tiles = m_sgb_tile_data + ( ( yidx % 8 ) << 1 );
943            tiles = m_sgb_tile_data + ((yidx % 8) << 1);
542944         tiles2 = tiles + 16;
543945
544         UINT8 pal = (map[xidx+1] & 0x1C) >> 2;
545         if( pal == 0 )
946         UINT8 pal = (map[xidx + 1] & 0x1C) >> 2;
947         if (pal == 0)
546948            pal = 1;
547949         pal <<= 4;
548950
549         if (m_cartslot && m_cartslot->get_sgb_hack())
951         if (m_sgb_border_hack)
550952         { /* A few games do weird stuff */
551953            UINT8 tileno = map[xidx];
552            if( tileno >= 128 ) tileno = ((64 + tileno) % 128) + 128;
954            if (tileno >= 128) tileno = ((64 + tileno) % 128) + 128;
553955            else tileno = (64 + tileno) % 128;
554            data = tiles[ tileno * 32 ] | ( tiles[ ( tileno * 32 ) + 1 ] << 8 );
555            data2 = tiles2[ tileno * 32 ] | ( tiles2[ ( tileno * 32 ) + 1 ] << 8 );
956            data = tiles[tileno * 32] | (tiles[(tileno * 32) + 1] << 8);
957            data2 = tiles2[tileno * 32] | (tiles2[(tileno * 32) + 1] << 8);
556958         }
557959         else
558960         {
559            data = tiles[ map[xidx] * 32 ] | ( tiles[ (map[xidx] * 32 ) + 1 ] << 8 );
560            data2 = tiles2[ map[xidx] * 32 ] | ( tiles2[ (map[xidx] * 32 ) + 1 ] << 8 );
961            data = tiles[map[xidx] * 32] | (tiles[(map[xidx] * 32) + 1] << 8);
962            data2 = tiles2[map[xidx] * 32] | (tiles2[(map[xidx] * 32) + 1] << 8);
561963         }
562964
563         for( UINT8 i = 0; i < 8; i++ )
965         for (int i = 0; i < 8; i++)
564966         {
565967            register UINT8 colour;
566            if( (map[xidx+1] & 0x40) )  /* Horizontal flip */
968            if ((map[xidx + 1] & 0x40))  /* Horizontal flip */
567969            {
568970               colour = ((data  & 0x0001) ? 1 : 0) | ((data  & 0x0100) ? 2 : 0) |
569971                     ((data2 & 0x0001) ? 4 : 0) | ((data2 & 0x0100) ? 8 : 0);
r23879r23880
581983             * Drawing there is allowed, but due to the way we draw the
582984             * scanline, it can obscure the screen even when it shouldn't.
583985             */
584            if( !((yidx >= SGB_YOFFSET && yidx < SGB_YOFFSET + 144) &&
585               (xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160)) )
986            if (!((yidx >= SGB_YOFFSET && yidx < SGB_YOFFSET + 144) &&
987               (xindex >= SGB_XOFFSET && xindex < SGB_XOFFSET + 160)))
586988            {
587               gb_plot_pixel(m_bitmap, xindex, yidx, m_sgb_pal[pal + colour]);
989               plot_pixel(m_bitmap, xindex, yidx, m_sgb_pal[pal + colour]);
588990            }
589991            xindex++;
590992         }
r23879r23880
592994   }
593995}
594996
595void gb_state::sgb_update_scanline()
997void sgb_lcd_device::update_scanline()
596998{
597999   bitmap_ind16 &bitmap = m_bitmap;
5981000
5991001   g_profiler.start(PROFILER_VIDEO);
6001002
601   if ( ( LCDSTAT & 0x03 ) == 0x03 )
1003   if ((LCDSTAT & 0x03) == 0x03)
6021004   {
6031005      /* Calcuate number of pixels to render based on time still left on the timer */
604      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd.lcd_timer->remaining( ) );
1006      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd_timer->remaining());
6051007      int l = 0;
6061008
607      if ( m_lcd.start_x < 0 )
1009      if (m_start_x < 0)
6081010      {
6091011         /* Window is enabled if the hardware says so AND the current scanline is
6101012          * within the window AND the window X coordinate is <=166 */
611         m_lcd.layer[1].enabled = ((LCDCONT & 0x20) && m_lcd.current_line >= WNDPOSY && WNDPOSX <= 166) ? 1 : 0;
1013         m_layer[1].enabled = ((LCDCONT & 0x20) && m_current_line >= WNDPOSY && WNDPOSX <= 166) ? 1 : 0;
6121014
6131015         /* BG is enabled if the hardware says so AND (window_off OR (window_on
614          * AND window's X position is >=7 ) ) */
615         m_lcd.layer[0].enabled = ((LCDCONT & 0x01) && ((!m_lcd.layer[1].enabled) || (m_lcd.layer[1].enabled && WNDPOSX >= 7))) ? 1 : 0;
1016          * AND window's X position is >=7 )) */
1017         m_layer[0].enabled = ((LCDCONT & 0x01) && ((!m_layer[1].enabled) || (m_layer[1].enabled && WNDPOSX >= 7))) ? 1 : 0;
6161018
617         if ( m_lcd.layer[0].enabled )
1019         if (m_layer[0].enabled)
6181020         {
619            m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
620            m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
621            m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
622            m_lcd.layer[0].xindex = SCROLLX >> 3;
623            m_lcd.layer[0].xshift = SCROLLX & 7;
624            m_lcd.layer[0].xstart = 0;
625            m_lcd.layer[0].xend = 160;
1021            m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
1022            m_layer[0].bg_map = m_vram + m_gb_bgdtab_offs;
1023            m_layer[0].bg_tiles = m_vram + m_gb_chrgen_offs;
1024            m_layer[0].xindex = SCROLLX >> 3;
1025            m_layer[0].xshift = SCROLLX & 7;
1026            m_layer[0].xstart = 0;
1027            m_layer[0].xend = 160;
6261028         }
6271029
628         if ( m_lcd.layer[1].enabled )
1030         if (m_layer[1].enabled)
6291031         {
6301032            int xpos;
6311033
r23879r23880
6341036            if (xpos < 0)
6351037               xpos = 0;
6361038
637            m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
638            m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
639            m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
640            m_lcd.layer[1].xindex = 0;
641            m_lcd.layer[1].xshift = 0;
642            m_lcd.layer[1].xstart = xpos;
643            m_lcd.layer[1].xend = 160;
644            m_lcd.layer[0].xend = xpos;
1039            m_layer[1].bgline = m_window_lines_drawn;
1040            m_layer[1].bg_map = m_vram + m_gb_wndtab_offs;
1041            m_layer[1].bg_tiles = m_vram + m_gb_chrgen_offs;
1042            m_layer[1].xindex = 0;
1043            m_layer[1].xshift = 0;
1044            m_layer[1].xstart = xpos;
1045            m_layer[1].xend = 160;
1046            m_layer[0].xend = xpos;
6451047         }
646         m_lcd.start_x = 0;
1048         m_start_x = 0;
6471049      }
6481050
649      if ( cycles_to_go == 0 )
1051      if (cycles_to_go == 0)
6501052      {
6511053         /* Does this belong here? or should it be moved to the else block */
6521054         /* Handle SGB mask */
653         switch( m_sgb_window_mask )
1055         switch (m_sgb_window_mask)
6541056         {
6551057         case 1: /* Freeze screen */
6561058            return;
6571059         case 2: /* Blank screen (black) */
6581060            {
6591061               rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160-1, SGB_YOFFSET, SGB_YOFFSET + 144 - 1);
660               bitmap.fill(0, r );
661            } return;
1062               bitmap.fill(0, r);
1063            }
1064            return;
6621065         case 3: /* Blank screen (white - or should it be color 0?) */
6631066            {
6641067               rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160 - 1, SGB_YOFFSET, SGB_YOFFSET + 144 - 1);
665               bitmap.fill(32767, r );
666            } return;
1068               bitmap.fill(32767, r);
1069            }
1070            return;
6671071         }
6681072
6691073         /* Draw the "border" if we're on the first line */
670         if ( m_lcd.current_line == 0 )
1074         if (m_current_line == 0)
6711075         {
672            sgb_refresh_border();
1076            refresh_border();
6731077         }
6741078      }
675      if ( cycles_to_go < 160 )
1079      if (cycles_to_go < 160)
6761080      {
677         m_lcd.end_x = MIN(160 - cycles_to_go,160);
1081         m_end_x = MIN(160 - cycles_to_go,160);
6781082
6791083         /* if background or screen disabled clear line */
680         if ( ! ( LCDCONT & 0x01 ) )
1084         if (!(LCDCONT & 0x01))
6811085         {
682            rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160 - 1, m_lcd.current_line + SGB_YOFFSET, m_lcd.current_line + SGB_YOFFSET);
683            bitmap.fill(0, r );
1086            rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160 - 1, m_current_line + SGB_YOFFSET, m_current_line + SGB_YOFFSET);
1087            bitmap.fill(0, r);
6841088         }
685         while( l < 2 )
1089         while (l < 2)
6861090         {
6871091            UINT8   xindex, sgb_palette, *map, *tiles;
6881092            UINT16  data;
6891093            int i, tile_index;
6901094
691            if ( ! m_lcd.layer[l].enabled )
1095            if (!m_layer[l].enabled)
6921096            {
6931097               l++;
6941098               continue;
6951099            }
696            map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
697            tiles = m_lcd.layer[l].bg_tiles + ( ( m_lcd.layer[l].bgline & 7 ) << 1 );
698            xindex = m_lcd.start_x;
699            if ( xindex < m_lcd.layer[l].xstart )
700               xindex = m_lcd.layer[l].xstart;
701            i = m_lcd.end_x;
702            if ( i > m_lcd.layer[l].xend )
703               i = m_lcd.layer[l].xend;
1100            map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
1101            tiles = m_layer[l].bg_tiles + ((m_layer[l].bgline & 7) << 1);
1102            xindex = m_start_x;
1103            if (xindex < m_layer[l].xstart)
1104               xindex = m_layer[l].xstart;
1105            i = m_end_x;
1106            if (i > m_layer[l].xend)
1107               i = m_layer[l].xend;
7041108            i = i - xindex;
7051109
706            tile_index = (map[m_lcd.layer[l].xindex] ^ m_lcd.gb_tile_no_mod) * 16;
707            data = tiles[tile_index] | ( tiles[tile_index + 1] << 8 );
708            data <<= m_lcd.layer[l].xshift;
1110            tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
1111            data = tiles[tile_index] | (tiles[tile_index + 1] << 8);
1112            data <<= m_layer[l].xshift;
7091113
7101114            /* Figure out which palette we're using */
711            sgb_palette = m_sgb_pal_map[ ( m_lcd.end_x - i ) >> 3 ][ m_lcd.current_line >> 3 ] << 2;
1115            sgb_palette = m_sgb_pal_map[(m_end_x - i) >> 3][m_current_line >> 3] << 2;
7121116
713            while( i > 0 )
1117            while (i > 0)
7141118            {
715               while( ( m_lcd.layer[l].xshift < 8 ) && i )
1119               while ((m_layer[l].xshift < 8) && i)
7161120               {
717                  register int colour = ( ( data & 0x8000 ) ? 2 : 0 ) | ( ( data & 0x0080 ) ? 1 : 0 );
718                  gb_plot_pixel( bitmap, xindex + SGB_XOFFSET, m_lcd.current_line + SGB_YOFFSET, m_sgb_pal[ sgb_palette + m_lcd.gb_bpal[colour]] );
719                  m_lcd.bg_zbuf[xindex] = colour;
1121                  register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
1122                  plot_pixel(bitmap, xindex + SGB_XOFFSET, m_current_line + SGB_YOFFSET, m_sgb_pal[sgb_palette + m_gb_bpal[colour]]);
1123                  m_bg_zbuf[xindex] = colour;
7201124                  xindex++;
7211125                  data <<= 1;
722                  m_lcd.layer[l].xshift++;
1126                  m_layer[l].xshift++;
7231127                  i--;
7241128               }
725               if ( m_lcd.layer[l].xshift == 8 )
1129               if (m_layer[l].xshift == 8)
7261130               {
7271131                  /* Take possible changes to SCROLLY into account */
728                  if ( l == 0 )
1132                  if (l == 0)
7291133                  {
730                     m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
731                     map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
732                     tiles = m_lcd.layer[l].bg_tiles + ( ( m_lcd.layer[l].bgline & 7 ) << 1 );
1134                     m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
1135                     map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
1136                     tiles = m_layer[l].bg_tiles + ((m_layer[l].bgline & 7) << 1);
7331137                  }
7341138
735                  m_lcd.layer[l].xindex = ( m_lcd.layer[l].xindex + 1 ) & 31;
736                  m_lcd.layer[l].xshift = 0;
737                  tile_index = ( map[ m_lcd.layer[l].xindex ] ^ m_lcd.gb_tile_no_mod ) * 16;
738                  data = tiles[ tile_index ] | ( tiles[ tile_index + 1 ] << 8 );
739                  sgb_palette = m_sgb_pal_map[ ( m_lcd.end_x - i ) >> 3 ][ m_lcd.current_line >> 3 ] << 2;
1139                  m_layer[l].xindex = (m_layer[l].xindex + 1) & 31;
1140                  m_layer[l].xshift = 0;
1141                  tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
1142                  data = tiles[tile_index] | (tiles[tile_index + 1] << 8);
1143                  sgb_palette = m_sgb_pal_map[(m_end_x - i) >> 3][m_current_line >> 3] << 2;
7401144               }
7411145            }
7421146            l++;
7431147         }
744         if ( ( m_lcd.end_x == 160 ) && ( LCDCONT & 0x02 ) )
1148         if ((m_end_x == 160) && (LCDCONT & 0x02))
7451149         {
746            sgb_update_sprites();
1150            update_sprites();
7471151         }
748         m_lcd.start_x = m_lcd.end_x;
1152         m_start_x = m_end_x;
7491153      }
7501154   }
7511155   else
7521156   {
753      if ( ! ( LCDCONT * 0x80 ) )
1157      if (!(LCDCONT * 0x80))
7541158      {
7551159         /* if screen disabled clear line */
756         if ( m_lcd.previous_line != m_lcd.current_line )
1160         if (m_previous_line != m_current_line)
7571161         {
7581162            /* Also refresh border here??? */
759            if ( m_lcd.current_line < 144 )
1163            if (m_current_line < 144)
7601164            {
761               rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160 - 1, m_lcd.current_line + SGB_YOFFSET, m_lcd.current_line + SGB_YOFFSET);
1165               rectangle r(SGB_XOFFSET, SGB_XOFFSET + 160 - 1, m_current_line + SGB_YOFFSET, m_current_line + SGB_YOFFSET);
7621166               bitmap.fill(0, r);
7631167            }
764            m_lcd.previous_line = m_lcd.current_line;
1168            m_previous_line = m_current_line;
7651169         }
7661170      }
7671171   }
r23879r23880
7711175
7721176/* --- Game Boy Color Specific --- */
7731177
774void gb_state::cgb_update_sprites()
1178void cgb_lcd_device::update_sprites()
7751179{
7761180   bitmap_ind16 &bitmap = m_bitmap;
7771181   UINT8 height, tilemask, line, *oam;
778   int i, xindex, yindex;
1182   int xindex, yindex;
7791183
7801184   if (LCDCONT & 0x04)
7811185   {
r23879r23880
7881192      tilemask = 0xFF;
7891193   }
7901194
791   yindex = m_lcd.current_line;
792   line = m_lcd.current_line + 16;
1195   yindex = m_current_line;
1196   line = m_current_line + 16;
7931197
794   oam = m_lcd.gb_oam + 39 * 4;
795   for (i = 39; i >= 0; i--)
1198   oam = m_oam + 39 * 4;
1199   for (int i = 39; i >= 0; i--)
7961200   {
7971201      /* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
7981202      if (line >= oam[0] && line < (oam[0] + height) && oam[1] && oam[1] < 168)
r23879r23880
8011205         UINT8 bit, pal;
8021206
8031207         /* Handle mono mode for GB games */
804         if( ! m_lcd.gbc_mode )
1208         if (!m_gbc_mode)
8051209            pal = (oam[3] & 0x10) ? 4 : 0;
8061210         else
8071211            pal = ((oam[3] & 0x7) * 4);
r23879r23880
8091213         xindex = oam[1] - 8;
8101214         if (oam[3] & 0x40)         /* flip y ? */
8111215         {
812            data = *((UINT16 *) &m_lcd.gb_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (height - 1 - line + oam[0]) * 2]);
1216            data = *((UINT16 *) &m_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (height - 1 - line + oam[0]) * 2]);
8131217         }
8141218         else
8151219         {
816            data = *((UINT16 *) &m_lcd.gb_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (line - oam[0]) * 2]);
1220            data = *((UINT16 *) &m_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (line - oam[0]) * 2]);
8171221         }
8181222#ifndef LSB_FIRST
8191223         data = (data << 8) | (data >> 8);
r23879r23880
8251229            for (bit = 0; bit < 8; bit++, xindex++)
8261230            {
8271231               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
828               if (colour && !m_lcd.bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
1232               if (colour && !m_bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
8291233               {
830                  if ( ! m_lcd.gbc_mode )
831                     colour = pal ? m_lcd.gb_spal1[colour] : m_lcd.gb_spal0[colour];
832                  gb_plot_pixel(bitmap, xindex, yindex, m_lcd.cgb_spal[pal + colour]);
1234                  if (! m_gbc_mode)
1235                     colour = pal ? m_gb_spal1[colour] : m_gb_spal0[colour];
1236                  plot_pixel(bitmap, xindex, yindex, m_cgb_spal[pal + colour]);
8331237               }
8341238               data >>= 1;
8351239            }
r23879r23880
8381242            for (bit = 0; bit < 8; bit++, xindex++)
8391243            {
8401244               register int colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
841               if((m_lcd.bg_zbuf[xindex] & 0x80) && (m_lcd.bg_zbuf[xindex] & 0x7f) && (LCDCONT & 0x1))
1245               if ((m_bg_zbuf[xindex] & 0x80) && (m_bg_zbuf[xindex] & 0x7f) && (LCDCONT & 0x1))
8421246                  colour = 0;
8431247               if (colour && xindex >= 0 && xindex < 160)
8441248               {
845                  if ( ! m_lcd.gbc_mode )
846                     colour = pal ? m_lcd.gb_spal1[colour] : m_lcd.gb_spal0[colour];
847                  gb_plot_pixel(bitmap, xindex, yindex, m_lcd.cgb_spal[pal + colour]);
1249                  if (! m_gbc_mode)
1250                     colour = pal ? m_gb_spal1[colour] : m_gb_spal0[colour];
1251                  plot_pixel(bitmap, xindex, yindex, m_cgb_spal[pal + colour]);
8481252               }
8491253               data >>= 1;
8501254            }
r23879r23880
8531257            for (bit = 0; bit < 8; bit++, xindex++)
8541258            {
8551259               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
856               if (colour && !m_lcd.bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
1260               if (colour && !m_bg_zbuf[xindex] && xindex >= 0 && xindex < 160)
8571261               {
858                  if ( ! m_lcd.gbc_mode )
859                     colour = pal ? m_lcd.gb_spal1[colour] : m_lcd.gb_spal0[colour];
860                  gb_plot_pixel(bitmap, xindex, yindex, m_lcd.cgb_spal[pal + colour]);
1262                  if (! m_gbc_mode)
1263                     colour = pal ? m_gb_spal1[colour] : m_gb_spal0[colour];
1264                  plot_pixel(bitmap, xindex, yindex, m_cgb_spal[pal + colour]);
8611265               }
8621266               data <<= 1;
8631267            }
r23879r23880
8661270            for (bit = 0; bit < 8; bit++, xindex++)
8671271            {
8681272               register int colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
869               if((m_lcd.bg_zbuf[xindex] & 0x80) && (m_lcd.bg_zbuf[xindex] & 0x7f) && (LCDCONT & 0x1))
1273               if ((m_bg_zbuf[xindex] & 0x80) && (m_bg_zbuf[xindex] & 0x7f) && (LCDCONT & 0x1))
8701274                  colour = 0;
8711275               if (colour && xindex >= 0 && xindex < 160)
8721276               {
873                  if ( ! m_lcd.gbc_mode )
874                     colour = pal ? m_lcd.gb_spal1[colour] : m_lcd.gb_spal0[colour];
875                  gb_plot_pixel(bitmap, xindex, yindex, m_lcd.cgb_spal[pal + colour]);
1277                  if (! m_gbc_mode)
1278                     colour = pal ? m_gb_spal1[colour] : m_gb_spal0[colour];
1279                  plot_pixel(bitmap, xindex, yindex, m_cgb_spal[pal + colour]);
8761280               }
8771281               data <<= 1;
8781282            }
r23879r23880
8831287   }
8841288}
8851289
886void gb_state::cgb_update_scanline()
1290void cgb_lcd_device::update_scanline()
8871291{
8881292   bitmap_ind16 &bitmap = m_bitmap;
8891293
8901294   g_profiler.start(PROFILER_VIDEO);
8911295
892   if ( ( LCDSTAT & 0x03 ) == 0x03 )
1296   if ((LCDSTAT & 0x03) == 0x03)
8931297   {
8941298      /* Calcuate number of pixels to render based on time still left on the timer */
895      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd.lcd_timer->remaining( ) );
1299      UINT32 cycles_to_go = m_maincpu->attotime_to_cycles(m_lcd_timer->remaining());
8961300      int l = 0;
8971301
898      if ( m_lcd.start_x < 0 )
1302      if (m_start_x < 0)
8991303      {
9001304         /* Window is enabled if the hardware says so AND the current scanline is
9011305          * within the window AND the window X coordinate is <=166 */
902         m_lcd.layer[1].enabled = ( ( LCDCONT & 0x20 ) && ( m_lcd.current_line >= WNDPOSY ) && ( WNDPOSX <= 166 ) ) ? 1 : 0;
1306         m_layer[1].enabled = ((LCDCONT & 0x20) && (m_current_line >= WNDPOSY) && (WNDPOSX <= 166)) ? 1 : 0;
9031307
9041308         /* BG is enabled if the hardware says so AND (window_off OR (window_on
905          * AND window's X position is >=7 ) ) */
906         m_lcd.layer[0].enabled = ( ( LCDCONT & 0x01 ) && ( ( ! m_lcd.layer[1].enabled ) || ( m_lcd.layer[1].enabled && ( WNDPOSX >= 7 ) ) ) ) ? 1 : 0;
1309          * AND window's X position is >=7 )) */
1310         m_layer[0].enabled = ((LCDCONT & 0x01) && ((!m_layer[1].enabled) || (m_layer[1].enabled && (WNDPOSX >= 7)))) ? 1 : 0;
9071311
908         if ( m_lcd.layer[0].enabled )
1312         if (m_layer[0].enabled)
9091313         {
910            m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
911            m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
912            m_lcd.layer[0].gbc_map = m_lcd.gb_vram + m_lcd.gbc_bgdtab_offs;
913            m_lcd.layer[0].xindex = SCROLLX >> 3;
914            m_lcd.layer[0].xshift = SCROLLX & 7;
915            m_lcd.layer[0].xstart = 0;
916            m_lcd.layer[0].xend = 160;
1314            m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
1315            m_layer[0].bg_map = m_vram + m_gb_bgdtab_offs;
1316            m_layer[0].gbc_map = m_vram + m_gbc_bgdtab_offs;
1317            m_layer[0].xindex = SCROLLX >> 3;
1318            m_layer[0].xshift = SCROLLX & 7;
1319            m_layer[0].xstart = 0;
1320            m_layer[0].xend = 160;
9171321         }
9181322
919         if ( m_lcd.layer[1].enabled )
1323         if (m_layer[1].enabled)
9201324         {
9211325            int xpos;
9221326
r23879r23880
9251329            if (xpos < 0)
9261330               xpos = 0;
9271331
928            m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
929            m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
930            m_lcd.layer[1].gbc_map = m_lcd.gb_vram + m_lcd.gbc_wndtab_offs;
931            m_lcd.layer[1].xindex = 0;
932            m_lcd.layer[1].xshift = 0;
933            m_lcd.layer[1].xstart = xpos;
934            m_lcd.layer[1].xend = 160;
935            m_lcd.layer[0].xend = xpos;
1332            m_layer[1].bgline = m_window_lines_drawn;
1333            m_layer[1].bg_map = m_vram + m_gb_wndtab_offs;
1334            m_layer[1].gbc_map = m_vram + m_gbc_wndtab_offs;
1335            m_layer[1].xindex = 0;
1336            m_layer[1].xshift = 0;
1337            m_layer[1].xstart = xpos;
1338            m_layer[1].xend = 160;
1339            m_layer[0].xend = xpos;
9361340         }
937         m_lcd.start_x = 0;
1341         m_start_x = 0;
9381342      }
9391343
940      if ( cycles_to_go < 160 )
1344      if (cycles_to_go < 160)
9411345      {
942         m_lcd.end_x = MIN(160 - cycles_to_go,160);
1346         m_end_x = MIN(160 - cycles_to_go, 160);
9431347         /* Draw empty line when the background is disabled */
944         if ( ! ( LCDCONT & 0x01 ) )
1348         if (!(LCDCONT & 0x01))
9451349         {
946            rectangle r(m_lcd.start_x, m_lcd.end_x - 1, m_lcd.current_line, m_lcd.current_line);
947            bitmap.fill(( ! m_lcd.gbc_mode ) ? 0 : 32767 , r);
1350            rectangle r(m_start_x, m_end_x - 1, m_current_line, m_current_line);
1351            bitmap.fill((!m_gbc_mode) ? 0 : 32767, r);
9481352         }
949         while ( l < 2 )
1353         while (l < 2)
9501354         {
9511355            UINT8   xindex, *map, *tiles, *gbcmap;
9521356            UINT16  data;
9531357            int i, tile_index;
9541358
955            if ( ! m_lcd.layer[l].enabled )
1359            if (!m_layer[l].enabled)
9561360            {
9571361               l++;
9581362               continue;
9591363            }
960            map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
961            gbcmap = m_lcd.layer[l].gbc_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
962            tiles = (gbcmap[m_lcd.layer[l].xindex] & 0x08) ? (m_lcd.gb_vram + m_lcd.gbc_chrgen_offs) : (m_lcd.gb_vram + m_lcd.gb_chrgen_offs);
1364            map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
1365            gbcmap = m_layer[l].gbc_map + ((m_layer[l].bgline << 2) & 0x3E0);
1366            tiles = (gbcmap[m_layer[l].xindex] & 0x08) ? (m_vram + m_gbc_chrgen_offs) : (m_vram + m_gb_chrgen_offs);
9631367
9641368            /* Check for vertical flip */
965            if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x40 )
1369            if (gbcmap[m_layer[l].xindex] & 0x40)
9661370            {
967               tiles += ( ( 7 - ( m_lcd.layer[l].bgline & 0x07 ) ) << 1 );
1371               tiles += ((7 - (m_layer[l].bgline & 0x07)) << 1);
9681372            }
9691373            else
9701374            {
971               tiles += ( ( m_lcd.layer[l].bgline & 0x07 ) << 1 );
1375               tiles += ((m_layer[l].bgline & 0x07) << 1);
9721376            }
973            xindex = m_lcd.start_x;
974            if ( xindex < m_lcd.layer[l].xstart )
975               xindex = m_lcd.layer[l].xstart;
976            i = m_lcd.end_x;
977            if ( i > m_lcd.layer[l].xend )
978               i = m_lcd.layer[l].xend;
1377            xindex = m_start_x;
1378            if (xindex < m_layer[l].xstart)
1379               xindex = m_layer[l].xstart;
1380            i = m_end_x;
1381            if (i > m_layer[l].xend)
1382               i = m_layer[l].xend;
9791383            i = i - xindex;
9801384
981            tile_index = ( map[ m_lcd.layer[l].xindex ] ^ m_lcd.gb_tile_no_mod ) * 16;
982            data = tiles[ tile_index ] | ( tiles[ tile_index + 1 ] << 8 );
1385            tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
1386            data = tiles[tile_index] | (tiles[tile_index + 1] << 8);
9831387            /* Check for horinzontal flip */
984            if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x20 )
1388            if (gbcmap[m_layer[l].xindex] & 0x20)
9851389            {
986               data >>= m_lcd.layer[l].xshift;
1390               data >>= m_layer[l].xshift;
9871391            }
9881392            else
9891393            {
990               data <<= m_lcd.layer[l].xshift;
1394               data <<= m_layer[l].xshift;
9911395            }
9921396
993            while ( i > 0 )
1397            while (i > 0)
9941398            {
995               while ( ( m_lcd.layer[l].xshift < 8 ) && i )
1399               while ((m_layer[l].xshift < 8) && i)
9961400               {
9971401                  int colour;
9981402                  /* Check for horinzontal flip */
999                  if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x20 )
1403                  if (gbcmap[m_layer[l].xindex] & 0x20)
10001404                  {
1001                     colour = ( ( data & 0x0100 ) ? 2 : 0 ) | ( ( data & 0x0001 ) ? 1 : 0 );
1405                     colour = ((data & 0x0100) ? 2 : 0) | ((data & 0x0001) ? 1 : 0);
10021406                     data >>= 1;
10031407                  }
10041408                  else
10051409                  {
1006                     colour = ( ( data & 0x8000 ) ? 2 : 0 ) | ( ( data & 0x0080 ) ? 1 : 0 );
1410                     colour = ((data & 0x8000) ? 2 : 0) | ((data & 0x0080) ? 1 : 0);
10071411                     data <<= 1;
10081412                  }
1009                  gb_plot_pixel( bitmap, xindex, m_lcd.current_line, m_lcd.cgb_bpal[ ( ! m_lcd.gbc_mode ) ? m_lcd.gb_bpal[colour] : ( ( ( gbcmap[ m_lcd.layer[l].xindex ] & 0x07 ) * 4 ) + colour ) ] );
1010                  m_lcd.bg_zbuf[ xindex ] = colour + ( gbcmap[ m_lcd.layer[l].xindex ] & 0x80 );
1413                  plot_pixel(bitmap, xindex, m_current_line, m_cgb_bpal[(!m_gbc_mode) ? m_gb_bpal[colour] : (((gbcmap[m_layer[l].xindex] & 0x07) * 4) + colour)]);
1414                  m_bg_zbuf[xindex] = colour + (gbcmap[m_layer[l].xindex] & 0x80);
10111415                  xindex++;
1012                  m_lcd.layer[l].xshift++;
1416                  m_layer[l].xshift++;
10131417                  i--;
10141418               }
1015               if ( m_lcd.layer[l].xshift == 8 )
1419               if (m_layer[l].xshift == 8)
10161420               {
10171421                  /* Take possible changes to SCROLLY into account */
1018                  if ( l == 0 )
1422                  if (l == 0)
10191423                  {
1020                     m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
1021                     map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
1022                     gbcmap = m_lcd.layer[l].gbc_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
1424                     m_layer[0].bgline = (SCROLLY + m_current_line) & 0xFF;
1425                     map = m_layer[l].bg_map + ((m_layer[l].bgline << 2) & 0x3E0);
1426                     gbcmap = m_layer[l].gbc_map + ((m_layer[l].bgline << 2) & 0x3E0);
10231427                  }
10241428
1025                  m_lcd.layer[l].xindex = ( m_lcd.layer[l].xindex + 1 ) & 31;
1026                  m_lcd.layer[l].xshift = 0;
1027                  tiles = (gbcmap[m_lcd.layer[l].xindex] & 0x08) ? (m_lcd.gb_vram + m_lcd.gbc_chrgen_offs) : (m_lcd.gb_vram + m_lcd.gb_chrgen_offs);
1429                  m_layer[l].xindex = (m_layer[l].xindex + 1) & 31;
1430                  m_layer[l].xshift = 0;
1431                  tiles = (gbcmap[m_layer[l].xindex] & 0x08) ? (m_vram + m_gbc_chrgen_offs) : (m_vram + m_gb_chrgen_offs);
10281432
10291433                  /* Check for vertical flip */
1030                  if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x40 )
1434                  if (gbcmap[m_layer[l].xindex] & 0x40)
10311435                  {
1032                     tiles += ( ( 7 - ( m_lcd.layer[l].bgline & 0x07 ) ) << 1 );
1436                     tiles += ((7 - (m_layer[l].bgline & 0x07)) << 1);
10331437                  }
10341438                  else
10351439                  {
1036                     tiles += ( ( m_lcd.layer[l].bgline & 0x07 ) << 1 );
1440                     tiles += ((m_layer[l].bgline & 0x07) << 1);
10371441                  }
1038                  tile_index = ( map[ m_lcd.layer[l].xindex ] ^ m_lcd.gb_tile_no_mod ) * 16;
1039                  data = tiles[ tile_index ] | ( tiles[ tile_index + 1 ] << 8 );
1442                  tile_index = (map[m_layer[l].xindex] ^ m_gb_tile_no_mod) * 16;
1443                  data = tiles[tile_index] | (tiles[tile_index + 1] << 8);
10401444               }
10411445            }
10421446            l++;
10431447         }
1044         if ( m_lcd.end_x == 160 && ( LCDCONT & 0x02 ) )
1448         if (m_end_x == 160 && (LCDCONT & 0x02))
10451449         {
1046            cgb_update_sprites();
1450            update_sprites();
10471451         }
1048         m_lcd.start_x = m_lcd.end_x;
1452         m_start_x = m_end_x;
10491453      }
10501454   }
10511455   else
10521456   {
1053      if ( ! ( LCDCONT & 0x80 ) )
1457      if (!(LCDCONT & 0x80))
10541458      {
10551459         /* Draw an empty line when LCD is disabled */
1056         if ( m_lcd.previous_line != m_lcd.current_line )
1460         if (m_previous_line != m_current_line)
10571461         {
1058            if ( m_lcd.current_line < 144 )
1462            if (m_current_line < 144)
10591463            {
10601464               screen_device *screen = machine().first_screen();
10611465               const rectangle &r1 = screen->visible_area();
1062               rectangle r(r1.min_x, r1.max_x, m_lcd.current_line, m_lcd.current_line);
1063               bitmap.fill(( ! m_lcd.gbc_mode ) ? 0 : 32767 , r);
1466               rectangle r(r1.min_x, r1.max_x, m_current_line, m_current_line);
1467               bitmap.fill((!m_gbc_mode) ? 0 : 32767 , r);
10641468            }
1065            m_lcd.previous_line = m_lcd.current_line;
1469            m_previous_line = m_current_line;
10661470         }
10671471      }
10681472   }
r23879r23880
10701474   g_profiler.stop();
10711475}
10721476
1073/* OAM contents on power up.
10741477
1075The OAM area seems contain some kind of unit fingerprint. On each boot
1076the data is almost always the same. Some random bits are flipped between
1077different boots. It is currently unknown how much these fingerprints
1078differ between different units.
1079
1080OAM fingerprints taken from Wilbert Pol's own unit.
1081*/
1082
1083static const UINT8 dmg_oam_fingerprint[0x100] = {
1084   0xD8, 0xE6, 0xB3, 0x89, 0xEC, 0xDE, 0x11, 0x62, 0x0B, 0x7E, 0x48, 0x9E, 0xB9, 0x6E, 0x26, 0xC9,
1085   0x36, 0xF4, 0x7D, 0xE4, 0xD9, 0xCE, 0xFA, 0x5E, 0xA3, 0x77, 0x60, 0xFC, 0x1C, 0x64, 0x8B, 0xAC,
1086   0xB6, 0x74, 0x3F, 0x9A, 0x0E, 0xFE, 0xEA, 0xA9, 0x40, 0x3A, 0x7A, 0xB6, 0xF2, 0xED, 0xA8, 0x3E,
1087   0xAF, 0x2C, 0xD2, 0xF2, 0x01, 0xE0, 0x5B, 0x3A, 0x53, 0x6A, 0x1C, 0x6C, 0x20, 0xD9, 0x22, 0xB4,
1088   0x8C, 0x38, 0x71, 0x69, 0x3E, 0x93, 0xA3, 0x22, 0xCE, 0x76, 0x24, 0xE7, 0x1A, 0x14, 0x6B, 0xB1,
1089   0xF9, 0x3D, 0xBF, 0x3D, 0x74, 0x64, 0xCB, 0xF5, 0xDC, 0x9A, 0x53, 0xC6, 0x0E, 0x78, 0x34, 0xCB,
1090   0x42, 0xB3, 0xFF, 0x07, 0x73, 0xAE, 0x6C, 0xA2, 0x6F, 0x6A, 0xA4, 0x66, 0x0A, 0x8C, 0x40, 0xB3,
1091   0x9A, 0x3D, 0x39, 0x78, 0xAB, 0x29, 0xE7, 0xC5, 0x7A, 0xDD, 0x51, 0x95, 0x2B, 0xE4, 0x1B, 0xF6,
1092   0x31, 0x16, 0x34, 0xFE, 0x11, 0xF2, 0x5E, 0x11, 0xF3, 0x95, 0x66, 0xB9, 0x37, 0xC2, 0xAD, 0x6D,
1093   0x1D, 0xA7, 0x79, 0x06, 0xD7, 0xE5, 0x8F, 0xFA, 0x9C, 0x02, 0x0C, 0x31, 0x8B, 0x17, 0x2E, 0x31,
1094   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1095   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1097   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1099   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1100};
1101
1102static const UINT8 mgb_oam_fingerprint[0x100] = {
1103   0xB9, 0xE9, 0x0D, 0x69, 0xBB, 0x7F, 0x00, 0x80, 0xE9, 0x7B, 0x79, 0xA2, 0xFD, 0xCF, 0xD8, 0x0A,
1104   0x87, 0xEF, 0x44, 0x11, 0xFE, 0x37, 0x10, 0x21, 0xFA, 0xFF, 0x00, 0x17, 0xF6, 0x4F, 0x83, 0x03,
1105   0x3A, 0xF4, 0x00, 0x24, 0xBB, 0xAE, 0x05, 0x01, 0xFF, 0xF7, 0x12, 0x48, 0xA7, 0x5E, 0xF6, 0x28,
1106   0x5B, 0xFF, 0x2E, 0x10, 0xFF, 0xB9, 0x50, 0xC8, 0xAF, 0x77, 0x2C, 0x1A, 0x62, 0xD7, 0x81, 0xC2,
1107   0xFD, 0x5F, 0xA0, 0x94, 0xAF, 0xFF, 0x51, 0x20, 0x36, 0x76, 0x50, 0x0A, 0xFD, 0xF6, 0x20, 0x00,
1108   0xFE, 0xF7, 0xA0, 0x68, 0xFF, 0xFC, 0x29, 0x51, 0xA3, 0xFA, 0x06, 0xC4, 0x94, 0xFF, 0x39, 0x0A,
1109   0xFF, 0x6C, 0x20, 0x20, 0xF1, 0xAD, 0x0C, 0x81, 0x56, 0xFB, 0x03, 0x82, 0xFF, 0xFF, 0x08, 0x58,
1110   0x96, 0x7E, 0x01, 0x4D, 0xFF, 0xE4, 0x82, 0xE3, 0x3D, 0xBB, 0x54, 0x00, 0x3D, 0xF3, 0x04, 0x21,
1111   0xB7, 0x39, 0xCC, 0x10, 0xF9, 0x5B, 0x80, 0x50, 0x3F, 0x6A, 0x1C, 0x21, 0x1F, 0xFA, 0xA8, 0x52,
1112   0x5F, 0xB3, 0x44, 0xA1, 0x96, 0x1E, 0x00, 0x27, 0x63, 0x77, 0x30, 0x54, 0x37, 0x6F, 0x60, 0x22,
1113   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1115   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1118   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1119};
1120
1121static const UINT8 cgb_oam_fingerprint[0x100] = {
1122   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1123   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1128   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1129   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1132   0x74, 0xFF, 0x09, 0x00, 0x9D, 0x61, 0xA8, 0x28, 0x36, 0x1E, 0x58, 0xAA, 0x75, 0x74, 0xA1, 0x42,
1133   0x05, 0x96, 0x40, 0x09, 0x41, 0x02, 0x60, 0x00, 0x1F, 0x11, 0x22, 0xBC, 0x31, 0x52, 0x22, 0x54,
1134   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
1135   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
1136   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04,
1137   0x22, 0xA9, 0xC4, 0x00, 0x1D, 0xAD, 0x80, 0x0C, 0x5D, 0xFA, 0x51, 0x92, 0x93, 0x98, 0xA4, 0x04
1138};
1139
1140/*
1141  For an AGS in CGB mode this data is: */
1142#if 0
1143static const UINT8 abs_oam_fingerprint[0x100] = {
1144   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1145   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1147   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1148   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1149   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154   0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1155   0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
1156   0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
1157   0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1158   0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1159   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1160};
1161#endif
1162
1163enum {
1164   GB_LCD_STATE_LYXX_M3=1,
1165   GB_LCD_STATE_LYXX_PRE_M0,
1166   GB_LCD_STATE_LYXX_M0,
1167   GB_LCD_STATE_LYXX_M0_SCX3,
1168   GB_LCD_STATE_LYXX_M0_GBC_PAL,
1169   GB_LCD_STATE_LYXX_M0_PRE_INC,
1170   GB_LCD_STATE_LYXX_M0_INC,
1171   GB_LCD_STATE_LY00_M2,
1172   GB_LCD_STATE_LYXX_M2,
1173   GB_LCD_STATE_LY9X_M1,
1174   GB_LCD_STATE_LY9X_M1_INC,
1175   GB_LCD_STATE_LY00_M1,
1176   GB_LCD_STATE_LY00_M1_1,
1177   GB_LCD_STATE_LY00_M1_2,
1178   GB_LCD_STATE_LY00_M0
1179};
1180
1181TIMER_CALLBACK_MEMBER(gb_state::gb_video_init_vbl)
1478TIMER_CALLBACK_MEMBER(gb_lcd_device::video_init_vbl)
11821479{
1183   m_maincpu->set_input_line(VBL_INT, ASSERT_LINE );
1480   m_maincpu->set_input_line(VBL_INT, ASSERT_LINE);
11841481}
11851482
1186void gb_state::gb_videoptr_restore()
1483UINT32 gb_lcd_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
11871484{
1188   m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
1189   m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
1190   m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
1191   m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
1192}
1193
1194void gb_state::gbc_videoptr_restore()
1195{
1196   m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
1197   m_lcd.layer[0].gbc_map = m_lcd.gb_vram + m_lcd.gbc_bgdtab_offs;
1198   m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
1199   m_lcd.layer[1].gbc_map = m_lcd.gb_vram + m_lcd.gbc_wndtab_offs;
1200}
1201
1202void gb_state::save_gb_video()
1203{
1204   save_item(NAME(m_lcd.window_lines_drawn));
1205   save_item(NAME(m_lcd.gb_vid_regs));
1206   save_item(NAME(m_lcd.bg_zbuf));
1207
1208   save_item(NAME(m_lcd.cgb_bpal));
1209   save_item(NAME(m_lcd.cgb_spal));
1210
1211   save_item(NAME(m_lcd.gb_bpal));
1212   save_item(NAME(m_lcd.gb_spal0));
1213   save_item(NAME(m_lcd.gb_spal1));
1214
1215   save_item(NAME(m_lcd.current_line));
1216   save_item(NAME(m_lcd.cmp_line));
1217   save_item(NAME(m_lcd.sprCount));
1218   save_item(NAME(m_lcd.sprite));
1219   save_item(NAME(m_lcd.previous_line));
1220   save_item(NAME(m_lcd.start_x));
1221   save_item(NAME(m_lcd.end_x));
1222   save_item(NAME(m_lcd.mode));
1223   save_item(NAME(m_lcd.state));
1224   save_item(NAME(m_lcd.lcd_irq_line));
1225   save_item(NAME(m_lcd.triggering_line_irq));
1226   save_item(NAME(m_lcd.line_irq));
1227   save_item(NAME(m_lcd.triggering_mode_irq));
1228   save_item(NAME(m_lcd.mode_irq));
1229   save_item(NAME(m_lcd.delayed_line_irq));
1230   save_item(NAME(m_lcd.sprite_cycles));
1231   save_item(NAME(m_lcd.scrollx_adjust));
1232   save_item(NAME(m_lcd.oam_locked));
1233   save_item(NAME(m_lcd.vram_locked));
1234   save_item(NAME(m_lcd.pal_locked));
1235   save_item(NAME(m_lcd.hdma_enabled));
1236   save_item(NAME(m_lcd.hdma_possible));
1237   save_item(NAME(m_lcd.gbc_mode));
1238   save_item(NAME(m_lcd.gb_tile_no_mod));
1239   save_item(NAME(m_lcd.gb_vram_bank));
1240
1241   save_item(NAME(m_lcd.gb_chrgen_offs));
1242   save_item(NAME(m_lcd.gb_bgdtab_offs));
1243   save_item(NAME(m_lcd.gb_wndtab_offs));
1244   save_item(NAME(m_lcd.gbc_chrgen_offs));
1245   save_item(NAME(m_lcd.gbc_bgdtab_offs));
1246   save_item(NAME(m_lcd.gbc_wndtab_offs));
1247
1248   save_item(NAME(m_lcd.layer[0].enabled));
1249   save_item(NAME(m_lcd.layer[0].xindex));
1250   save_item(NAME(m_lcd.layer[0].xshift));
1251   save_item(NAME(m_lcd.layer[0].xstart));
1252   save_item(NAME(m_lcd.layer[0].xend));
1253   save_item(NAME(m_lcd.layer[0].bgline));
1254   save_item(NAME(m_lcd.layer[1].enabled));
1255   save_item(NAME(m_lcd.layer[1].xindex));
1256   save_item(NAME(m_lcd.layer[1].xshift));
1257   save_item(NAME(m_lcd.layer[1].xstart));
1258   save_item(NAME(m_lcd.layer[1].xend));
1259   save_item(NAME(m_lcd.layer[1].bgline));
1260}
1261
1262void gb_state::gb_video_start( int mode )
1263{
1264   int vram_size = (mode == GB_VIDEO_CGB) ? 0x4000 : 0x2000;
1265
1266   machine().primary_screen->register_screen_bitmap(m_bitmap);
1267   m_lcd.gb_vram = auto_alloc_array_clear(machine(), UINT8, vram_size);
1268   m_lcd.gb_oam = auto_alloc_array_clear(machine(), UINT8, 0x100);
1269
1270   save_pointer(NAME(m_lcd.gb_vram), vram_size);
1271   save_pointer(NAME(m_lcd.gb_oam), 0x100);
1272   save_gb_video();
1273
1274   if (mode == GB_VIDEO_CGB)
1275   {
1276      m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gbc_lcd_timer_proc),this));
1277      machine().save().register_postload(save_prepost_delegate(FUNC(gb_state::gbc_videoptr_restore), this));
1278   }
1279   else
1280   {
1281      m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_lcd_timer_proc),this));
1282      machine().save().register_postload(save_prepost_delegate(FUNC(gb_state::gb_videoptr_restore), this));
1283   }
1284
1285   switch (mode)
1286   {
1287      case GB_VIDEO_DMG:
1288         memcpy(m_lcd.gb_oam, dmg_oam_fingerprint, 0x100);
1289         break;
1290      case GB_VIDEO_MGB:
1291         /* Initialize part of VRAM. This code must be deleted when we have added the bios dump */
1292         for (int i = 1; i < 0x0d; i++)
1293         {
1294            m_lcd.gb_vram[0x1903 + i] = i;
1295            m_lcd.gb_vram[0x1923 + i] = i + 0x0C;
1296         }
1297         m_lcd.gb_vram[0x1910] = 0x19;
1298         memcpy(m_lcd.gb_oam, mgb_oam_fingerprint, 0x100);
1299         break;
1300      case GB_VIDEO_SGB:
1301         break;
1302      case GB_VIDEO_CGB:
1303         memcpy(m_lcd.gb_oam, cgb_oam_fingerprint, 0x100);
1304         break;
1305   }
1306}
1307
1308
1309UINT32 gb_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
1310{
13111485   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
13121486   return 0;
13131487}
13141488
1315void gb_state::gb_video_reset( int mode )
1316{
1317   address_space &space = m_maincpu->space(AS_PROGRAM);
13181489
1319   m_lcd.window_lines_drawn = 0;
1320
1321   m_lcd.current_line = 0;
1322   m_lcd.cmp_line = 0;
1323   m_lcd.sprCount = 0;
1324   m_lcd.previous_line = 0;
1325   m_lcd.start_x = 0;
1326   m_lcd.end_x = 0;
1327   m_lcd.mode = 0;
1328   m_lcd.state = 0;
1329   m_lcd.lcd_irq_line = 0;
1330   m_lcd.triggering_line_irq = 0;
1331   m_lcd.line_irq = 0;
1332   m_lcd.triggering_mode_irq = 0;
1333   m_lcd.mode_irq = 0;
1334   m_lcd.delayed_line_irq = 0;
1335   m_lcd.sprite_cycles = 0;
1336   m_lcd.scrollx_adjust = 0;
1337   m_lcd.oam_locked = 0;
1338   m_lcd.vram_locked = 0;
1339   m_lcd.pal_locked = 0;
1340   m_lcd.gbc_mode = 0;
1341   m_lcd.gb_tile_no_mod = 0;
1342   m_lcd.gb_vram_bank = 0;
1343
1344   m_lcd.gb_chrgen_offs = 0;
1345   m_lcd.gb_bgdtab_offs = 0x1c00;
1346   m_lcd.gb_wndtab_offs = 0x1c00;
1347
1348   memset(&m_lcd.gb_vid_regs, 0, sizeof(m_lcd.gb_vid_regs));
1349   memset(&m_lcd.bg_zbuf, 0, sizeof(m_lcd.bg_zbuf));
1350   memset(&m_lcd.cgb_bpal, 0, sizeof(m_lcd.cgb_bpal));
1351   memset(&m_lcd.cgb_spal, 0, sizeof(m_lcd.cgb_spal));
1352   memset(&m_lcd.sprite, 0, sizeof(m_lcd.sprite));
1353   memset(&m_lcd.layer[0], 0, sizeof(m_lcd.layer[0]));
1354   memset(&m_lcd.layer[1], 0, sizeof(m_lcd.layer[1]));
1355
1356   // specific reg initialization
1357   m_lcd.gb_vid_regs[0x06] = 0xff;
1358
1359   for (int i = 0x0c; i < _NR_GB_VID_REGS; i++)
1360      m_lcd.gb_vid_regs[i] = 0xff;
1361
1362   LCDSTAT = 0x80;
1363   LCDCONT = 0x00;     /* Video hardware is turned off at boot time */
1364   m_lcd.current_line = CURLINE = CMPLINE = 0x00;
1365   SCROLLX = SCROLLY = 0x00;
1366   SPR0PAL = SPR1PAL = 0xFF;
1367   WNDPOSX = WNDPOSY = 0x00;
1368
1369   // Initialize palette arrays
1370   for (int i = 0; i < 4; i++)
1371      m_lcd.gb_bpal[i] = m_lcd.gb_spal0[i] = m_lcd.gb_spal1[i] = i;
1372
1373   switch( mode )
1374   {
1375   case GB_VIDEO_DMG:
1376      m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
1377
1378      /* set the scanline update function */
1379      update_scanline = &gb_state::gb_update_scanline;
1380      break;
1381
1382   case GB_VIDEO_MGB:
1383      /* set the scanline update function */
1384      update_scanline = &gb_state::gb_update_scanline;
1385      /* Make sure the VBlank interrupt is set when the first instruction gets executed */
1386      machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(1), timer_expired_delegate(FUNC(gb_state::gb_video_init_vbl),this));
1387
1388      /* Initialize some video registers */
1389      gb_video_w(space, 0x0, 0x91);    /* LCDCONT */
1390      gb_video_w(space, 0x7, 0xFC);    /* BGRDPAL */
1391      gb_video_w(space, 0x8, 0xFC);    /* SPR0PAL */
1392      gb_video_w(space, 0x9, 0xFC);    /* SPR1PAL */
1393
1394      CURLINE = m_lcd.current_line = 0;
1395      LCDSTAT = ( LCDSTAT & 0xF8 ) | 0x05;
1396      m_lcd.mode = 1;
1397      m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(60), GB_LCD_STATE_LY00_M0);
1398      break;
1399
1400   case GB_VIDEO_SGB:
1401      /* set the scanline update function */
1402      update_scanline = &gb_state::sgb_update_scanline;
1403      break;
1404
1405   case GB_VIDEO_CGB:
1406      /* set the scanline update function */
1407      update_scanline = &gb_state::cgb_update_scanline;
1408
1409      m_lcd.gbc_chrgen_offs = 0x2000;
1410      m_lcd.gbc_bgdtab_offs = 0x3c00;
1411      m_lcd.gbc_wndtab_offs = 0x3c00;
1412
1413      /* HDMA disabled */
1414      m_lcd.hdma_enabled = 0;
1415      m_lcd.hdma_possible = 0;
1416
1417      m_lcd.gbc_mode = 1;
1418      break;
1419   }
1420}
1421
1422
1423void gb_state::gbc_hdma(UINT16 length)
1490void gb_lcd_device::increment_scanline()
14241491{
1425   UINT16 src, dst;
1426   address_space &space = m_maincpu->space(AS_PROGRAM);
1427
1428   src = ((UINT16)HDMA1 << 8) | (HDMA2 & 0xF0);
1429   dst = ((UINT16)(HDMA3 & 0x1F) << 8) | (HDMA4 & 0xF0);
1430   dst |= 0x8000;
1431   while( length > 0 )
1492   m_current_line = (m_current_line + 1) % 154;
1493   if (LCDCONT & 0x80)
14321494   {
1433      space.write_byte( dst++, space.read_byte( src++ ) );
1434      length--;
1495      CURLINE = m_current_line;
14351496   }
1436   HDMA1 = src >> 8;
1437   HDMA2 = src & 0xF0;
1438   HDMA3 = 0x1f & (dst >> 8);
1439   HDMA4 = dst & 0xF0;
1440   HDMA5--;
1441   if( (HDMA5 & 0x7f) == 0x7f )
1497   if (m_current_line == 0)
14421498   {
1443      HDMA5 = 0xff;
1444      m_lcd.hdma_enabled = 0;
1499      m_window_lines_drawn = 0;
14451500   }
14461501}
14471502
1448
1449void gb_state::gb_increment_scanline()
1503TIMER_CALLBACK_MEMBER(gb_lcd_device::lcd_timer_proc)
14501504{
1451   m_lcd.current_line = ( m_lcd.current_line + 1 ) % 154;
1452   if ( LCDCONT & 0x80 )
1453   {
1454      CURLINE = m_lcd.current_line;
1455   }
1456   if ( m_lcd.current_line == 0 )
1457   {
1458      m_lcd.window_lines_drawn = 0;
1459   }
1460}
1461
1462TIMER_CALLBACK_MEMBER(gb_state::gb_lcd_timer_proc)
1463{
14641505   static const int sprite_cycles[] = { 0, 8, 20, 32, 44, 52, 64, 76, 88, 96, 108 };
14651506
1466   m_lcd.state = param;
1507   m_state = param;
14671508
1468   if ( LCDCONT & 0x80 )
1509   if (LCDCONT & 0x80)
14691510   {
1470      switch( m_lcd.state )
1511      switch (m_state)
14711512      {
14721513      case GB_LCD_STATE_LYXX_PRE_M0:  /* Just before switching to mode 0 */
1473         m_lcd.mode = 0;
1474         if ( LCDSTAT & 0x08 )
1514         m_mode = 0;
1515         if (LCDSTAT & 0x08)
14751516         {
1476            if ( ! m_lcd.mode_irq )
1517            if (!m_mode_irq)
14771518            {
1478               if ( ! m_lcd.line_irq && ! m_lcd.delayed_line_irq )
1519               if (!m_line_irq && !m_delayed_line_irq)
14791520               {
1480                  m_lcd.mode_irq = 1;
1481                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1521                  m_mode_irq = 1;
1522                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
14821523               }
14831524            }
14841525            else
14851526            {
1486               m_lcd.mode_irq = 0;
1527               m_mode_irq = 0;
14871528            }
14881529         }
1489         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0);
1530         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0);
14901531         break;
14911532      case GB_LCD_STATE_LYXX_M0:      /* Switch to mode 0 */
14921533         /* update current scanline */
1493         (this->*update_scanline)();
1534         update_scanline();
14941535         /* Increment the number of window lines drawn if enabled */
1495         if ( m_lcd.layer[1].enabled )
1536         if (m_layer[1].enabled)
14961537         {
1497            m_lcd.window_lines_drawn++;
1538            m_window_lines_drawn++;
14981539         }
1499         m_lcd.previous_line = m_lcd.current_line;
1540         m_previous_line = m_current_line;
15001541         /* Set Mode 0 lcdstate */
1501         m_lcd.mode = 0;
1542         m_mode = 0;
15021543         LCDSTAT &= 0xFC;
1503         m_lcd.oam_locked = UNLOCKED;
1504         m_lcd.vram_locked = UNLOCKED;
1544         m_oam_locked = UNLOCKED;
1545         m_vram_locked = UNLOCKED;
15051546         /*
15061547             There seems to a kind of feature in the Game Boy hardware when the lowest bits of the
15071548             SCROLLX register equals 3 or 7, then the delayed M0 irq is triggered 4 cycles later
15081549             than usual.
15091550             The SGB probably has the same bug.
15101551         */
1511         if ( ( SCROLLX & 0x03 ) == 0x03 )
1552         if ((SCROLLX & 0x03) == 0x03)
15121553         {
1513            m_lcd.scrollx_adjust += 4;
1514            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_SCX3);
1554            m_scrollx_adjust += 4;
1555            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_SCX3);
15151556            break;
15161557         }
15171558      case GB_LCD_STATE_LYXX_M0_SCX3:
15181559         /* Generate lcd interrupt if requested */
1519         if ( ! m_lcd.mode_irq && ( LCDSTAT & 0x08 ) &&
1520               ( ( ! m_lcd.line_irq && m_lcd.delayed_line_irq ) || ! ( LCDSTAT & 0x40 ) ) )
1560         if (!m_mode_irq && (LCDSTAT & 0x08) &&
1561               ((!m_line_irq && m_delayed_line_irq) || !(LCDSTAT & 0x40)))
15211562         {
1522            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1563            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
15231564         }
1524         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(196 - m_lcd.scrollx_adjust - m_lcd.sprite_cycles), GB_LCD_STATE_LYXX_M0_PRE_INC);
1565         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(196 - m_scrollx_adjust - m_sprite_cycles), GB_LCD_STATE_LYXX_M0_PRE_INC);
15251566         break;
15261567      case GB_LCD_STATE_LYXX_M0_PRE_INC:  /* Just before incrementing the line counter go to mode 2 internally */
1527         if ( CURLINE < 143 )
1568         if (CURLINE < 143)
15281569         {
1529            m_lcd.mode = 2;
1530            m_lcd.triggering_mode_irq = ( LCDSTAT & 0x20 ) ? 1 : 0;
1531            if ( m_lcd.triggering_mode_irq )
1570            m_mode = 2;
1571            m_triggering_mode_irq = (LCDSTAT & 0x20) ? 1 : 0;
1572            if (m_triggering_mode_irq)
15321573            {
1533               if ( ! m_lcd.mode_irq )
1574               if (!m_mode_irq)
15341575               {
1535                  if ( ! m_lcd.line_irq && ! m_lcd.delayed_line_irq )
1576                  if (!m_line_irq && !m_delayed_line_irq)
15361577                  {
1537                     m_lcd.mode_irq = 1;
1538                     m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1578                     m_mode_irq = 1;
1579                     m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
15391580                  }
15401581               }
15411582               else
15421583               {
1543                  m_lcd.mode_irq = 0;
1584                  m_mode_irq = 0;
15441585               }
15451586            }
15461587         }
1547         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_INC);
1588         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_INC);
15481589         break;
15491590      case GB_LCD_STATE_LYXX_M0_INC:  /* Increment LY, stay in M0 for 4 more cycles */
1550         gb_increment_scanline();
1551         m_lcd.delayed_line_irq = m_lcd.line_irq;
1552         m_lcd.triggering_line_irq = ( ( CMPLINE == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1553         m_lcd.line_irq = 0;
1554         if ( ! m_lcd.mode_irq && ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq && ! m_lcd.triggering_mode_irq )
1591         increment_scanline();
1592         m_delayed_line_irq = m_line_irq;
1593         m_triggering_line_irq = ((CMPLINE == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
1594         m_line_irq = 0;
1595         if (!m_mode_irq && !m_delayed_line_irq && m_triggering_line_irq && !m_triggering_mode_irq)
15551596         {
1556            m_lcd.line_irq = m_lcd.triggering_line_irq;
1557            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1597            m_line_irq = m_triggering_line_irq;
1598            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
15581599         }
15591600         /* Reset LY==LYC STAT bit */
15601601         LCDSTAT &= 0xFB;
15611602         /* Check if we're going into VBlank next */
1562         if ( CURLINE == 144 )
1603         if (CURLINE == 144)
15631604         {
1564            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
1605            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
15651606         }
15661607         else
15671608         {
15681609            /* Internally switch to mode 2 */
1569            m_lcd.mode = 2;
1610            m_mode = 2;
15701611            /* Generate lcd interrupt if requested */
1571            if ( ! m_lcd.mode_irq && m_lcd.triggering_mode_irq &&
1572                  ( ( ! m_lcd.triggering_line_irq && ! m_lcd.delayed_line_irq ) || ! ( LCDSTAT & 0x40 ) ) )
1612            if (!m_mode_irq && m_triggering_mode_irq &&
1613                  ((!m_triggering_line_irq && !m_delayed_line_irq) || !(LCDSTAT & 0x40)))
15731614            {
1574               m_lcd.mode_irq = 1;
1575               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1615               m_mode_irq = 1;
1616               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
15761617            }
1577            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M2);
1618            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M2);
15781619         }
15791620         break;
15801621      case GB_LCD_STATE_LY00_M2:      /* Switch to mode 2 on line #0 */
15811622         /* Set Mode 2 lcdstate */
1582         m_lcd.mode = 2;
1583         LCDSTAT = ( LCDSTAT & 0xFC ) | 0x02;
1584         m_lcd.oam_locked = LOCKED;
1623         m_mode = 2;
1624         LCDSTAT = (LCDSTAT & 0xFC) | 0x02;
1625         m_oam_locked = LOCKED;
15851626         /* Generate lcd interrupt if requested */
1586         if ( ( LCDSTAT & 0x20 ) && ! m_lcd.line_irq )
1627         if ((LCDSTAT & 0x20) && !m_line_irq)
15871628         {
1588            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1629            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
15891630         }
15901631         /* Check for regular compensation of x-scroll register */
1591         m_lcd.scrollx_adjust = ( SCROLLX & 0x04 ) ? 4 : 0;
1632         m_scrollx_adjust = (SCROLLX & 0x04) ? 4 : 0;
15921633         /* Mode 2 lasts approximately 80 clock cycles */
1593         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
1634         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
15941635         break;
15951636      case GB_LCD_STATE_LYXX_M2:      /* Switch to mode 2 */
15961637         /* Update STAT register to the correct state */
15971638         LCDSTAT = (LCDSTAT & 0xFC) | 0x02;
1598         m_lcd.oam_locked = LOCKED;
1639         m_oam_locked = LOCKED;
15991640         /* Generate lcd interrupt if requested */
1600         if ( ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq && ! ( LCDSTAT & 0x20 ) ) ||
1601               ( ! m_lcd.mode_irq && ! m_lcd.line_irq && ! m_lcd.delayed_line_irq && m_lcd.triggering_mode_irq ) )
1641         if ((m_delayed_line_irq && m_triggering_line_irq && !(LCDSTAT & 0x20)) ||
1642               (!m_mode_irq && !m_line_irq && !m_delayed_line_irq && m_triggering_mode_irq))
16021643         {
1603            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1644            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
16041645         }
1605         m_lcd.line_irq = m_lcd.triggering_line_irq;
1606         m_lcd.triggering_mode_irq = 0;
1646         m_line_irq = m_triggering_line_irq;
1647         m_triggering_mode_irq = 0;
16071648         /* Check if LY==LYC STAT bit should be set */
1608         if ( CURLINE == CMPLINE )
1649         if (CURLINE == CMPLINE)
16091650         {
16101651            LCDSTAT |= 0x04;
16111652         }
16121653         /* Check for regular compensation of x-scroll register */
1613         m_lcd.scrollx_adjust = ( SCROLLX & 0x04 ) ? 4 : 0;
1654         m_scrollx_adjust = (SCROLLX & 0x04) ? 4 : 0;
16141655         /* Mode 2 last for approximately 80 clock cycles */
1615         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
1656         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
16161657         break;
16171658      case GB_LCD_STATE_LYXX_M3:      /* Switch to mode 3 */
1618         gb_select_sprites();
1619         m_lcd.sprite_cycles = sprite_cycles[ m_lcd.sprCount ];
1659         select_sprites();
1660         m_sprite_cycles = sprite_cycles[m_sprCount];
16201661         /* Set Mode 3 lcdstate */
1621         m_lcd.mode = 3;
1662         m_mode = 3;
16221663         LCDSTAT = (LCDSTAT & 0xFC) | 0x03;
1623         m_lcd.vram_locked = LOCKED;
1664         m_vram_locked = LOCKED;
16241665         /* Check for compensations of x-scroll register */
16251666         /* Mode 3 lasts for approximately 172+cycles needed to handle sprites clock cycles */
1626         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(168 + m_lcd.scrollx_adjust + m_lcd.sprite_cycles), GB_LCD_STATE_LYXX_PRE_M0);
1627         m_lcd.start_x = -1;
1667         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(168 + m_scrollx_adjust + m_sprite_cycles), GB_LCD_STATE_LYXX_PRE_M0);
1668         m_start_x = -1;
16281669         break;
16291670      case GB_LCD_STATE_LY9X_M1:      /* Switch to or stay in mode 1 */
1630         if ( CURLINE == 144 )
1671         if (CURLINE == 144)
16311672         {
16321673            /* Trigger VBlank interrupt */
1633            m_maincpu->set_input_line(VBL_INT, ASSERT_LINE );
1674            m_maincpu->set_input_line(VBL_INT, ASSERT_LINE);
16341675            /* Set VBlank lcdstate */
1635            m_lcd.mode = 1;
1676            m_mode = 1;
16361677            LCDSTAT = (LCDSTAT & 0xFC) | 0x01;
16371678            /* Trigger LCD interrupt if requested */
1638            if ( LCDSTAT & 0x10 )
1679            if (LCDSTAT & 0x10)
16391680            {
1640               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1681               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
16411682            }
16421683         }
16431684         /* Check if LY==LYC STAT bit should be set */
1644         if ( CURLINE == CMPLINE )
1685         if (CURLINE == CMPLINE)
16451686         {
16461687            LCDSTAT |= 0x04;
16471688         }
1648         if ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
1689         if (m_delayed_line_irq && m_triggering_line_irq)
16491690         {
1650            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1691            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
16511692         }
1652         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(452), GB_LCD_STATE_LY9X_M1_INC);
1693         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(452), GB_LCD_STATE_LY9X_M1_INC);
16531694         break;
16541695      case GB_LCD_STATE_LY9X_M1_INC:      /* Increment scanline counter */
1655         gb_increment_scanline();
1656         m_lcd.delayed_line_irq = m_lcd.line_irq;
1657         m_lcd.triggering_line_irq = ( ( CMPLINE == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1658         m_lcd.line_irq = 0;
1659         if ( ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
1696         increment_scanline();
1697         m_delayed_line_irq = m_line_irq;
1698         m_triggering_line_irq = ((CMPLINE == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
1699         m_line_irq = 0;
1700         if (!m_delayed_line_irq && m_triggering_line_irq)
16601701         {
1661            m_lcd.line_irq = m_lcd.triggering_line_irq;
1662            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1702            m_line_irq = m_triggering_line_irq;
1703            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
16631704         }
16641705         /* Reset LY==LYC STAT bit */
16651706         LCDSTAT &= 0xFB;
1666         if ( m_lcd.current_line == 153 )
1707         if (m_current_line == 153)
16671708         {
1668            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1);
1709            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1);
16691710         }
16701711         else
16711712         {
1672            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
1713            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
16731714         }
16741715         break;
16751716      case GB_LCD_STATE_LY00_M1:      /* we stay in VBlank but current line counter should already be incremented */
16761717         /* Check LY=LYC for line #153 */
1677         if ( m_lcd.delayed_line_irq )
1718         if (m_delayed_line_irq)
16781719         {
1679            if ( m_lcd.triggering_line_irq )
1720            if (m_triggering_line_irq)
16801721            {
1681               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1722               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
16821723            }
16831724         }
1684         m_lcd.delayed_line_irq = m_lcd.delayed_line_irq | m_lcd.line_irq;
1685         if ( CURLINE == CMPLINE )
1725         m_delayed_line_irq = m_delayed_line_irq | m_line_irq;
1726         if (CURLINE == CMPLINE)
16861727         {
16871728            LCDSTAT |= 0x04;
16881729         }
1689         gb_increment_scanline();
1690         m_lcd.triggering_line_irq = ( ( CMPLINE == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1691         m_lcd.line_irq = 0;
1730         increment_scanline();
1731         m_triggering_line_irq = ((CMPLINE == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
1732         m_line_irq = 0;
16921733         LCDSTAT &= 0xFB;
1693         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4/*8*/), GB_LCD_STATE_LY00_M1_1);
1734         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4/*8*/), GB_LCD_STATE_LY00_M1_1);
16941735         break;
16951736      case GB_LCD_STATE_LY00_M1_1:
1696         if ( ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
1737         if (!m_delayed_line_irq && m_triggering_line_irq)
16971738         {
1698            m_lcd.line_irq = m_lcd.triggering_line_irq;
1699            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1739            m_line_irq = m_triggering_line_irq;
1740            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
17001741         }
1701         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_2);
1742         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_2);
17021743         break;
17031744      case GB_LCD_STATE_LY00_M1_2:    /* Rest of line #0 during VBlank */
1704         if ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
1745         if (m_delayed_line_irq && m_triggering_line_irq)
17051746         {
1706            m_lcd.line_irq = m_lcd.triggering_line_irq;
1707            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1747            m_line_irq = m_triggering_line_irq;
1748            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
17081749         }
1709         if ( CURLINE == CMPLINE )
1750         if (CURLINE == CMPLINE)
17101751         {
17111752            LCDSTAT |= 0x04;
17121753         }
1713         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(444), GB_LCD_STATE_LY00_M0);
1754         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(444), GB_LCD_STATE_LY00_M0);
17141755         break;
17151756      case GB_LCD_STATE_LY00_M0:      /* The STAT register seems to go to 0 for about 4 cycles */
17161757         /* Set Mode 0 lcdstat */
1717         m_lcd.mode = 0;
1718         LCDSTAT = ( LCDSTAT & 0xFC );
1719         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M2);
1758         m_mode = 0;
1759         LCDSTAT = (LCDSTAT & 0xFC);
1760         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M2);
17201761         break;
17211762      }
17221763   }
17231764   else
17241765   {
1725      gb_increment_scanline();
1726      if ( m_lcd.current_line < 144 )
1766      increment_scanline();
1767      if (m_current_line < 144)
17271768      {
1728         (this->*update_scanline)();
1769         update_scanline();
17291770      }
1730      m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
1771      m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
17311772   }
17321773}
17331774
1734TIMER_CALLBACK_MEMBER(gb_state::gbc_lcd_timer_proc)
1775
1776// CGB specific code
1777
1778void cgb_lcd_device::hdma_trans(UINT16 length)
17351779{
1780   UINT16 src, dst;
1781   address_space &space = m_maincpu->space(AS_PROGRAM);
1782   
1783   src = ((UINT16)HDMA1 << 8) | (HDMA2 & 0xF0);
1784   dst = ((UINT16)(HDMA3 & 0x1F) << 8) | (HDMA4 & 0xF0);
1785   dst |= 0x8000;
1786   while (length > 0)
1787   {
1788      space.write_byte(dst++, space.read_byte(src++));
1789      length--;
1790   }
1791   HDMA1 = src >> 8;
1792   HDMA2 = src & 0xF0;
1793   HDMA3 = 0x1f & (dst >> 8);
1794   HDMA4 = dst & 0xF0;
1795   HDMA5--;
1796   if ((HDMA5 & 0x7f) == 0x7f)
1797   {
1798      HDMA5 = 0xff;
1799      m_hdma_enabled = 0;
1800   }
1801}
1802
1803
1804TIMER_CALLBACK_MEMBER(cgb_lcd_device::lcd_timer_proc)
1805{
17361806   static const int sprite_cycles[] = { 0, 8, 20, 32, 44, 52, 64, 76, 88, 96, 108 };
17371807
1738   m_lcd.state = param;
1808   m_state = param;
17391809
1740   if ( LCDCONT & 0x80 )
1810   if (LCDCONT & 0x80)
17411811   {
1742      switch( m_lcd.state )
1812      switch (m_state)
17431813      {
17441814      case GB_LCD_STATE_LYXX_PRE_M0:  /* Just before switching to mode 0 */
1745         m_lcd.mode = 0;
1746         if ( LCDSTAT & 0x08 )
1815         m_mode = 0;
1816         if (LCDSTAT & 0x08)
17471817         {
1748            if ( ! m_lcd.mode_irq )
1818            if (!m_mode_irq)
17491819            {
1750               if ( ! m_lcd.line_irq && ! m_lcd.delayed_line_irq )
1820               if (!m_line_irq && !m_delayed_line_irq)
17511821               {
1752                  m_lcd.mode_irq = 1;
1753                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1822                  m_mode_irq = 1;
1823                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
17541824               }
17551825            }
17561826            else
17571827            {
1758               m_lcd.mode_irq = 0;
1828               m_mode_irq = 0;
17591829            }
17601830         }
1761         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0);
1831         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0);
17621832         break;
17631833      case GB_LCD_STATE_LYXX_M0:      /* Switch to mode 0 */
17641834         /* update current scanline */
1765         (this->*update_scanline)();
1835         update_scanline();
17661836         /* Increment the number of window lines drawn if enabled */
1767         if ( m_lcd.layer[1].enabled )
1837         if (m_layer[1].enabled)
17681838         {
1769            m_lcd.window_lines_drawn++;
1839            m_window_lines_drawn++;
17701840         }
1771         m_lcd.previous_line = m_lcd.current_line;
1841         m_previous_line = m_current_line;
17721842         /* Set Mode 0 lcdstate */
1773         m_lcd.mode = 0;
1843         m_mode = 0;
17741844         LCDSTAT &= 0xFC;
1775         m_lcd.oam_locked = UNLOCKED;
1776         m_lcd.vram_locked = UNLOCKED;
1845         m_oam_locked = UNLOCKED;
1846         m_vram_locked = UNLOCKED;
17771847         /*
17781848             There seems to a kind of feature in the Game Boy hardware when the lowest bits of the
17791849             SCROLLX register equals 3 or 7, then the delayed M0 irq is triggered 4 cycles later
17801850             than usual.
17811851             The SGB probably has the same bug.
17821852         */
1783         m_lcd.triggering_mode_irq = ( LCDSTAT & 0x08 ) ? 1 : 0;
1784         if ( ( SCROLLX & 0x03 ) == 0x03 )
1853         m_triggering_mode_irq = (LCDSTAT & 0x08) ? 1 : 0;
1854         if ((SCROLLX & 0x03) == 0x03)
17851855         {
1786            m_lcd.scrollx_adjust += 4;
1787            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_SCX3);
1856            m_scrollx_adjust += 4;
1857            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_SCX3);
17881858            break;
17891859         }
17901860      case GB_LCD_STATE_LYXX_M0_SCX3:
17911861         /* Generate lcd interrupt if requested */
1792         if ( ! m_lcd.mode_irq && m_lcd.triggering_mode_irq &&
1793               ( ( ! m_lcd.line_irq && m_lcd.delayed_line_irq ) || ! ( LCDSTAT & 0x40 ) ) )
1862         if (!m_mode_irq && m_triggering_mode_irq &&
1863               ((!m_line_irq && m_delayed_line_irq) || !(LCDSTAT & 0x40)))
17941864         {
1795            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1796            m_lcd.triggering_mode_irq = 0;
1865            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
1866            m_triggering_mode_irq = 0;
17971867         }
1798         if ( ( SCROLLX & 0x03 ) == 0x03 )
1868         if ((SCROLLX & 0x03) == 0x03)
17991869         {
1800            m_lcd.pal_locked = UNLOCKED;
1870            m_pal_locked = UNLOCKED;
18011871         }
1802         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_GBC_PAL);
1872         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_GBC_PAL);
18031873         break;
18041874      case GB_LCD_STATE_LYXX_M0_GBC_PAL:
1805         m_lcd.pal_locked = UNLOCKED;
1875         m_pal_locked = UNLOCKED;
18061876         /* Check for HBLANK DMA */
1807         if( m_lcd.hdma_enabled )
1877         if (m_hdma_enabled)
18081878         {
1809            gbc_hdma(0x10);
1810//              cpunum_set_reg( 0, LR35902_DMA_CYCLES, 36 );
1879            hdma_trans(0x10);
1880//              cpunum_set_reg(0, LR35902_DMA_CYCLES, 36);
18111881         }
18121882         else
18131883         {
1814            m_lcd.hdma_possible = 1;
1884            m_hdma_possible = 1;
18151885         }
1816         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(192 - m_lcd.scrollx_adjust - m_lcd.sprite_cycles), GB_LCD_STATE_LYXX_M0_PRE_INC);
1886         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(192 - m_scrollx_adjust - m_sprite_cycles), GB_LCD_STATE_LYXX_M0_PRE_INC);
18171887         break;
18181888      case GB_LCD_STATE_LYXX_M0_PRE_INC:  /* Just before incrementing the line counter go to mode 2 internally */
1819         m_lcd.cmp_line = CMPLINE;
1820         if ( CURLINE < 143 )
1889         m_cmp_line = CMPLINE;
1890         if (CURLINE < 143)
18211891         {
1822            m_lcd.mode = 2;
1823            if ( LCDSTAT & 0x20 )
1892            m_mode = 2;
1893            if (LCDSTAT & 0x20)
18241894            {
1825               if ( ! m_lcd.mode_irq )
1895               if (!m_mode_irq)
18261896               {
1827                  if ( ! m_lcd.line_irq && ! m_lcd.delayed_line_irq )
1897                  if (!m_line_irq && !m_delayed_line_irq)
18281898                  {
1829                     m_lcd.mode_irq = 1;
1830                     m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1899                     m_mode_irq = 1;
1900                     m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
18311901                  }
18321902               }
18331903               else
18341904               {
1835                  m_lcd.mode_irq = 0;
1905                  m_mode_irq = 0;
18361906               }
18371907            }
18381908         }
1839         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_INC);
1909         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M0_INC);
18401910         break;
18411911      case GB_LCD_STATE_LYXX_M0_INC:  /* Increment LY, stay in M0 for 4 more cycles */
1842         gb_increment_scanline();
1843         m_lcd.delayed_line_irq = m_lcd.line_irq;
1844         m_lcd.triggering_line_irq = ( ( m_lcd.cmp_line == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1845         m_lcd.line_irq = 0;
1846         if ( ! m_lcd.mode_irq && ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq && ! ( LCDSTAT & 0x20 ) )
1912         increment_scanline();
1913         m_delayed_line_irq = m_line_irq;
1914         m_triggering_line_irq = ((m_cmp_line == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
1915         m_line_irq = 0;
1916         if (!m_mode_irq && !m_delayed_line_irq && m_triggering_line_irq && !(LCDSTAT & 0x20))
18471917         {
1848            m_lcd.line_irq = m_lcd.triggering_line_irq;
1849            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1918            m_line_irq = m_triggering_line_irq;
1919            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
18501920         }
1851         m_lcd.hdma_possible = 0;
1921         m_hdma_possible = 0;
18521922         /* Check if we're going into VBlank next */
1853         if ( CURLINE == 144 )
1923         if (CURLINE == 144)
18541924         {
1855            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
1925            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
18561926         }
18571927         else
18581928         {
18591929            /* Internally switch to mode 2 */
1860            m_lcd.mode = 2;
1930            m_mode = 2;
18611931            /* Generate lcd interrupt if requested */
1862            if ( ! m_lcd.mode_irq && ( LCDSTAT & 0x20 ) &&
1863                  ( ( ! m_lcd.triggering_line_irq && ! m_lcd.delayed_line_irq ) || ! ( LCDSTAT & 0x40 ) ) )
1932            if (!m_mode_irq && (LCDSTAT & 0x20) &&
1933                  ((!m_triggering_line_irq && !m_delayed_line_irq) || !(LCDSTAT & 0x40)))
18641934            {
1865               m_lcd.mode_irq = 1;
1866               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1935               m_mode_irq = 1;
1936               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
18671937            }
1868            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M2);
1938            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LYXX_M2);
18691939         }
18701940         break;
18711941      case GB_LCD_STATE_LY00_M2:      /* Switch to mode 2 on line #0 */
18721942         /* Set Mode 2 lcdstate */
1873         m_lcd.mode = 2;
1874         LCDSTAT = ( LCDSTAT & 0xFC ) | 0x02;
1875         m_lcd.oam_locked = LOCKED;
1943         m_mode = 2;
1944         LCDSTAT = (LCDSTAT & 0xFC) | 0x02;
1945         m_oam_locked = LOCKED;
18761946         /* Generate lcd interrupt if requested */
1877         if ( ( LCDSTAT & 0x20 ) && ! m_lcd.line_irq )
1947         if ((LCDSTAT & 0x20) && ! m_line_irq)
18781948         {
1879            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1949            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
18801950         }
18811951         /* Check for regular compensation of x-scroll register */
1882         m_lcd.scrollx_adjust = ( SCROLLX & 0x04 ) ? 4 : 0;
1952         m_scrollx_adjust = (SCROLLX & 0x04) ? 4 : 0;
18831953         /* Mode 2 lasts approximately 80 clock cycles */
1884         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
1954         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
18851955         break;
18861956      case GB_LCD_STATE_LYXX_M2:      /* Switch to mode 2 */
18871957         /* Update STAT register to the correct state */
18881958         LCDSTAT = (LCDSTAT & 0xFC) | 0x02;
1889         m_lcd.oam_locked = LOCKED;
1959         m_oam_locked = LOCKED;
18901960         /* Generate lcd interrupt if requested */
1891         if ( ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq && ! ( LCDSTAT & 0x20 ) ) ||
1892               ( !m_lcd.mode_irq && ! m_lcd.line_irq && ! m_lcd.delayed_line_irq && ( LCDSTAT & 0x20 ) ) )
1961         if ((m_delayed_line_irq && m_triggering_line_irq && !(LCDSTAT & 0x20)) ||
1962               (!m_mode_irq && !m_line_irq && !m_delayed_line_irq && (LCDSTAT & 0x20)))
18931963         {
1894            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
1964            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
18951965         }
1896         m_lcd.line_irq = m_lcd.triggering_line_irq;
1966         m_line_irq = m_triggering_line_irq;
18971967         /* Check if LY==LYC STAT bit should be set */
1898         if ( CURLINE == CMPLINE )
1968         if (CURLINE == CMPLINE)
18991969         {
19001970            LCDSTAT |= 0x04;
19011971         }
r23879r23880
19041974            LCDSTAT &= ~0x04;
19051975         }
19061976         /* Check for regular compensation of x-scroll register */
1907         m_lcd.scrollx_adjust = ( SCROLLX & 0x04 ) ? 4 : 0;
1977         m_scrollx_adjust = (SCROLLX & 0x04) ? 4 : 0;
19081978         /* Mode 2 last for approximately 80 clock cycles */
1909         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
1979         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
19101980         break;
19111981      case GB_LCD_STATE_LYXX_M3:      /* Switch to mode 3 */
1912         gb_select_sprites();
1913         m_lcd.sprite_cycles = sprite_cycles[ m_lcd.sprCount ];
1982         select_sprites();
1983         m_sprite_cycles = sprite_cycles[m_sprCount];
19141984         /* Set Mode 3 lcdstate */
1915         m_lcd.mode = 3;
1985         m_mode = 3;
19161986         LCDSTAT = (LCDSTAT & 0xFC) | 0x03;
1917         m_lcd.vram_locked = LOCKED;
1918         m_lcd.pal_locked = LOCKED;
1987         m_vram_locked = LOCKED;
1988         m_pal_locked = LOCKED;
19191989         /* Check for compensations of x-scroll register */
19201990         /* Mode 3 lasts for approximately 172+cycles needed to handle sprites clock cycles */
1921         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(168 + m_lcd.scrollx_adjust + m_lcd.sprite_cycles), GB_LCD_STATE_LYXX_PRE_M0);
1922         m_lcd.start_x = -1;
1991         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(168 + m_scrollx_adjust + m_sprite_cycles), GB_LCD_STATE_LYXX_PRE_M0);
1992         m_start_x = -1;
19231993         break;
19241994      case GB_LCD_STATE_LY9X_M1:      /* Switch to or stay in mode 1 */
1925         if ( CURLINE == 144 )
1995         if (CURLINE == 144)
19261996         {
19271997            /* Trigger VBlank interrupt */
1928            m_maincpu->set_input_line(VBL_INT, ASSERT_LINE );
1998            m_maincpu->set_input_line(VBL_INT, ASSERT_LINE);
19291999            /* Set VBlank lcdstate */
1930            m_lcd.mode = 1;
2000            m_mode = 1;
19312001            LCDSTAT = (LCDSTAT & 0xFC) | 0x01;
19322002            /* Trigger LCD interrupt if requested */
1933            if ( LCDSTAT & 0x10 )
2003            if (LCDSTAT & 0x10)
19342004            {
1935               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2005               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
19362006            }
19372007         }
19382008         /* Check if LY==LYC STAT bit should be set */
1939         if ( CURLINE == CMPLINE )
2009         if (CURLINE == CMPLINE)
19402010         {
19412011            LCDSTAT |= 0x04;
19422012         }
r23879r23880
19442014         {
19452015            LCDSTAT &= ~0x04;
19462016         }
1947         if ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
2017         if (m_delayed_line_irq && m_triggering_line_irq)
19482018         {
1949            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2019            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
19502020         }
1951         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(452), GB_LCD_STATE_LY9X_M1_INC);
2021         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(452), GB_LCD_STATE_LY9X_M1_INC);
19522022         break;
19532023      case GB_LCD_STATE_LY9X_M1_INC:      /* Increment scanline counter */
1954         gb_increment_scanline();
1955         m_lcd.delayed_line_irq = m_lcd.line_irq;
1956         m_lcd.triggering_line_irq = ( ( CMPLINE == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1957         m_lcd.line_irq = 0;
1958         if ( ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
2024         increment_scanline();
2025         m_delayed_line_irq = m_line_irq;
2026         m_triggering_line_irq = ((CMPLINE == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
2027         m_line_irq = 0;
2028         if (!m_delayed_line_irq && m_triggering_line_irq)
19592029         {
1960            m_lcd.line_irq = m_lcd.triggering_line_irq;
1961            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2030            m_line_irq = m_triggering_line_irq;
2031            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
19622032         }
1963         if ( m_lcd.current_line == 153 )
2033         if (m_current_line == 153)
19642034         {
1965            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1);
2035            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1);
19662036         }
19672037         else
19682038         {
1969            m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
2039            m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY9X_M1);
19702040         }
19712041         break;
19722042      case GB_LCD_STATE_LY00_M1:      /* we stay in VBlank but current line counter should already be incremented */
19732043         /* Check LY=LYC for line #153 */
1974         if ( m_lcd.delayed_line_irq )
2044         if (m_delayed_line_irq)
19752045         {
1976            if ( m_lcd.triggering_line_irq )
2046            if (m_triggering_line_irq)
19772047            {
1978               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2048               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
19792049            }
19802050         }
1981         m_lcd.delayed_line_irq = m_lcd.delayed_line_irq | m_lcd.line_irq;
1982         if ( CURLINE == CMPLINE )
2051         m_delayed_line_irq = m_delayed_line_irq | m_line_irq;
2052         if (CURLINE == CMPLINE)
19832053         {
19842054            LCDSTAT |= 0x04;
19852055         }
r23879r23880
19872057         {
19882058            LCDSTAT &= ~0x04;
19892059         }
1990         gb_increment_scanline();
1991         m_lcd.triggering_line_irq = ( ( CMPLINE == CURLINE ) && ( LCDSTAT & 0x40 ) ) ? 1 : 0;
1992         m_lcd.line_irq = 0;
2060         increment_scanline();
2061         m_triggering_line_irq = ((CMPLINE == CURLINE) && (LCDSTAT & 0x40)) ? 1 : 0;
2062         m_line_irq = 0;
19932063         LCDSTAT &= 0xFB;
1994         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_1);
2064         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_1);
19952065         break;
19962066      case GB_LCD_STATE_LY00_M1_1:
1997         if ( ! m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
2067         if (!m_delayed_line_irq && m_triggering_line_irq)
19982068         {
1999            m_lcd.line_irq = m_lcd.triggering_line_irq;
2000            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2069            m_line_irq = m_triggering_line_irq;
2070            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
20012071         }
2002         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_2);
2072         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M1_2);
20032073         break;
20042074      case GB_LCD_STATE_LY00_M1_2:    /* Rest of line #0 during VBlank */
2005         if ( m_lcd.delayed_line_irq && m_lcd.triggering_line_irq )
2075         if (m_delayed_line_irq && m_triggering_line_irq)
20062076         {
2007            m_lcd.line_irq = m_lcd.triggering_line_irq;
2008            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2077            m_line_irq = m_triggering_line_irq;
2078            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
20092079         }
2010         if ( CURLINE == CMPLINE )
2080         if (CURLINE == CMPLINE)
20112081         {
20122082            LCDSTAT |= 0x04;
20132083         }
r23879r23880
20152085         {
20162086            LCDSTAT &= ~0x04;
20172087         }
2018         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(444), GB_LCD_STATE_LY00_M0);
2088         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(444), GB_LCD_STATE_LY00_M0);
20192089         break;
20202090      case GB_LCD_STATE_LY00_M0:      /* The STAT register seems to go to 0 for about 4 cycles */
20212091         /* Set Mode 0 lcdstat */
2022         m_lcd.mode = 0;
2023         m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M2);
2092         m_mode = 0;
2093         m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(4), GB_LCD_STATE_LY00_M2);
20242094         break;
20252095      }
20262096   }
20272097   else
20282098   {
2029      gb_increment_scanline();
2030      if ( m_lcd.current_line < 144 )
2099      increment_scanline();
2100      if (m_current_line < 144)
20312101      {
2032         (this->*update_scanline)();
2102         update_scanline();
20332103      }
2034      m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
2104      m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(456));
20352105   }
20362106}
20372107
20382108
2039void gb_state::gb_lcd_switch_on()
2109void gb_lcd_device::lcd_switch_on()
20402110{
2041   m_lcd.current_line = 0;
2042   m_lcd.previous_line = 153;
2043   m_lcd.window_lines_drawn = 0;
2044   m_lcd.line_irq = 0;
2045   m_lcd.delayed_line_irq = 0;
2046   m_lcd.mode = 0;
2047   m_lcd.oam_locked = LOCKED;   /* TODO: Investigate whether this OAM locking is correct. */
2111   m_current_line = 0;
2112   m_previous_line = 153;
2113   m_window_lines_drawn = 0;
2114   m_line_irq = 0;
2115   m_delayed_line_irq = 0;
2116   m_mode = 0;
2117   m_oam_locked = LOCKED;   /* TODO: Investigate whether this OAM locking is correct. */
20482118   /* Check for LY=LYC coincidence */
2049   if ( CURLINE == CMPLINE )
2119   if (CURLINE == CMPLINE)
20502120   {
20512121      LCDSTAT |= 0x04;
20522122      /* Generate lcd interrupt if requested */
2053      if ( LCDSTAT & 0x40 )
2123      if (LCDSTAT & 0x40)
20542124      {
2055         m_maincpu->set_input_line( LCD_INT, ASSERT_LINE );
2125         m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
20562126      }
20572127   }
2058   m_lcd.state = GB_LCD_STATE_LY00_M2;
2059   m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
2128   m_state = GB_LCD_STATE_LY00_M2;
2129   m_lcd_timer->adjust(m_maincpu->cycles_to_attotime(80), GB_LCD_STATE_LYXX_M3);
20602130}
20612131
2062READ8_MEMBER(gb_state::gb_video_r)
2063{
2064   return m_lcd.gb_vid_regs[offset];
2065}
20662132
2067READ8_MEMBER(gb_state::gb_vram_r)
2133
2134
2135READ8_MEMBER(gb_lcd_device::vram_r)
20682136{
2069   return (m_lcd.vram_locked == LOCKED) ? 0xff : m_lcd.gb_vram[offset + (m_lcd.gb_vram_bank * 0x2000)];
2137   return (m_vram_locked == LOCKED) ? 0xff : m_vram[offset + (m_vram_bank * 0x2000)];
20702138}
20712139
2072WRITE8_MEMBER(gb_state::gb_vram_w)
2140WRITE8_MEMBER(gb_lcd_device::vram_w)
20732141{
2074   if (m_lcd.vram_locked == LOCKED)
2142   if (m_vram_locked == LOCKED)
20752143      return;
2076
2077   m_lcd.gb_vram[offset + (m_lcd.gb_vram_bank * 0x2000)] = data;
2144   
2145   m_vram[offset + (m_vram_bank * 0x2000)] = data;
20782146}
20792147
2080READ8_MEMBER(gb_state::gb_oam_r)
2148READ8_MEMBER(gb_lcd_device::oam_r)
20812149{
2082   return (m_lcd.oam_locked == LOCKED) ? 0xff : m_lcd.gb_oam[offset];
2150   return (m_oam_locked == LOCKED) ? 0xff : m_oam[offset];
20832151}
20842152
2085WRITE8_MEMBER(gb_state::gb_oam_w)
2153WRITE8_MEMBER(gb_lcd_device::oam_w)
20862154{
2087   if (m_lcd.oam_locked == LOCKED || offset >= 0xa0)
2155   if (m_oam_locked == LOCKED || offset >= 0xa0)
20882156      return;
2157   
2158   m_oam[offset] = data;
2159}
20892160
2090   m_lcd.gb_oam[offset] = data;
2161
2162
2163READ8_MEMBER(gb_lcd_device::video_r)
2164{
2165   return m_vid_regs[offset];
20912166}
20922167
2093WRITE8_MEMBER(gb_state::gb_video_w)
2168WRITE8_MEMBER(gb_lcd_device::video_w)
20942169{
20952170   switch (offset)
20962171   {
20972172   case 0x00:                      /* LCDC - LCD Control */
2098      m_lcd.gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
2099      m_lcd.gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
2100      m_lcd.gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
2101      m_lcd.gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
2173      m_gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
2174      m_gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
2175      m_gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
2176      m_gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
21022177      /* if LCD controller is switched off, set STAT and LY to 00 */
21032178      if (!(data & 0x80))
21042179      {
21052180         LCDSTAT &= ~0x03;
21062181         CURLINE = 0;
2107         m_lcd.oam_locked = UNLOCKED;
2108         m_lcd.vram_locked = UNLOCKED;
2182         m_oam_locked = UNLOCKED;
2183         m_vram_locked = UNLOCKED;
21092184      }
21102185      /* If LCD is being switched on */
21112186      if (!(LCDCONT & 0x80) && (data & 0x80))
21122187      {
2113         gb_lcd_switch_on();
2188         lcd_switch_on();
21142189      }
21152190      break;
21162191   case 0x01:                      /* STAT - LCD Status */
r23879r23880
21202195         Writing to STAT when the LCD controller is active causes a STAT
21212196         interrupt to be triggered.
21222197       */
2123      if ( LCDCONT & 0x80 )
2198      if (LCDCONT & 0x80)
21242199      {
21252200         /* Triggers seen so far:
21262201            - 0x40 -> 0x00 - trigger
r23879r23880
21362211            - 0x20 -> 0x00/0x08/0x10/0x20/0x40 (mode 2, after m2int) - don't trigger
21372212            - 0x20 -> 0x00/0x08/0x10/0x20/0x40 (mode 3, after m2int) - don't trigger
21382213         */
2139         if ( ! m_lcd.mode_irq && ( ( m_lcd.mode == 1 ) ||
2140            ( ( LCDSTAT & 0x40 ) && ! ( data & 0x68 ) ) ||
2141            ( ! ( LCDSTAT & 0x40 ) && ( data & 0x40 ) && ( LCDSTAT & 0x04 ) ) ||
2142            ( ! ( LCDSTAT & 0x48 ) && ( data & 0x08 ) ) ||
2143            ( ( LCDSTAT & 0x60 ) == 0x00 && ( data & 0x60 ) == 0x20 ) ||
2144            ( ( LCDSTAT & 0x60 ) == 0x20 && ( data & 0x40 ) )
2145            ) )
2214         if (!m_mode_irq && ((m_mode == 1) ||
2215            ((LCDSTAT & 0x40) && !(data & 0x68)) ||
2216            (!(LCDSTAT & 0x40) && (data & 0x40) && (LCDSTAT & 0x04)) ||
2217            (!(LCDSTAT & 0x48) && (data & 0x08)) ||
2218            ((LCDSTAT & 0x60) == 0x00 && (data & 0x60) == 0x20) ||
2219            ((LCDSTAT & 0x60) == 0x20 && (data & 0x40))
2220            ))
21462221         {
2147               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2222            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
21482223         }
21492224         /*
21502225            - 0x20 -> 0x08/0x18/0x28/0x48 (mode 0, after m2int) - trigger
21512226            - 0x20 -> 0x00/0x10/0x20/0x40 (mode 0, after m2int) - trigger (stat bug)
21522227            - 0x00 -> 0xXX (mode 0) - trigger stat bug
21532228         */
2154         if ( m_lcd.mode_irq && m_lcd.mode == 0 )
2229         if (m_mode_irq && m_mode == 0)
21552230         {
2156            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2231            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
21572232         }
21582233      }
21592234      break;
21602235   case 0x04:                      /* LY - LCD Y-coordinate */
21612236      return;
21622237   case 0x05:                      /* LYC */
2163      if ( CMPLINE != data )
2238      if (CMPLINE != data)
21642239      {
2165         if ( CURLINE == data )
2240         if (CURLINE == data)
21662241         {
2167            if ( m_lcd.state != GB_LCD_STATE_LYXX_M0_INC && m_lcd.state != GB_LCD_STATE_LY9X_M1_INC )
2242            if (m_state != GB_LCD_STATE_LYXX_M0_INC && m_state != GB_LCD_STATE_LY9X_M1_INC)
21682243            {
21692244               LCDSTAT |= 0x04;
21702245               /* Generate lcd interrupt if requested */
2171               if ( LCDSTAT & 0x40 )
2246               if (LCDSTAT & 0x40)
21722247               {
2173                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2248                  m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
21742249               }
21752250            }
21762251         }
21772252         else
21782253         {
21792254            LCDSTAT &= 0xFB;
2180            m_lcd.triggering_line_irq = 0;
2255            m_triggering_line_irq = 0;
21812256         }
21822257      }
21832258      break;
21842259   case 0x06:                      /* DMA - DMA Transfer and Start Address */
21852260      {
2186         UINT8 *P = m_lcd.gb_oam;
2261         UINT8 *P = m_oam;
21872262         offset = (UINT16) data << 8;
21882263         for (data = 0; data < 0xA0; data++)
21892264            *P++ = space.read_byte(offset++);
21902265      }
21912266      return;
21922267   case 0x07:                      /* BGP - Background Palette */
2193      (this->*update_scanline)();
2194      m_lcd.gb_bpal[0] = data & 0x3;
2195      m_lcd.gb_bpal[1] = (data & 0xC) >> 2;
2196      m_lcd.gb_bpal[2] = (data & 0x30) >> 4;
2197      m_lcd.gb_bpal[3] = (data & 0xC0) >> 6;
2268      update_scanline();
2269      m_gb_bpal[0] = data & 0x3;
2270      m_gb_bpal[1] = (data & 0xC) >> 2;
2271      m_gb_bpal[2] = (data & 0x30) >> 4;
2272      m_gb_bpal[3] = (data & 0xC0) >> 6;
21982273      break;
21992274   case 0x08:                      /* OBP0 - Object Palette 0 */
2200//      (this->*update_scanline)();
2201      m_lcd.gb_spal0[0] = data & 0x3;
2202      m_lcd.gb_spal0[1] = (data & 0xC) >> 2;
2203      m_lcd.gb_spal0[2] = (data & 0x30) >> 4;
2204      m_lcd.gb_spal0[3] = (data & 0xC0) >> 6;
2275//      update_scanline();
2276      m_gb_spal0[0] = data & 0x3;
2277      m_gb_spal0[1] = (data & 0xC) >> 2;
2278      m_gb_spal0[2] = (data & 0x30) >> 4;
2279      m_gb_spal0[3] = (data & 0xC0) >> 6;
22052280      break;
22062281   case 0x09:                      /* OBP1 - Object Palette 1 */
2207//      (this->*update_scanline)();
2208      m_lcd.gb_spal1[0] = data & 0x3;
2209      m_lcd.gb_spal1[1] = (data & 0xC) >> 2;
2210      m_lcd.gb_spal1[2] = (data & 0x30) >> 4;
2211      m_lcd.gb_spal1[3] = (data & 0xC0) >> 6;
2282//      update_scanline();
2283      m_gb_spal1[0] = data & 0x3;
2284      m_gb_spal1[1] = (data & 0xC) >> 2;
2285      m_gb_spal1[2] = (data & 0x30) >> 4;
2286      m_gb_spal1[3] = (data & 0xC0) >> 6;
22122287      break;
22132288   case 0x02:                      /* SCY - Scroll Y */
22142289   case 0x03:                      /* SCX - Scroll X */
2215      (this->*update_scanline)();
2290      update_scanline();
2291      break;
22162292   case 0x0A:                      /* WY - Window Y position */
22172293   case 0x0B:                      /* WX - Window X position */
22182294      break;
22192295   default:                        /* Unknown register, no change */
22202296      return;
22212297   }
2222   m_lcd.gb_vid_regs[offset] = data;
2298   m_vid_regs[offset] = data;
22232299}
22242300
2225READ8_MEMBER(gb_state::gbc_video_r)
2301READ8_MEMBER(cgb_lcd_device::video_r)
22262302{
2227   switch( offset )
2303   switch (offset)
22282304   {
22292305   case 0x11:  /* FF51 */
22302306   case 0x12:  /* FF52 */
r23879r23880
22332309      return 0xFF;
22342310   case 0x29:  /* FF69 */
22352311   case 0x2B:  /* FF6B */
2236      if ( m_lcd.pal_locked == LOCKED )
2312      if (m_pal_locked == LOCKED)
22372313      {
22382314         return 0xFF;
22392315      }
22402316      break;
22412317   }
2242   return m_lcd.gb_vid_regs[offset];
2318   return m_vid_regs[offset];
22432319}
22442320
2245WRITE8_MEMBER(gb_state::gbc_video_w)
2321WRITE8_MEMBER(cgb_lcd_device::video_w)
22462322{
2247   switch( offset )
2323   switch (offset)
22482324   {
22492325   case 0x00:      /* LCDC - LCD Control */
2250      m_lcd.gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
2251      m_lcd.gbc_chrgen_offs = (data & 0x10) ? 0x2000 : 0x2800;
2252      m_lcd.gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
2253      m_lcd.gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
2254      m_lcd.gbc_bgdtab_offs = (data & 0x08) ? 0x3c00 : 0x3800;
2255      m_lcd.gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
2256      m_lcd.gbc_wndtab_offs = (data & 0x40) ? 0x3c00 : 0x3800;
2326      m_gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
2327      m_gbc_chrgen_offs = (data & 0x10) ? 0x2000 : 0x2800;
2328      m_gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
2329      m_gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
2330      m_gbc_bgdtab_offs = (data & 0x08) ? 0x3c00 : 0x3800;
2331      m_gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
2332      m_gbc_wndtab_offs = (data & 0x40) ? 0x3c00 : 0x3800;
22572333      /* if LCD controller is switched off, set STAT to 00 */
2258      if ( ! ( data & 0x80 ) )
2334      if (!(data & 0x80))
22592335      {
22602336         LCDSTAT &= ~0x03;
22612337         CURLINE = 0;
2262         m_lcd.oam_locked = UNLOCKED;
2263         m_lcd.vram_locked = UNLOCKED;
2264         m_lcd.pal_locked = UNLOCKED;
2338         m_oam_locked = UNLOCKED;
2339         m_vram_locked = UNLOCKED;
2340         m_pal_locked = UNLOCKED;
22652341      }
22662342      /* If LCD is being switched on */
2267      if ( !( LCDCONT & 0x80 ) && ( data & 0x80 ) )
2343      if (!(LCDCONT & 0x80) && (data & 0x80))
22682344      {
2269         gb_lcd_switch_on();
2345         lcd_switch_on();
22702346      }
22712347      break;
22722348   case 0x01:      /* STAT - LCD Status */
22732349      data = 0x80 | (data & 0x78) | (LCDSTAT & 0x07);
2274      if ( LCDCONT & 0x80 )
2350      if (LCDCONT & 0x80)
22752351      {
22762352         /*
22772353            - 0x20 -> 0x08/0x18/0x28/0x48 (mode 0, after m2int) - trigger
22782354         */
2279         if ( m_lcd.mode_irq && m_lcd.mode == 0 && ( LCDSTAT & 0x28 ) == 0x20 && ( data & 0x08 ) )
2355         if (m_mode_irq && m_mode == 0 && (LCDSTAT & 0x28) == 0x20 && (data & 0x08))
22802356         {
2281            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2357            m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
22822358         }
22832359         /* Check if line irqs are being disabled */
2284         if ( ! ( data & 0x40 ) )
2360         if (!(data & 0x40))
22852361         {
2286            m_lcd.delayed_line_irq = 0;
2362            m_delayed_line_irq = 0;
22872363         }
22882364         /* Check if line irqs are being enabled */
2289         if ( ! ( LCDSTAT & 0x40 ) && ( data & 0x40 ) )
2365         if (!(LCDSTAT & 0x40) && (data & 0x40))
22902366         {
2291            if ( CMPLINE == CURLINE )
2367            if (CMPLINE == CURLINE)
22922368            {
2293               m_lcd.line_irq = 1;
2294               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2369               m_line_irq = 1;
2370               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
22952371            }
22962372         }
22972373      }
22982374      break;
22992375   case 0x05:                      /* LYC */
2300      if ( CMPLINE != data )
2376      if (CMPLINE != data)
23012377      {
2302         if ( ( m_lcd.state != GB_LCD_STATE_LYXX_M0_PRE_INC && CURLINE == data ) ||
2303               ( m_lcd.state == GB_LCD_STATE_LYXX_M0_INC && m_lcd.triggering_line_irq ) )
2378         if ((m_state != GB_LCD_STATE_LYXX_M0_PRE_INC && CURLINE == data) ||
2379               (m_state == GB_LCD_STATE_LYXX_M0_INC && m_triggering_line_irq))
23042380         {
23052381            LCDSTAT |= 0x04;
23062382            /* Generate lcd interrupt if requested */
2307            if ( LCDSTAT & 0x40 )
2383            if (LCDSTAT & 0x40)
23082384            {
2309               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE );
2385               m_maincpu->set_input_line(LCD_INT, ASSERT_LINE);
23102386            }
23112387         }
23122388         else
23132389         {
23142390            LCDSTAT &= 0xFB;
2315            m_lcd.triggering_line_irq = 0;
2316            m_lcd.cmp_line = data;
2391            m_triggering_line_irq = 0;
2392            m_cmp_line = data;
23172393         }
23182394      }
23192395      break;
23202396   case 0x07:      /* BGP - GB background palette */
2321      (this->*update_scanline)();
2322      m_lcd.gb_bpal[0] = data & 0x3;
2323      m_lcd.gb_bpal[1] = (data & 0xC) >> 2;
2324      m_lcd.gb_bpal[2] = (data & 0x30) >> 4;
2325      m_lcd.gb_bpal[3] = (data & 0xC0) >> 6;
2397      update_scanline();
2398      m_gb_bpal[0] = data & 0x3;
2399      m_gb_bpal[1] = (data & 0xC) >> 2;
2400      m_gb_bpal[2] = (data & 0x30) >> 4;
2401      m_gb_bpal[3] = (data & 0xC0) >> 6;
23262402      break;
23272403   case 0x08:      /* OBP0 - GB Object 0 palette */
2328      m_lcd.gb_spal0[0] = data & 0x3;
2329      m_lcd.gb_spal0[1] = (data & 0xC) >> 2;
2330      m_lcd.gb_spal0[2] = (data & 0x30) >> 4;
2331      m_lcd.gb_spal0[3] = (data & 0xC0) >> 6;
2404      m_gb_spal0[0] = data & 0x3;
2405      m_gb_spal0[1] = (data & 0xC) >> 2;
2406      m_gb_spal0[2] = (data & 0x30) >> 4;
2407      m_gb_spal0[3] = (data & 0xC0) >> 6;
23322408      break;
23332409   case 0x09:      /* OBP1 - GB Object 1 palette */
2334      m_lcd.gb_spal1[0] = data & 0x3;
2335      m_lcd.gb_spal1[1] = (data & 0xC) >> 2;
2336      m_lcd.gb_spal1[2] = (data & 0x30) >> 4;
2337      m_lcd.gb_spal1[3] = (data & 0xC0) >> 6;
2410      m_gb_spal1[0] = data & 0x3;
2411      m_gb_spal1[1] = (data & 0xC) >> 2;
2412      m_gb_spal1[2] = (data & 0x30) >> 4;
2413      m_gb_spal1[3] = (data & 0xC0) >> 6;
23382414      break;
23392415   case 0x0c:      /* Undocumented register involved in selecting gb/gbc mode */
2340      logerror( "Write to undocumented register: %X = %X\n", offset, data );
2416      logerror("Write to undocumented register: %X = %X\n", offset, data);
23412417      break;
23422418   case 0x0F:      /* VBK - VRAM bank select */
2343      m_lcd.gb_vram_bank = data & 0x01;
2419      m_vram_bank = data & 0x01;
23442420      data |= 0xFE;
23452421      break;
23462422   case 0x11:      /* HDMA1 - HBL General DMA - Source High */
r23879r23880
23552431      data &= 0xF0;
23562432      break;
23572433   case 0x15:      /* HDMA5 - HBL General DMA - Mode, Length */
2358      if( !(data & 0x80) )
2434      if (!(data & 0x80))
23592435      {
2360         if( m_lcd.hdma_enabled )
2436         if (m_hdma_enabled)
23612437         {
2362            m_lcd.hdma_enabled = 0;
2438            m_hdma_enabled = 0;
23632439            data = HDMA5 & 0x80;
23642440         }
23652441         else
23662442         {
23672443            /* General DMA */
2368            gbc_hdma( ((data & 0x7F) + 1) * 0x10 );
2369//              cpunum_set_reg( 0, LR35902_DMA_CYCLES, 4 + ( ( ( data & 0x7F ) + 1 ) * 32 ) );
2444            hdma_trans(((data & 0x7F) + 1) * 0x10);
2445//              cpunum_set_reg(0, LR35902_DMA_CYCLES, 4 + (((data & 0x7F) + 1) * 32));
23702446            data = 0xff;
23712447         }
23722448      }
23732449      else
23742450      {
23752451         /* H-Blank DMA */
2376         m_lcd.hdma_enabled = 1;
2452         m_hdma_enabled = 1;
23772453         data &= 0x7f;
2378         m_lcd.gb_vid_regs[offset] = data;
2454         m_vid_regs[offset] = data;
23792455         /* Check if HDMA should be immediately performed */
2380         if ( m_lcd.hdma_possible )
2456         if (m_hdma_possible)
23812457         {
2382            gbc_hdma( 0x10 );
2383//              cpunum_set_reg( 0, LR35902_DMA_CYCLES, 36 );
2384            m_lcd.hdma_possible = 0;
2458            hdma_trans(0x10);
2459//              cpunum_set_reg(0, LR35902_DMA_CYCLES, 36);
2460            m_hdma_possible = 0;
23852461         }
23862462      }
23872463      break;
23882464   case 0x28:      /* BCPS - Background palette specification */
23892465      GBCBCPS = data;
23902466      if (data & 0x01)
2391         GBCBCPD = m_lcd.cgb_bpal[( data >> 1 ) & 0x1F] >> 8;
2467         GBCBCPD = m_cgb_bpal[(data >> 1) & 0x1F] >> 8;
23922468      else
2393         GBCBCPD = m_lcd.cgb_bpal[( data >> 1 ) & 0x1F] & 0xFF;
2469         GBCBCPD = m_cgb_bpal[(data >> 1) & 0x1F] & 0xFF;
23942470      break;
23952471   case 0x29:      /* BCPD - background palette data */
2396      if ( m_lcd.pal_locked == LOCKED )
2472      if (m_pal_locked == LOCKED)
23972473      {
23982474         return;
23992475      }
24002476      GBCBCPD = data;
24012477      if (GBCBCPS & 0x01)
2402         m_lcd.cgb_bpal[( GBCBCPS >> 1 ) & 0x1F] = ((data << 8) | (m_lcd.cgb_bpal[( GBCBCPS >> 1 ) & 0x1F] & 0xFF)) & 0x7FFF;
2478         m_cgb_bpal[(GBCBCPS >> 1) & 0x1F] = ((data << 8) | (m_cgb_bpal[(GBCBCPS >> 1) & 0x1F] & 0xFF)) & 0x7FFF;
24032479      else
2404         m_lcd.cgb_bpal[( GBCBCPS >> 1 ) & 0x1F] = ((m_lcd.cgb_bpal[( GBCBCPS >> 1 ) & 0x1F] & 0xFF00) | data) & 0x7FFF;
2405      if( GBCBCPS & 0x80 )
2480         m_cgb_bpal[(GBCBCPS >> 1) & 0x1F] = ((m_cgb_bpal[(GBCBCPS >> 1) & 0x1F] & 0xFF00) | data) & 0x7FFF;
2481      if (GBCBCPS & 0x80)
24062482      {
24072483         GBCBCPS++;
24082484         GBCBCPS &= 0xBF;
r23879r23880
24112487   case 0x2A:      /* OCPS - Object palette specification */
24122488      GBCOCPS = data;
24132489      if (data & 0x01)
2414         GBCOCPD = m_lcd.cgb_spal[( data >> 1 ) & 0x1F] >> 8;
2490         GBCOCPD = m_cgb_spal[(data >> 1) & 0x1F] >> 8;
24152491      else
2416         GBCOCPD = m_lcd.cgb_spal[( data >> 1 ) & 0x1F] & 0xFF;
2492         GBCOCPD = m_cgb_spal[(data >> 1) & 0x1F] & 0xFF;
24172493      break;
24182494   case 0x2B:      /* OCPD - Object palette data */
2419      if ( m_lcd.pal_locked == LOCKED )
2495      if (m_pal_locked == LOCKED)
24202496      {
24212497         return;
24222498      }
24232499      GBCOCPD = data;
24242500      if (GBCOCPS & 0x01)
2425         m_lcd.cgb_spal[( GBCOCPS >> 1 ) & 0x1F] = ((data << 8) | (m_lcd.cgb_spal[( GBCOCPS >> 1 ) & 0x1F] & 0xFF)) & 0x7FFF;
2501         m_cgb_spal[(GBCOCPS >> 1) & 0x1F] = ((data << 8) | (m_cgb_spal[(GBCOCPS >> 1) & 0x1F] & 0xFF)) & 0x7FFF;
24262502      else
2427         m_lcd.cgb_spal[( GBCOCPS >> 1 ) & 0x1F] = ((m_lcd.cgb_spal[( GBCOCPS >> 1 ) & 0x1F] & 0xFF00) | data) & 0x7FFF;
2428      if( GBCOCPS & 0x80 )
2503         m_cgb_spal[(GBCOCPS >> 1) & 0x1F] = ((m_cgb_spal[(GBCOCPS >> 1) & 0x1F] & 0xFF00) | data) & 0x7FFF;
2504      if (GBCOCPS & 0x80)
24292505      {
24302506         GBCOCPS++;
24312507         GBCOCPS &= 0xBF;
r23879r23880
24342510   /* Undocumented registers */
24352511   case 0x2C:
24362512      /* bit 0 can be read/written */
2437      logerror( "Write to undocumented register: %X = %X\n", offset, data );
2438      data = 0xFE | ( data & 0x01 );
2439      if ( data & 0x01 )
2513      logerror("Write to undocumented register: %X = %X\n", offset, data);
2514      data = 0xFE | (data & 0x01);
2515      if (data & 0x01)
24402516      {
2441         m_lcd.gbc_mode = 0;
2517         m_gbc_mode = 0;
24422518      }
24432519      break;
24442520   case 0x32:
24452521   case 0x33:
24462522   case 0x34:
24472523      /* whole byte can be read/written */
2448      logerror( "Write to undocumented register: %X = %X\n", offset, data );
2524      logerror("Write to undocumented register: %X = %X\n", offset, data);
24492525      break;
24502526   case 0x35:
24512527      /* bit 4-6 can be read/written */
2452      logerror( "Write to undocumented register: %X = %X\n", offset, data );
2453      data = 0x8F | ( data & 0x70 );
2528      logerror("Write to undocumented register: %X = %X\n", offset, data);
2529      data = 0x8F | (data & 0x70);
24542530      break;
24552531   case 0x36:
24562532   case 0x37:
2457      logerror( "Write to undocumented register: %X = %X\n", offset, data );
2533      logerror("Write to undocumented register: %X = %X\n", offset, data);
24582534      return;
24592535   default:
24602536      /* we didn't handle the write, so pass it to the GB handler */
2461      gb_video_w( space, offset, data );
2537      gb_lcd_device::video_w(space, offset, data);
24622538      return;
24632539   }
24642540
2465   m_lcd.gb_vid_regs[offset] = data;
2541   m_vid_regs[offset] = data;
24662542}
2543
2544// Super Game Boy
2545
2546void sgb_lcd_device::sgb_io_write_pal(int offs, UINT8 *data)
2547{
2548   switch (offs)
2549   {
2550      case 0x00:  /* PAL01 */
2551         m_sgb_pal[0 * 4 + 0] = data[1] | (data[2] << 8);
2552         m_sgb_pal[0 * 4 + 1] = data[3] | (data[4] << 8);
2553         m_sgb_pal[0 * 4 + 2] = data[5] | (data[6] << 8);
2554         m_sgb_pal[0 * 4 + 3] = data[7] | (data[8] << 8);
2555         m_sgb_pal[1 * 4 + 0] = data[1] | (data[2] << 8);
2556         m_sgb_pal[1 * 4 + 1] = data[9] | (data[10] << 8);
2557         m_sgb_pal[1 * 4 + 2] = data[11] | (data[12] << 8);
2558         m_sgb_pal[1 * 4 + 3] = data[13] | (data[14] << 8);
2559         break;
2560      case 0x01:  /* PAL23 */
2561         m_sgb_pal[2 * 4 + 0] = data[1] | (data[2] << 8);
2562         m_sgb_pal[2 * 4 + 1] = data[3] | (data[4] << 8);
2563         m_sgb_pal[2 * 4 + 2] = data[5] | (data[6] << 8);
2564         m_sgb_pal[2 * 4 + 3] = data[7] | (data[8] << 8);
2565         m_sgb_pal[3 * 4 + 0] = data[1] | (data[2] << 8);
2566         m_sgb_pal[3 * 4 + 1] = data[9] | (data[10] << 8);
2567         m_sgb_pal[3 * 4 + 2] = data[11] | (data[12] << 8);
2568         m_sgb_pal[3 * 4 + 3] = data[13] | (data[14] << 8);
2569         break;
2570      case 0x02:  /* PAL03 */
2571         m_sgb_pal[0 * 4 + 0] = data[1] | (data[2] << 8);
2572         m_sgb_pal[0 * 4 + 1] = data[3] | (data[4] << 8);
2573         m_sgb_pal[0 * 4 + 2] = data[5] | (data[6] << 8);
2574         m_sgb_pal[0 * 4 + 3] = data[7] | (data[8] << 8);
2575         m_sgb_pal[3 * 4 + 0] = data[1] | (data[2] << 8);
2576         m_sgb_pal[3 * 4 + 1] = data[9] | (data[10] << 8);
2577         m_sgb_pal[3 * 4 + 2] = data[11] | (data[12] << 8);
2578         m_sgb_pal[3 * 4 + 3] = data[13] | (data[14] << 8);
2579         break;
2580      case 0x03:  /* PAL12 */
2581         m_sgb_pal[1 * 4 + 0] = data[1] | (data[2] << 8);
2582         m_sgb_pal[1 * 4 + 1] = data[3] | (data[4] << 8);
2583         m_sgb_pal[1 * 4 + 2] = data[5] | (data[6] << 8);
2584         m_sgb_pal[1 * 4 + 3] = data[7] | (data[8] << 8);
2585         m_sgb_pal[2 * 4 + 0] = data[1] | (data[2] << 8);
2586         m_sgb_pal[2 * 4 + 1] = data[9] | (data[10] << 8);
2587         m_sgb_pal[2 * 4 + 2] = data[11] | (data[12] << 8);
2588         m_sgb_pal[2 * 4 + 3] = data[13] | (data[14] << 8);
2589         break;
2590      case 0x04:  /* ATTR_BLK */
2591      {
2592         UINT8 I, J, K, o;
2593         for( K = 0; K < data[1]; K++ )
2594         {
2595            o = K * 6;
2596            if( data[o + 2] & 0x1 )
2597            {
2598               for( I = data[ o + 4]; I <= data[o + 6]; I++ )
2599               {
2600                  for( J = data[o + 5]; J <= data[o + 7]; J++ )
2601                  {
2602                     m_sgb_pal_map[I][J] = data[o + 3] & 0x3;
2603                  }
2604               }
2605            }
2606         }
2607      }
2608         break;
2609      case 0x05:  /* ATTR_LIN */
2610      {
2611         UINT8 J, K;
2612         if( data[1] > 15 )
2613            data[1] = 15;
2614         for( K = 0; K < data[1]; K++ )
2615         {
2616            if( data[K + 1] & 0x80 )
2617            {
2618               for( J = 0; J < 20; J++ )
2619               {
2620                  m_sgb_pal_map[J][data[K + 1] & 0x1f] = (data[K + 1] & 0x60) >> 5;
2621               }
2622            }
2623            else
2624            {
2625               for( J = 0; J < 18; J++ )
2626               {
2627                  m_sgb_pal_map[data[K + 1] & 0x1f][J] = (data[K + 1] & 0x60) >> 5;
2628               }
2629            }
2630         }
2631      }
2632         break;
2633      case 0x06:  /* ATTR_DIV */
2634      {
2635         UINT8 I, J;
2636         if( data[1] & 0x40 ) /* Vertical */
2637         {
2638            for( I = 0; I < data[2]; I++ )
2639            {
2640               for( J = 0; J < 20; J++ )
2641               {
2642                  m_sgb_pal_map[J][I] = (data[1] & 0xC) >> 2;
2643               }
2644            }
2645            for( J = 0; J < 20; J++ )
2646            {
2647               m_sgb_pal_map[J][data[2]] = (data[1] & 0x30) >> 4;
2648            }
2649            for( I = data[2] + 1; I < 18; I++ )
2650            {
2651               for( J = 0; J < 20; J++ )
2652               {
2653                  m_sgb_pal_map[J][I] = data[1] & 0x3;
2654               }
2655            }
2656         }
2657         else /* Horizontal */
2658         {
2659            for( I = 0; I < data[2]; I++ )
2660            {
2661               for( J = 0; J < 18; J++ )
2662               {
2663                  m_sgb_pal_map[I][J] = (data[1] & 0xC) >> 2;
2664               }
2665            }
2666            for( J = 0; J < 18; J++ )
2667            {
2668               m_sgb_pal_map[data[2]][J] = (data[1] & 0x30) >> 4;
2669            }
2670            for( I = data[2] + 1; I < 20; I++ )
2671            {
2672               for( J = 0; J < 18; J++ )
2673               {
2674                  m_sgb_pal_map[I][J] = data[1] & 0x3;
2675               }
2676            }
2677         }
2678      }
2679         break;
2680      case 0x07:  /* ATTR_CHR */
2681      {
2682         UINT16 I, sets;
2683         UINT8 x, y;
2684         sets = (data[3] | (data[4] << 8) );
2685         if( sets > 360 )
2686            sets = 360;
2687         sets >>= 2;
2688         sets += 6;
2689         x = data[1];
2690         y = data[2];
2691         if( data[5] ) /* Vertical */
2692         {
2693            for( I = 6; I < sets; I++ )
2694            {
2695               m_sgb_pal_map[x][y++] = (data[I] & 0xC0) >> 6;
2696               if( y > 17 )
2697               {
2698                  y = 0;
2699                  x++;
2700                  if( x > 19 )
2701                     x = 0;
2702               }
2703               
2704               m_sgb_pal_map[x][y++] = (data[I] & 0x30) >> 4;
2705               if( y > 17 )
2706               {
2707                  y = 0;
2708                  x++;
2709                  if( x > 19 )
2710                     x = 0;
2711               }
2712               
2713               m_sgb_pal_map[x][y++] = (data[I] & 0xC) >> 2;
2714               if( y > 17 )
2715               {
2716                  y = 0;
2717                  x++;
2718                  if( x > 19 )
2719                     x = 0;
2720               }
2721               
2722               m_sgb_pal_map[x][y++] = data[I] & 0x3;
2723               if( y > 17 )
2724               {
2725                  y = 0;
2726                  x++;
2727                  if( x > 19 )
2728                     x = 0;
2729               }
2730            }
2731         }
2732         else /* horizontal */
2733         {
2734            for( I = 6; I < sets; I++ )
2735            {
2736               m_sgb_pal_map[x++][y] = (data[I] & 0xC0) >> 6;
2737               if( x > 19 )
2738               {
2739                  x = 0;
2740                  y++;
2741                  if( y > 17 )
2742                     y = 0;
2743               }
2744               
2745               m_sgb_pal_map[x++][y] = (data[I] & 0x30) >> 4;
2746               if( x > 19 )
2747               {
2748                  x = 0;
2749                  y++;
2750                  if( y > 17 )
2751                     y = 0;
2752               }
2753               
2754               m_sgb_pal_map[x++][y] = (data[I] & 0xC) >> 2;
2755               if( x > 19 )
2756               {
2757                  x = 0;
2758                  y++;
2759                  if( y > 17 )
2760                     y = 0;
2761               }
2762               
2763               m_sgb_pal_map[x++][y] = data[I] & 0x3;
2764               if( x > 19 )
2765               {
2766                  x = 0;
2767                  y++;
2768                  if( y > 17 )
2769                     y = 0;
2770               }
2771            }
2772         }
2773      }
2774         break;
2775      case 0x08:  /* SOUND */
2776         /* This command enables internal sound effects */
2777         /* Not Implemented */
2778         break;
2779      case 0x09:  /* SOU_TRN */
2780         /* This command sends data to the SNES sound processor.
2781          We'll need to emulate that for this to be used */
2782         /* Not Implemented */
2783         break;
2784      case 0x0A:  /* PAL_SET */
2785      {
2786         UINT16 index_;
2787         
2788         /* Palette 0 */
2789         index_ = (UINT16)(data[1] | (data[2] << 8)) * 4;
2790         m_sgb_pal[0] = m_sgb_pal_data[index_];
2791         m_sgb_pal[1] = m_sgb_pal_data[index_ + 1];
2792         m_sgb_pal[2] = m_sgb_pal_data[index_ + 2];
2793         m_sgb_pal[3] = m_sgb_pal_data[index_ + 3];
2794         /* Palette 1 */
2795         index_ = (UINT16)(data[3] | (data[4] << 8)) * 4;
2796         m_sgb_pal[4] = m_sgb_pal_data[index_];
2797         m_sgb_pal[5] = m_sgb_pal_data[index_ + 1];
2798         m_sgb_pal[6] = m_sgb_pal_data[index_ + 2];
2799         m_sgb_pal[7] = m_sgb_pal_data[index_ + 3];
2800         /* Palette 2 */
2801         index_ = (UINT16)(data[5] | (data[6] << 8)) * 4;
2802         m_sgb_pal[8] = m_sgb_pal_data[index_];
2803         m_sgb_pal[9] = m_sgb_pal_data[index_ + 1];
2804         m_sgb_pal[10] = m_sgb_pal_data[index_ + 2];
2805         m_sgb_pal[11] = m_sgb_pal_data[index_ + 3];
2806         /* Palette 3 */
2807         index_ = (UINT16)(data[7] | (data[8] << 8)) * 4;
2808         m_sgb_pal[12] = m_sgb_pal_data[index_];
2809         m_sgb_pal[13] = m_sgb_pal_data[index_ + 1];
2810         m_sgb_pal[14] = m_sgb_pal_data[index_ + 2];
2811         m_sgb_pal[15] = m_sgb_pal_data[index_ + 3];
2812         /* Attribute File */
2813         if (data[9] & 0x40)
2814            m_sgb_window_mask = 0;
2815         m_sgb_atf = (data[9] & 0x3f) * (18 * 5);
2816         if (data[9] & 0x80)
2817         {
2818            for (int j = 0; j < 18; j++ )
2819            {
2820               for (int i = 0; i < 5; i++ )
2821               {
2822                  m_sgb_pal_map[i * 4][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0xC0) >> 6;
2823                  m_sgb_pal_map[(i * 4) + 1][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0x30) >> 4;
2824                  m_sgb_pal_map[(i * 4) + 2][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0xC) >> 2;
2825                  m_sgb_pal_map[(i * 4) + 3][j] = m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0x3;
2826               }
2827            }
2828         }
2829      }
2830         break;
2831      case 0x0B:  /* PAL_TRN */
2832      {
2833         UINT16 col;
2834         
2835         for (int i = 0; i < 2048; i++ )
2836         {
2837            col = (m_vram[0x0800 + (i * 2) + 1] << 8) | m_vram[0x0800 + (i * 2)];
2838            m_sgb_pal_data[i] = col;
2839         }
2840      }
2841         break;
2842      case 0x0C:  /* ATRC_EN */
2843         /* Not Implemented */
2844         break;
2845      case 0x0D:  /* TEST_EN */
2846         /* Not Implemented */
2847         break;
2848      case 0x0E:  /* ICON_EN */
2849         /* Not Implemented */
2850         break;
2851      case 0x0F:  /* DATA_SND */
2852         /* Not Implemented */
2853         break;
2854      case 0x10:  /* DATA_TRN */
2855         /* Not Implemented */
2856         break;
2857      case 0x12:  /* JUMP */
2858         /* Not Implemented */
2859         break;
2860      case 0x13:  /* CHR_TRN */
2861         if (data[1] & 0x1)
2862            memcpy(m_sgb_tile_data + 4096, m_vram + 0x0800, 4096);
2863         else
2864            memcpy(m_sgb_tile_data, m_vram + 0x0800, 4096);
2865         break;
2866      case 0x14:  /* PCT_TRN */
2867      {
2868         UINT16 col;
2869         if (m_sgb_border_hack)
2870         {
2871            memcpy(m_sgb_tile_map, m_vram + 0x1000, 2048);
2872            for (int i = 0; i < 64; i++)
2873            {
2874               col = (m_vram[0x0800 + (i * 2) + 1 ] << 8) | m_vram[0x0800 + (i * 2)];
2875               m_sgb_pal[SGB_BORDER_PAL_OFFSET + i] = col;
2876            }
2877         }
2878         else /* Do things normally */
2879         {
2880            memcpy(m_sgb_tile_map, m_vram + 0x0800, 2048);
2881            for (int i = 0; i < 64; i++)
2882            {
2883               col = (m_vram[0x1000 + (i * 2) + 1] << 8) | m_vram[0x1000 + (i * 2)];
2884               m_sgb_pal[SGB_BORDER_PAL_OFFSET + i] = col;
2885            }
2886         }
2887      }
2888         break;
2889      case 0x15:  /* ATTR_TRN */
2890         memcpy(m_sgb_atf_data, m_vram + 0x0800, 4050);
2891         break;
2892      case 0x16:  /* ATTR_SET */
2893      {         
2894         /* Attribute File */
2895         if (data[1] & 0x40)
2896            m_sgb_window_mask = 0;
2897         m_sgb_atf = (data[1] & 0x3f) * (18 * 5);
2898         for (int j = 0; j < 18; j++)
2899         {
2900            for (int i = 0; i < 5; i++)
2901            {
2902               m_sgb_pal_map[i * 4][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0xC0) >> 6;
2903               m_sgb_pal_map[(i * 4) + 1][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0x30) >> 4;
2904               m_sgb_pal_map[(i * 4) + 2][j] = (m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0xC) >> 2;
2905               m_sgb_pal_map[(i * 4) + 3][j] = m_sgb_atf_data[(j * 5) + m_sgb_atf + i] & 0x3;
2906            }
2907         }
2908      }
2909         break;
2910      case 0x17:  /* MASK_EN */
2911         m_sgb_window_mask = data[1];
2912         break;
2913      case 0x18:  /* OBJ_TRN */
2914         /* Not Implemnted */
2915         break;
2916      case 0x19:  /* ? */
2917         /* Called by: dkl,dkl2,dkl3,zeldadx
2918          But I don't know what it is for. */
2919         /* Not Implemented */
2920         break;
2921      case 0x1E:  /* Used by bootrom to transfer the gb cart header */
2922         break;
2923      case 0x1F:  /* Used by bootrom to transfer the gb cart header */
2924         break;
2925      default:
2926         logerror( "SGB: Unknown Command 0x%02x!\n", data[0] >> 3 );
2927   }
2928   
2929}
2930
2931
trunk/src/mess/drivers/gb.c
r23879r23880
556556static ADDRESS_MAP_START(gameboy_map, AS_PROGRAM, 8, gb_state )
557557   ADDRESS_MAP_UNMAP_HIGH
558558   AM_RANGE(0x0000, 0x7fff) AM_READWRITE(gb_cart_r, gb_bank_w)
559   AM_RANGE(0x8000, 0x9fff) AM_READWRITE(gb_vram_r, gb_vram_w)  /* 8k VRAM */
559   AM_RANGE(0x8000, 0x9fff) AM_DEVREADWRITE("lcd", gb_lcd_device, vram_r, vram_w)  /* 8k VRAM */
560560   AM_RANGE(0xa000, 0xbfff) AM_READWRITE(gb_ram_r, gb_ram_w)    /* 8k switched RAM bank (cartridge) */
561561   AM_RANGE(0xc000, 0xdfff) AM_RAM                               /* 8k low RAM */
562562   AM_RANGE(0xe000, 0xfdff) AM_READWRITE(gb_echo_r, gb_echo_w)  /* echo RAM */
563   AM_RANGE(0xfe00, 0xfeff) AM_READWRITE(gb_oam_r, gb_oam_w)    /* OAM RAM */
563   AM_RANGE(0xfe00, 0xfeff) AM_DEVREADWRITE("lcd", gb_lcd_device, oam_r, oam_w)    /* OAM RAM */
564564   AM_RANGE(0xff00, 0xff0f) AM_READWRITE(gb_io_r, gb_io_w)      /* I/O */
565565   AM_RANGE(0xff10, 0xff26) AM_DEVREADWRITE("custom", gameboy_sound_device, sound_r, sound_w)      /* sound registers */
566566   AM_RANGE(0xff27, 0xff2f) AM_NOP                     /* unused */
567567   AM_RANGE(0xff30, 0xff3f) AM_DEVREADWRITE("custom", gameboy_sound_device, wave_r, wave_w)        /* Wave ram */
568   AM_RANGE(0xff40, 0xff7f) AM_READWRITE(gb_video_r, gb_io2_w)     /* Video controller & BIOS flip-flop */
568   AM_RANGE(0xff40, 0xff7f) AM_DEVREAD("lcd", gb_lcd_device, video_r) AM_WRITE(gb_io2_w)     /* Video controller & BIOS flip-flop */
569569   AM_RANGE(0xff80, 0xfffe) AM_RAM                     /* High RAM */
570570   AM_RANGE(0xffff, 0xffff) AM_READWRITE(gb_ie_r, gb_ie_w)        /* Interrupt enable register */
571571ADDRESS_MAP_END
r23879r23880
573573static ADDRESS_MAP_START(sgb_map, AS_PROGRAM, 8, gb_state )
574574   ADDRESS_MAP_UNMAP_HIGH
575575   AM_RANGE(0x0000, 0x7fff) AM_READWRITE(gb_cart_r, gb_bank_w)
576   AM_RANGE(0x8000, 0x9fff) AM_READWRITE(gb_vram_r, gb_vram_w)  /* 8k VRAM */
576   AM_RANGE(0x8000, 0x9fff) AM_DEVREADWRITE("lcd", sgb_lcd_device, vram_r, vram_w)  /* 8k VRAM */
577577   AM_RANGE(0xa000, 0xbfff) AM_READWRITE(gb_ram_r, gb_ram_w)    /* 8k switched RAM bank (cartridge) */
578578   AM_RANGE(0xc000, 0xdfff) AM_RAM                               /* 8k low RAM */
579579   AM_RANGE(0xe000, 0xfdff) AM_READWRITE(gb_echo_r, gb_echo_w)  /* echo RAM */
580   AM_RANGE(0xfe00, 0xfeff) AM_READWRITE(gb_oam_r, gb_oam_w)    /* OAM RAM */
580   AM_RANGE(0xfe00, 0xfeff) AM_DEVREADWRITE("lcd", sgb_lcd_device, oam_r, oam_w)    /* OAM RAM */
581581   AM_RANGE(0xff00, 0xff0f) AM_READWRITE(gb_io_r, sgb_io_w)     /* I/O */
582582   AM_RANGE(0xff10, 0xff26) AM_DEVREADWRITE("custom", gameboy_sound_device, sound_r, sound_w)      /* sound registers */
583583   AM_RANGE(0xff27, 0xff2f) AM_NOP                     /* unused */
584584   AM_RANGE(0xff30, 0xff3f) AM_DEVREADWRITE("custom", gameboy_sound_device, wave_r, wave_w)        /* Wave RAM */
585   AM_RANGE(0xff40, 0xff7f) AM_READWRITE(gb_video_r, gb_io2_w)        /* Video controller & BIOS flip-flop */
585   AM_RANGE(0xff40, 0xff7f) AM_DEVREAD("lcd", sgb_lcd_device, video_r) AM_WRITE(gb_io2_w)        /* Video controller & BIOS flip-flop */
586586   AM_RANGE(0xff80, 0xfffe) AM_RAM                     /* High RAM */
587587   AM_RANGE(0xffff, 0xffff) AM_READWRITE(gb_ie_r, gb_ie_w)        /* Interrupt enable register */
588588ADDRESS_MAP_END
r23879r23880
590590static ADDRESS_MAP_START(gbc_map, AS_PROGRAM, 8, gb_state )
591591   ADDRESS_MAP_UNMAP_HIGH
592592   AM_RANGE(0x0000, 0x7fff) AM_READWRITE(gbc_cart_r, gb_bank_w)
593   AM_RANGE(0x8000, 0x9fff) AM_READWRITE(gb_vram_r, gb_vram_w) /* 8k VRAM */
593   AM_RANGE(0x8000, 0x9fff) AM_DEVREADWRITE("lcd", cgb_lcd_device, vram_r, vram_w) /* 8k VRAM */
594594   AM_RANGE(0xa000, 0xbfff) AM_READWRITE(gb_ram_r, gb_ram_w)   /* 8k switched RAM bank (cartridge) */
595595   AM_RANGE(0xc000, 0xcfff) AM_RAM                     /* 4k fixed RAM bank */
596596   AM_RANGE(0xd000, 0xdfff) AM_RAMBANK("cgb_ram")                    /* 4k switched RAM bank */
597597   AM_RANGE(0xe000, 0xfdff) AM_READWRITE(gb_echo_r, gb_echo_w)  /* echo RAM */
598   AM_RANGE(0xfe00, 0xfeff) AM_READWRITE(gb_oam_r, gb_oam_w)  /* OAM RAM */
598   AM_RANGE(0xfe00, 0xfeff) AM_DEVREADWRITE("lcd", cgb_lcd_device, oam_r, oam_w)  /* OAM RAM */
599599   AM_RANGE(0xff00, 0xff0f) AM_READWRITE(gb_io_r, gb_io_w)        /* I/O */
600600   AM_RANGE(0xff10, 0xff26) AM_DEVREADWRITE("custom", gameboy_sound_device, sound_r, sound_w)      /* sound controller */
601601   AM_RANGE(0xff27, 0xff2f) AM_NOP                     /* unused */
602602   AM_RANGE(0xff30, 0xff3f) AM_DEVREADWRITE("custom", gameboy_sound_device, wave_r, wave_w)        /* Wave RAM */
603   AM_RANGE(0xff40, 0xff7f) AM_READWRITE(gbc_io2_r, gbc_io2_w)        /* Other I/O and video controller */
603   AM_RANGE(0xff40, 0xff7f) AM_DEVREAD("lcd", cgb_lcd_device, video_r) AM_WRITE(gbc_io2_w)        /* Other I/O and video controller */
604604   AM_RANGE(0xff80, 0xfffe) AM_RAM                     /* high RAM */
605605   AM_RANGE(0xffff, 0xffff) AM_READWRITE(gb_ie_r, gb_ie_w)        /* Interrupt enable register */
606606ADDRESS_MAP_END
r23879r23880
608608static ADDRESS_MAP_START(megaduck_map, AS_PROGRAM, 8, megaduck_state )
609609   ADDRESS_MAP_UNMAP_HIGH
610610   AM_RANGE(0x0000, 0x7fff) AM_READWRITE(cart_r, bank1_w)
611   AM_RANGE(0x8000, 0x9fff) AM_READWRITE(gb_vram_r, gb_vram_w)        /* 8k VRAM */
611   AM_RANGE(0x8000, 0x9fff) AM_DEVREADWRITE("lcd", gb_lcd_device, vram_r, vram_w)        /* 8k VRAM */
612612   AM_RANGE(0xa000, 0xafff) AM_NOP                         /* unused? */
613613   AM_RANGE(0xb000, 0xb000) AM_WRITE(bank2_w)
614614   AM_RANGE(0xb001, 0xbfff) AM_NOP                         /* unused? */
615615   AM_RANGE(0xc000, 0xfe9f) AM_RAM                         /* 8k low RAM, echo RAM */
616   AM_RANGE(0xfe00, 0xfeff) AM_READWRITE(gb_oam_r, gb_oam_w)      /* OAM RAM */
616   AM_RANGE(0xfe00, 0xfeff) AM_DEVREADWRITE("lcd", gb_lcd_device, oam_r, oam_w)      /* OAM RAM */
617617   AM_RANGE(0xff00, 0xff0f) AM_READWRITE(gb_io_r, gb_io_w)            /* I/O */
618618   AM_RANGE(0xff10, 0xff1f) AM_READWRITE(megaduck_video_r, megaduck_video_w)  /* video controller */
619619   AM_RANGE(0xff20, 0xff2f) AM_READWRITE(megaduck_sound_r1, megaduck_sound_w1) /* sound controller pt1 */
r23879r23880
687687   MCFG_SCREEN_ADD("screen", LCD)
688688   MCFG_SCREEN_REFRESH_RATE(DMG_FRAMES_PER_SECOND)
689689   MCFG_SCREEN_VBLANK_TIME(0)
690   MCFG_SCREEN_UPDATE_DRIVER(gb_state, screen_update)
690   MCFG_SCREEN_UPDATE_DEVICE("lcd", gb_lcd_device, screen_update)
691691   MCFG_DEFAULT_LAYOUT(layout_lcd)
692692//  MCFG_SCREEN_SIZE(20*8, 18*8)
693693   MCFG_SCREEN_SIZE( 458, 154 )
r23879r23880
697697   MCFG_PALETTE_LENGTH(4)
698698   MCFG_PALETTE_INIT_OVERRIDE(gb_state,gb)
699699
700   MCFG_GB_LCD_DMG_ADD( "lcd" )
701
700702   /* sound hardware */
701703   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
702704   MCFG_SOUND_ADD("custom", GAMEBOY, 0)
r23879r23880
728730   MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
729731   MCFG_PALETTE_LENGTH(32768)
730732   MCFG_PALETTE_INIT_OVERRIDE(gb_state,sgb)
733
734   MCFG_DEVICE_REMOVE("lcd")
735   MCFG_GB_LCD_SGB_ADD( "lcd" )
731736MACHINE_CONFIG_END
732737
733738static MACHINE_CONFIG_DERIVED( gbpocket, gameboy )
r23879r23880
739744   MCFG_MACHINE_START_OVERRIDE(gb_state, gbpocket)
740745   MCFG_MACHINE_RESET_OVERRIDE(gb_state, gbpocket)
741746   MCFG_PALETTE_INIT_OVERRIDE(gb_state,gbp)
747
748   MCFG_DEVICE_REMOVE("lcd")
749   MCFG_GB_LCD_MGB_ADD( "lcd" )
742750MACHINE_CONFIG_END
743751
744752static MACHINE_CONFIG_DERIVED( gbcolor, gameboy )
r23879r23880
752760   MCFG_PALETTE_LENGTH(32768)
753761   MCFG_PALETTE_INIT_OVERRIDE(gb_state,gbc)
754762
763   MCFG_DEVICE_REMOVE("lcd")
764   MCFG_GB_LCD_CGB_ADD( "lcd" )
765
755766   /* internal ram */
756767   MCFG_RAM_ADD(RAM_TAG)
757768   MCFG_RAM_DEFAULT_SIZE("48K") /* 2 pages of 8KB VRAM, 8 pages of 4KB RAM */
r23879r23880
779790   MCFG_MACHINE_START_OVERRIDE(megaduck_state, megaduck )
780791   MCFG_MACHINE_RESET_OVERRIDE(megaduck_state, megaduck )
781792
782   MCFG_SCREEN_UPDATE_DRIVER(gb_state, screen_update)
793   MCFG_SCREEN_UPDATE_DEVICE("lcd", gb_lcd_device, screen_update)
783794   MCFG_SCREEN_SIZE(20*8, 18*8)
784795   MCFG_SCREEN_VISIBLE_AREA(0*8, 20*8-1, 0*8, 18*8-1)
785796
r23879r23880
788799   MCFG_PALETTE_LENGTH(4)
789800   MCFG_PALETTE_INIT_OVERRIDE(megaduck_state,megaduck)
790801
802   MCFG_GB_LCD_DMG_ADD( "lcd" )
803
791804   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
792805   MCFG_SOUND_ADD("custom", GAMEBOY, 0)
793806   MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
trunk/src/mess/machine/gb.c
r23879r23880
135135
136136void gb_state::save_sgb_only()
137137{
138   save_item(NAME(m_sgb_pal));
139   save_item(NAME(m_sgb_tile_map));
140   save_item(NAME(m_sgb_window_mask));
141   save_item(NAME(m_sgb_pal_data));
142   save_item(NAME(m_sgb_atf_data));
143138   save_item(NAME(m_sgb_packets));
144139   save_item(NAME(m_sgb_bitcount));
145140   save_item(NAME(m_sgb_bytecount));
r23879r23880
148143   save_item(NAME(m_sgb_controller_no));
149144   save_item(NAME(m_sgb_controller_mode));
150145   save_item(NAME(m_sgb_data));
151   save_item(NAME(m_sgb_atf));
152
153   save_pointer(NAME(m_sgb_tile_data), 0x2000);
154   save_item(NAME(m_sgb_pal_map));
155146}
156147
157148
r23879r23880
184175   m_gb_serial_timer->enable( 0 );
185176
186177   save_gb_base();
187   gb_video_start(GB_VIDEO_DMG);
188178}
189179
190180MACHINE_START_MEMBER(gb_state,gbpocket)
r23879r23880
194184   m_gb_serial_timer->enable( 0 );
195185
196186   save_gb_base();
197   gb_video_start(GB_VIDEO_MGB);
198187}
199188
200189MACHINE_START_MEMBER(gb_state,gbc)
r23879r23880
208197
209198   save_gb_base();
210199   save_gbc_only();
211   gb_video_start(GB_VIDEO_CGB);
212200}
213201
214202
215203MACHINE_START_MEMBER(gb_state,sgb)
216204{
217205   m_sgb_packets = -1;
218   m_sgb_tile_data = auto_alloc_array_clear(machine(), UINT8, 0x2000);
219206
220207   /* Allocate the serial timer, and disable it */
221208   m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
r23879r23880
223210
224211   save_gb_base();
225212   save_sgb_only();
226   gb_video_start(GB_VIDEO_SGB);
213
214   if (m_cartslot && m_cartslot->get_sgb_hack())
215      machine().device<sgb_lcd_device>("lcd")->set_sgb_hack(TRUE);
227216}
228217
229218MACHINE_RESET_MEMBER(gb_state,gb)
230219{
231220   gb_init();
232221
233   gb_video_reset(GB_VIDEO_DMG);
234
235222   /* Enable BIOS rom */
236223   m_bios_disable = 0;
237224
r23879r23880
242229{
243230   gb_init();
244231
245   gb_video_reset(GB_VIDEO_MGB);
246
247232   gb_init_regs();
248233
249234   m_bios_disable = 1;
r23879r23880
260245{
261246   gb_init();
262247
263   gb_video_reset( GB_VIDEO_CGB );
264
265248   gb_init_regs();
266249
267250   /* Enable BIOS rom */
r23879r23880
275258{
276259   gb_init();
277260
278   gb_video_reset(GB_VIDEO_SGB);
279
280261   gb_init_regs();
281262
282
283263   /* Enable BIOS rom */
284264   m_bios_disable = 0;
285265
286   memset(m_sgb_tile_data, 0, 0x2000);
287
288   m_sgb_window_mask = 0;
289   memset(m_sgb_pal_map, 0, sizeof(m_sgb_pal_map));
290   memset(m_sgb_atf_data, 0, sizeof(m_sgb_atf_data));
291
292266   m_divcount = 0x0004;
293267}
294268
r23879r23880
376350      //printf("here again?\n");
377351   }
378352   else
379      gb_video_w(space, offset, data);
353      machine().device<gb_lcd_device>("lcd")->video_w(space, offset, data);
380354}
381355
382356#ifdef MAME_DEBUG
r23879r23880
473447                  m_sgb_packets = sgb_data[0] & 0x07;
474448                  m_sgb_start = 0;
475449               }
476               if (m_sgb_bytecount == (m_sgb_packets << 4) )
450               if (m_sgb_bytecount == (m_sgb_packets << 4))
477451               {
478                  switch( sgb_data[0] >> 3 )
452                  switch (sgb_data[0] >> 3)
479453                  {
480                     case 0x00:  /* PAL01 */
481                        m_sgb_pal[0*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
482                        m_sgb_pal[0*4 + 1] = sgb_data[3] | (sgb_data[4] << 8);
483                        m_sgb_pal[0*4 + 2] = sgb_data[5] | (sgb_data[6] << 8);
484                        m_sgb_pal[0*4 + 3] = sgb_data[7] | (sgb_data[8] << 8);
485                        m_sgb_pal[1*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
486                        m_sgb_pal[1*4 + 1] = sgb_data[9] | (sgb_data[10] << 8);
487                        m_sgb_pal[1*4 + 2] = sgb_data[11] | (sgb_data[12] << 8);
488                        m_sgb_pal[1*4 + 3] = sgb_data[13] | (sgb_data[14] << 8);
489                        break;
490                     case 0x01:  /* PAL23 */
491                        m_sgb_pal[2*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
492                        m_sgb_pal[2*4 + 1] = sgb_data[3] | (sgb_data[4] << 8);
493                        m_sgb_pal[2*4 + 2] = sgb_data[5] | (sgb_data[6] << 8);
494                        m_sgb_pal[2*4 + 3] = sgb_data[7] | (sgb_data[8] << 8);
495                        m_sgb_pal[3*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
496                        m_sgb_pal[3*4 + 1] = sgb_data[9] | (sgb_data[10] << 8);
497                        m_sgb_pal[3*4 + 2] = sgb_data[11] | (sgb_data[12] << 8);
498                        m_sgb_pal[3*4 + 3] = sgb_data[13] | (sgb_data[14] << 8);
499                        break;
500                     case 0x02:  /* PAL03 */
501                        m_sgb_pal[0*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
502                        m_sgb_pal[0*4 + 1] = sgb_data[3] | (sgb_data[4] << 8);
503                        m_sgb_pal[0*4 + 2] = sgb_data[5] | (sgb_data[6] << 8);
504                        m_sgb_pal[0*4 + 3] = sgb_data[7] | (sgb_data[8] << 8);
505                        m_sgb_pal[3*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
506                        m_sgb_pal[3*4 + 1] = sgb_data[9] | (sgb_data[10] << 8);
507                        m_sgb_pal[3*4 + 2] = sgb_data[11] | (sgb_data[12] << 8);
508                        m_sgb_pal[3*4 + 3] = sgb_data[13] | (sgb_data[14] << 8);
509                        break;
510                     case 0x03:  /* PAL12 */
511                        m_sgb_pal[1*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
512                        m_sgb_pal[1*4 + 1] = sgb_data[3] | (sgb_data[4] << 8);
513                        m_sgb_pal[1*4 + 2] = sgb_data[5] | (sgb_data[6] << 8);
514                        m_sgb_pal[1*4 + 3] = sgb_data[7] | (sgb_data[8] << 8);
515                        m_sgb_pal[2*4 + 0] = sgb_data[1] | (sgb_data[2] << 8);
516                        m_sgb_pal[2*4 + 1] = sgb_data[9] | (sgb_data[10] << 8);
517                        m_sgb_pal[2*4 + 2] = sgb_data[11] | (sgb_data[12] << 8);
518                        m_sgb_pal[2*4 + 3] = sgb_data[13] | (sgb_data[14] << 8);
519                        break;
520                     case 0x04:  /* ATTR_BLK */
521                        {
522                           UINT8 I, J, K, o;
523                           for( K = 0; K < sgb_data[1]; K++ )
524                           {
525                              o = K * 6;
526                              if( sgb_data[o + 2] & 0x1 )
527                              {
528                                 for( I = sgb_data[ o + 4]; I <= sgb_data[o + 6]; I++ )
529                                 {
530                                    for( J = sgb_data[o + 5]; J <= sgb_data[o + 7]; J++ )
531                                    {
532                                       m_sgb_pal_map[I][J] = sgb_data[o + 3] & 0x3;
533                                    }
534                                 }
535                              }
536                           }
537                        }
538                        break;
539                     case 0x05:  /* ATTR_LIN */
540                        {
541                           UINT8 J, K;
542                           if( sgb_data[1] > 15 )
543                              sgb_data[1] = 15;
544                           for( K = 0; K < sgb_data[1]; K++ )
545                           {
546                              if( sgb_data[K + 1] & 0x80 )
547                              {
548                                 for( J = 0; J < 20; J++ )
549                                 {
550                                    m_sgb_pal_map[J][sgb_data[K + 1] & 0x1f] = (sgb_data[K + 1] & 0x60) >> 5;
551                                 }
552                              }
553                              else
554                              {
555                                 for( J = 0; J < 18; J++ )
556                                 {
557                                    m_sgb_pal_map[sgb_data[K + 1] & 0x1f][J] = (sgb_data[K + 1] & 0x60) >> 5;
558                                 }
559                              }
560                           }
561                        }
562                        break;
563                     case 0x06:  /* ATTR_DIV */
564                        {
565                           UINT8 I, J;
566                           if( sgb_data[1] & 0x40 ) /* Vertical */
567                           {
568                              for( I = 0; I < sgb_data[2]; I++ )
569                              {
570                                 for( J = 0; J < 20; J++ )
571                                 {
572                                    m_sgb_pal_map[J][I] = (sgb_data[1] & 0xC) >> 2;
573                                 }
574                              }
575                              for( J = 0; J < 20; J++ )
576                              {
577                                 m_sgb_pal_map[J][sgb_data[2]] = (sgb_data[1] & 0x30) >> 4;
578                              }
579                              for( I = sgb_data[2] + 1; I < 18; I++ )
580                              {
581                                 for( J = 0; J < 20; J++ )
582                                 {
583                                    m_sgb_pal_map[J][I] = sgb_data[1] & 0x3;
584                                 }
585                              }
586                           }
587                           else /* Horizontal */
588                           {
589                              for( I = 0; I < sgb_data[2]; I++ )
590                              {
591                                 for( J = 0; J < 18; J++ )
592                                 {
593                                    m_sgb_pal_map[I][J] = (sgb_data[1] & 0xC) >> 2;
594                                 }
595                              }
596                              for( J = 0; J < 18; J++ )
597                              {
598                                 m_sgb_pal_map[sgb_data[2]][J] = (sgb_data[1] & 0x30) >> 4;
599                              }
600                              for( I = sgb_data[2] + 1; I < 20; I++ )
601                              {
602                                 for( J = 0; J < 18; J++ )
603                                 {
604                                    m_sgb_pal_map[I][J] = sgb_data[1] & 0x3;
605                                 }
606                              }
607                           }
608                        }
609                        break;
610                     case 0x07:  /* ATTR_CHR */
611                        {
612                           UINT16 I, sets;
613                           UINT8 x, y;
614                           sets = (sgb_data[3] | (sgb_data[4] << 8) );
615                           if( sets > 360 )
616                              sets = 360;
617                           sets >>= 2;
618                           sets += 6;
619                           x = sgb_data[1];
620                           y = sgb_data[2];
621                           if( sgb_data[5] ) /* Vertical */
622                           {
623                              for( I = 6; I < sets; I++ )
624                              {
625                                 m_sgb_pal_map[x][y++] = (sgb_data[I] & 0xC0) >> 6;
626                                 if( y > 17 )
627                                 {
628                                    y = 0;
629                                    x++;
630                                    if( x > 19 )
631                                       x = 0;
632                                 }
633
634                                 m_sgb_pal_map[x][y++] = (sgb_data[I] & 0x30) >> 4;
635                                 if( y > 17 )
636                                 {
637                                    y = 0;
638                                    x++;
639                                    if( x > 19 )
640                                       x = 0;
641                                 }
642
643                                 m_sgb_pal_map[x][y++] = (sgb_data[I] & 0xC) >> 2;
644                                 if( y > 17 )
645                                 {
646                                    y = 0;
647                                    x++;
648                                    if( x > 19 )
649                                       x = 0;
650                                 }
651
652                                 m_sgb_pal_map[x][y++] = sgb_data[I] & 0x3;
653                                 if( y > 17 )
654                                 {
655                                    y = 0;
656                                    x++;
657                                    if( x > 19 )
658                                       x = 0;
659                                 }
660                              }
661                           }
662                           else /* horizontal */
663                           {
664                              for( I = 6; I < sets; I++ )
665                              {
666                                 m_sgb_pal_map[x++][y] = (sgb_data[I] & 0xC0) >> 6;
667                                 if( x > 19 )
668                                 {
669                                    x = 0;
670                                    y++;
671                                    if( y > 17 )
672                                       y = 0;
673                                 }
674
675                                 m_sgb_pal_map[x++][y] = (sgb_data[I] & 0x30) >> 4;
676                                 if( x > 19 )
677                                 {
678                                    x = 0;
679                                    y++;
680                                    if( y > 17 )
681                                       y = 0;
682                                 }
683
684                                 m_sgb_pal_map[x++][y] = (sgb_data[I] & 0xC) >> 2;
685                                 if( x > 19 )
686                                 {
687                                    x = 0;
688                                    y++;
689                                    if( y > 17 )
690                                       y = 0;
691                                 }
692
693                                 m_sgb_pal_map[x++][y] = sgb_data[I] & 0x3;
694                                 if( x > 19 )
695                                 {
696                                    x = 0;
697                                    y++;
698                                    if( y > 17 )
699                                       y = 0;
700                                 }
701                              }
702                           }
703                        }
704                        break;
705                     case 0x08:  /* SOUND */
706                        /* This command enables internal sound effects */
707                        /* Not Implemented */
708                        break;
709                     case 0x09:  /* SOU_TRN */
710                        /* This command sends data to the SNES sound processor.
711                           We'll need to emulate that for this to be used */
712                        /* Not Implemented */
713                        break;
714                     case 0x0A:  /* PAL_SET */
715                        {
716                           UINT16 index_, J, I;
717
718                           /* Palette 0 */
719                           index_ = (UINT16)(sgb_data[1] | (sgb_data[2] << 8)) * 4;
720                           m_sgb_pal[0] = m_sgb_pal_data[index_];
721                           m_sgb_pal[1] = m_sgb_pal_data[index_ + 1];
722                           m_sgb_pal[2] = m_sgb_pal_data[index_ + 2];
723                           m_sgb_pal[3] = m_sgb_pal_data[index_ + 3];
724                           /* Palette 1 */
725                           index_ = (UINT16)(sgb_data[3] | (sgb_data[4] << 8)) * 4;
726                           m_sgb_pal[4] = m_sgb_pal_data[index_];
727                           m_sgb_pal[5] = m_sgb_pal_data[index_ + 1];
728                           m_sgb_pal[6] = m_sgb_pal_data[index_ + 2];
729                           m_sgb_pal[7] = m_sgb_pal_data[index_ + 3];
730                           /* Palette 2 */
731                           index_ = (UINT16)(sgb_data[5] | (sgb_data[6] << 8)) * 4;
732                           m_sgb_pal[8] = m_sgb_pal_data[index_];
733                           m_sgb_pal[9] = m_sgb_pal_data[index_ + 1];
734                           m_sgb_pal[10] = m_sgb_pal_data[index_ + 2];
735                           m_sgb_pal[11] = m_sgb_pal_data[index_ + 3];
736                           /* Palette 3 */
737                           index_ = (UINT16)(sgb_data[7] | (sgb_data[8] << 8)) * 4;
738                           m_sgb_pal[12] = m_sgb_pal_data[index_];
739                           m_sgb_pal[13] = m_sgb_pal_data[index_ + 1];
740                           m_sgb_pal[14] = m_sgb_pal_data[index_ + 2];
741                           m_sgb_pal[15] = m_sgb_pal_data[index_ + 3];
742                           /* Attribute File */
743                           if( sgb_data[9] & 0x40 )
744                              m_sgb_window_mask = 0;
745                           m_sgb_atf = (sgb_data[9] & 0x3f) * (18 * 5);
746                           if( sgb_data[9] & 0x80 )
747                           {
748                              for( J = 0; J < 18; J++ )
749                              {
750                                 for( I = 0; I < 5; I++ )
751                                 {
752                                    m_sgb_pal_map[I * 4][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0xC0) >> 6;
753                                    m_sgb_pal_map[(I * 4) + 1][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0x30) >> 4;
754                                    m_sgb_pal_map[(I * 4) + 2][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0xC) >> 2;
755                                    m_sgb_pal_map[(I * 4) + 3][J] = m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0x3;
756                                 }
757                              }
758                           }
759                        }
760                        break;
761                     case 0x0B:  /* PAL_TRN */
762                        {
763                           UINT16 I, col;
764
765                           for( I = 0; I < 2048; I++ )
766                           {
767                              col = (m_lcd.gb_vram[0x0800 + (I*2) + 1] << 8) | m_lcd.gb_vram[0x0800 + (I*2)];
768                              m_sgb_pal_data[I] = col;
769                           }
770                        }
771                        break;
772                     case 0x0C:  /* ATRC_EN */
773                        /* Not Implemented */
774                        break;
775                     case 0x0D:  /* TEST_EN */
776                        /* Not Implemented */
777                        break;
778                     case 0x0E:  /* ICON_EN */
779                        /* Not Implemented */
780                        break;
781                     case 0x0F:  /* DATA_SND */
782                        /* Not Implemented */
783                        break;
784                     case 0x10:  /* DATA_TRN */
785                        /* Not Implemented */
786                        break;
787454                     case 0x11:  /* MLT_REQ - Multi controller request */
788455                        if (sgb_data[1] == 0x00)
789456                           m_sgb_controller_mode = 0;
790457                        else if (sgb_data[1] == 0x01)
791458                           m_sgb_controller_mode = 2;
792459                        break;
793                     case 0x12:  /* JUMP */
794                        /* Not Implemented */
795                        break;
796                     case 0x13:  /* CHR_TRN */
797                        if (sgb_data[1] & 0x1)
798                           memcpy(m_sgb_tile_data + 4096, m_lcd.gb_vram + 0x0800, 4096);
799                        else
800                           memcpy(m_sgb_tile_data, m_lcd.gb_vram + 0x0800, 4096);
801                        break;
802                     case 0x14:  /* PCT_TRN */
803                        {
804                           int I;
805                           UINT16 col;
806                           if (m_cartslot && m_cartslot->get_sgb_hack())
807                           {
808                              memcpy(m_sgb_tile_map, m_lcd.gb_vram + 0x1000, 2048);
809                              for( I = 0; I < 64; I++ )
810                              {
811                                 col = (m_lcd.gb_vram[0x0800 + (I*2) + 1 ] << 8) | m_lcd.gb_vram[0x0800 + (I*2)];
812                                 m_sgb_pal[SGB_BORDER_PAL_OFFSET + I] = col;
813                              }
814                           }
815                           else /* Do things normally */
816                           {
817                              memcpy(m_sgb_tile_map, m_lcd.gb_vram + 0x0800, 2048);
818                              for( I = 0; I < 64; I++ )
819                              {
820                                 col = (m_lcd.gb_vram[0x1000 + (I*2) + 1] << 8) | m_lcd.gb_vram[0x1000 + (I*2)];
821                                 m_sgb_pal[SGB_BORDER_PAL_OFFSET + I] = col;
822                              }
823                           }
824                        }
825                        break;
826                     case 0x15:  /* ATTR_TRN */
827                        memcpy( m_sgb_atf_data, m_lcd.gb_vram + 0x0800, 4050 );
828                        break;
829                     case 0x16:  /* ATTR_SET */
830                        {
831                           UINT8 J, I;
832
833                           /* Attribute File */
834                           if( sgb_data[1] & 0x40 )
835                              m_sgb_window_mask = 0;
836                           m_sgb_atf = (sgb_data[1] & 0x3f) * (18 * 5);
837                           for( J = 0; J < 18; J++ )
838                           {
839                              for( I = 0; I < 5; I++ )
840                              {
841                                 m_sgb_pal_map[I * 4][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0xC0) >> 6;
842                                 m_sgb_pal_map[(I * 4) + 1][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0x30) >> 4;
843                                 m_sgb_pal_map[(I * 4) + 2][J] = (m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0xC) >> 2;
844                                 m_sgb_pal_map[(I * 4) + 3][J] = m_sgb_atf_data[(J * 5) + m_sgb_atf + I] & 0x3;
845                              }
846                           }
847                        }
848                        break;
849                     case 0x17:  /* MASK_EN */
850                        m_sgb_window_mask = sgb_data[1];
851                        break;
852                     case 0x18:  /* OBJ_TRN */
853                        /* Not Implemnted */
854                        break;
855                     case 0x19:  /* ? */
856                        /* Called by: dkl,dkl2,dkl3,zeldadx
857                           But I don't know what it is for. */
858                        /* Not Implemented */
859                        break;
860                     case 0x1E:  /* Used by bootrom to transfer the gb cart header */
861                        break;
862                     case 0x1F:  /* Used by bootrom to transfer the gb cart header */
863                        break;
864460                     default:
865                        logerror( "SGB: Unknown Command 0x%02x!\n", sgb_data[0] >> 3 );
461                        machine().device<sgb_lcd_device>("lcd")->sgb_io_write_pal(sgb_data[0] >> 3, &sgb_data[0]);
462                        break;                       
866463                  }
867
868464                  m_sgb_start = 0;
869465                  m_sgb_bytecount = 0;
870466                  m_sgb_packets = -1;
r23879r23880
1040636      default:
1041637         break;
1042638   }
1043   gbc_video_w( space, offset, data );
639   machine().device<cgb_lcd_device>("lcd")->video_w(space, offset, data);
1044640}
1045641
1046642READ8_MEMBER(gb_state::gbc_io2_r)
r23879r23880
1056652   default:
1057653      break;
1058654   }
1059   return gbc_video_r( space, offset );
655   return machine().device<cgb_lcd_device>("lcd")->video_r(space, offset);
1060656}
1061657
1062658/****************************************************************************
r23879r23880
1072668   m_gb_serial_timer->enable( 0 );
1073669
1074670   save_gb_base();
1075   gb_video_start(GB_VIDEO_DMG);
1076671}
1077672
1078673MACHINE_RESET_MEMBER(megaduck_state,megaduck)
r23879r23880
1081676   gb_init();
1082677
1083678   m_bios_disable = 1;
1084
1085   gb_video_reset( GB_VIDEO_DMG );
1086679}
1087680
1088681/*
r23879r23880
1125718{
1126719   UINT8 data;
1127720
1128   if ( (offset & 0x0C) && ((offset & 0x0C) ^ 0x0C) )
721   if ((offset & 0x0C) && ((offset & 0x0C) ^ 0x0C))
1129722   {
1130723      offset ^= 0x0C;
1131724   }
1132   data = gb_video_r( space, offset );
725   data = machine().device<gb_lcd_device>("lcd")->video_r(space, offset);
1133726   if ( offset )
1134727      return data;
1135728   return BITSWAP8(data,7,0,5,4,6,3,2,1);
r23879r23880
1137730
1138731WRITE8_MEMBER(megaduck_state::megaduck_video_w)
1139732{
1140   if ( !offset )
733   if (!offset)
1141734   {
1142735      data = BITSWAP8(data,7,3,5,4,2,1,0,6);
1143736   }
1144   if ( (offset & 0x0C) && ((offset & 0x0C) ^ 0x0C) )
737   if ((offset & 0x0C) && ((offset & 0x0C) ^ 0x0C))
1145738   {
1146739      offset ^= 0x0C;
1147740   }
1148   gb_video_w(space, offset, data );
741   machine().device<gb_lcd_device>("lcd")->video_w(space, offset, data);
1149742}
1150743
1151744/* Map megaduck audio offset to game boy audio offsets */

Previous 199869 Revisions Next


© 1997-2024 The MAME Team