1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /***************************************************************************
4
5 Sony PocketStation
6
7 PocketStation games were dowloaded from PS1 games into flash RAM after
8 the unit had been inserted in the memory card slot, and so this should
9 be emulated alongside the PS1. However, as many flash dumps exist, it
10 is possible to emulate the PocketStation in the meantime.
11
12 CPU: ARM7T (32 bit RISC Processor)
13 Memory: 2Kbytes of SRAM, 128Kbytes of FlashROM
14 Graphics: 32x32 monochrome LCD
15 Sound: 1 12-bit PCM channel
16 Input: 5 input buttons, 1 reset button
17 Infrared communication: Bi-directional and uni-directional comms
18 Other: 1 LED indicator
19
20 Currently, a handful of games run, but some die due to odd hardware
21 issues.
22
23 To start a game:
24 - Wait for the set-date screen to appear
25 - Press Down
26 - Set date with directional controls (optional)
27 - Press Button 1, wait, press Button 1, press Right, game starts
28
29 If you do nothing for about 20 secs, it turns itself off (screen goes white).
30
31 ****************************************************************************/
32
33 #include "emu.h"
34 #include "bus/generic/carts.h"
35 #include "bus/generic/slot.h"
36 #include "cpu/arm7/arm7.h"
37 #include "cpu/arm7/arm7core.h"
38 #include "sound/dac.h"
39 #include "emupal.h"
40 #include "screen.h"
41 #include "speaker.h"
42
43 #define LOG_UNKNOWN (1 << 0)
44 #define LOG_FTLB (1 << 1)
45 #define LOG_IRQS (1 << 2)
46 #define LOG_INTC (1 << 3)
47 #define LOG_TIMER (1 << 4)
48 #define LOG_CLOCK (1 << 5)
49 #define LOG_RTC (1 << 6)
50 #define LOG_LCD (1 << 7)
51 #define LOG_AUDIO (1 << 8)
52 #define LOG_ALL (LOG_UNKNOWN | LOG_FTLB | LOG_IRQS | LOG_INTC | LOG_TIMER | LOG_CLOCK | LOG_RTC | LOG_LCD | LOG_AUDIO)
53 #define LOG_DEFAULT LOG_ALL
54
55 #define VERBOSE (0)
56 #include "logmacro.h"
57
58 class pockstat_state : public driver_device
59 {
60 public:
pockstat_state(const machine_config & mconfig,device_type type,const char * tag)61 pockstat_state(const machine_config &mconfig, device_type type, const char *tag) :
62 driver_device(mconfig, type, tag),
63 m_lcd_buffer(*this, "lcd_buffer"),
64 m_maincpu(*this, "maincpu"),
65 m_cart(*this, "cartslot")
66 { }
67
68 void pockstat(machine_config &config);
69
70 DECLARE_INPUT_CHANGED_MEMBER(input_update);
71
72 private:
73 virtual void machine_start() override;
74 virtual void machine_reset() override;
75
76 void mem_map(address_map &map);
77
78 uint32_t screen_update_pockstat(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
79
80 void set_interrupt_line(uint32_t line, int state);
81 uint32_t get_interrupt_line(uint32_t line);
82
83 void timer_start(int index);
84
85 required_shared_ptr<uint32_t> m_lcd_buffer;
86 required_device<cpu_device> m_maincpu;
87 required_device<generic_slot_device> m_cart;
88 memory_region *m_cart_rom;
89
90 static constexpr uint32_t TIMER_COUNT = 3;
91
92 enum : uint32_t
93 {
94 CLOCK_STEADY = 0x10
95 };
96
97 enum
98 {
99 INT_BTN_ACTION = 0x00000001, // "Action button"
100 INT_BTN_RIGHT = 0x00000002, // "Right button"
101 INT_BTN_LEFT = 0x00000004, // "Left button"
102 INT_BTN_DOWN = 0x00000008, // "Down button"
103 INT_BTN_UP = 0x00000010, // "Up button"
104 INT_UNKNOWN = 0x00000020, // "Unknown"
105 INT_COM = 0x00000040, // "COM" ???
106 INT_TIMER0 = 0x00000080, // "Timer 0"
107 INT_TIMER1 = 0x00000100, // "Timer 1"
108 INT_RTC = 0x00000200, // "RTC"
109 INT_BATTERY = 0x00000400, // "Battery Monitor"
110 INT_IOP = 0x00000800, // "IOP"
111 INT_IRDA = 0x00001000, // "IrDA"
112 INT_TIMER2 = 0x00002000, // "Timer 2"
113 INT_IRQ_MASK = 0x00001fbf,
114 INT_FIQ_MASK = 0x00002040,
115 INT_STATUS_MASK = 0x0000021f
116 };
117
118 struct ftlb_regs_t
119 {
120 uint32_t control;
121 uint32_t stat;
122 uint32_t valid;
123 uint32_t wait1;
124 uint32_t wait2;
125 uint32_t entry[16];
126 uint32_t serial;
127 } m_ftlb_regs;
128
129 struct intc_regs_t
130 {
131 uint32_t hold;
132 uint32_t status;
133 uint32_t enable;
134 uint32_t mask;
135 } m_intc_regs;
136
137 struct timer_t
138 {
139 uint32_t period;
140 uint32_t count;
141 uint32_t control;
142 emu_timer *timer;
143 } m_timers[TIMER_COUNT];
144
145 struct clock_regs_t
146 {
147 uint32_t mode;
148 uint32_t control;
149 } m_clock_regs;
150
151 struct rtc_regs_t
152 {
153 uint32_t mode;
154 uint32_t control;
155 uint32_t time;
156 uint32_t date;
157 emu_timer *timer;
158 } m_rtc_regs;
159
160 uint32_t m_lcd_control;
161 int32_t m_flash_write_enable_count;
162 int32_t m_flash_write_count;
163
164 uint32_t ftlb_r(offs_t offset, uint32_t mem_mask = ~0);
165 void ftlb_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
166 uint32_t intc_r(offs_t offset, uint32_t mem_mask = ~0);
167 void intc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
168 uint32_t timer_r(offs_t offset, uint32_t mem_mask = ~0);
169 void timer_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
170 uint32_t clock_r(offs_t offset, uint32_t mem_mask = ~0);
171 void clock_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
172 uint32_t rtc_r(offs_t offset, uint32_t mem_mask = ~0);
173 void rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
174 uint32_t lcd_r(offs_t offset, uint32_t mem_mask = ~0);
175 void lcd_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
176 uint32_t rombank_r(offs_t offset, uint32_t mem_mask = ~0);
177 uint32_t flash_r(offs_t offset, uint32_t mem_mask = ~0);
178 void flash_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
179 uint32_t audio_r(offs_t offset, uint32_t mem_mask = ~0);
180 void audio_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
181 TIMER_CALLBACK_MEMBER(timer_tick);
182 TIMER_CALLBACK_MEMBER(rtc_tick);
183 DECLARE_DEVICE_IMAGE_LOAD_MEMBER(flash_load);
184
185 static const int CPU_FREQ[16];
186 };
187
188 const int pockstat_state::CPU_FREQ[16] =
189 {
190 0x00f800,
191 0x01f000,
192 0x03e000,
193 0x07c000,
194 0x0f8000,
195 0x1e8000,
196 0x3d0000,
197 0x7a0000,
198 0x7a0000,
199 0x7a0000,
200 0x7a0000,
201 0x7a0000,
202 0x7a0000,
203 0x7a0000,
204 0x7a0000,
205 0x7a0000
206 };
207
ftlb_r(offs_t offset,uint32_t mem_mask)208 uint32_t pockstat_state::ftlb_r(offs_t offset, uint32_t mem_mask)
209 {
210 switch(offset)
211 {
212 case 0x0000/4:
213 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Control = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.control, mem_mask);
214 return m_ftlb_regs.control | 1; // ???
215 case 0x0004/4:
216 LOGMASKED(LOG_FTLB, "%s: Unknown (F_STAT) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.stat, mem_mask);
217 return m_ftlb_regs.stat;
218 case 0x0008/4:
219 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Valid Tag = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.valid, mem_mask);
220 return m_ftlb_regs.valid;
221 case 0x000c/4:
222 LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT1) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.wait1, mem_mask);
223 return m_ftlb_regs.wait1;
224 case 0x0010/4:
225 LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT2) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.wait2 | 0x04, mem_mask);
226 return m_ftlb_regs.wait2 | 0x04;
227 case 0x0100/4:
228 case 0x0104/4:
229 case 0x0108/4:
230 case 0x010c/4:
231 case 0x0110/4:
232 case 0x0114/4:
233 case 0x0118/4:
234 case 0x011c/4:
235 case 0x0120/4:
236 case 0x0124/4:
237 case 0x0128/4:
238 case 0x012c/4:
239 case 0x0130/4:
240 case 0x0134/4:
241 case 0x0138/4:
242 case 0x013c/4:
243 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Entry %d = %08x & %08x\n", machine().describe_context(), offset - 0x100/4, m_ftlb_regs.entry[offset - 0x100/4],
244 mem_mask);
245 return m_ftlb_regs.entry[offset - 0x100/4];
246 case 0x0300/4:
247 LOGMASKED(LOG_FTLB, "%s: Unknown (F_SN) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.serial, mem_mask);
248 return m_ftlb_regs.serial;
249 default:
250 LOGMASKED(LOG_FTLB | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x06000000 + (offset << 2), mem_mask);
251 break;
252 }
253 return 0;
254 }
255
ftlb_w(offs_t offset,uint32_t data,uint32_t mem_mask)256 void pockstat_state::ftlb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
257 {
258 switch(offset)
259 {
260 case 0x0000/4:
261 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
262 COMBINE_DATA(&m_ftlb_regs.control);
263 break;
264 case 0x0004/4:
265 LOGMASKED(LOG_FTLB, "%s: Unknown (F_STAT) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
266 COMBINE_DATA(&m_ftlb_regs.stat);
267 break;
268 case 0x0008/4:
269 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Valid Tag = %08x & %08x\n", machine().describe_context(), data, mem_mask);
270 COMBINE_DATA(&m_ftlb_regs.valid);
271 break;
272 case 0x000c/4:
273 LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT1) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
274 COMBINE_DATA(&m_ftlb_regs.wait1);
275 break;
276 case 0x0010/4:
277 LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT2) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
278 COMBINE_DATA(&m_ftlb_regs.wait2);
279 break;
280 case 0x0100/4:
281 case 0x0104/4:
282 case 0x0108/4:
283 case 0x010c/4:
284 case 0x0110/4:
285 case 0x0114/4:
286 case 0x0118/4:
287 case 0x011c/4:
288 case 0x0120/4:
289 case 0x0124/4:
290 case 0x0128/4:
291 case 0x012c/4:
292 case 0x0130/4:
293 case 0x0134/4:
294 case 0x0138/4:
295 case 0x013c/4:
296 LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Entry %d = %08x & %08x\n", machine().describe_context(), offset - 0x100/4, data, mem_mask);
297 COMBINE_DATA(&m_ftlb_regs.entry[offset - 0x100/4]);
298 break;
299 case 0x0300/4:
300 LOGMASKED(LOG_FTLB, "%s: Unknown (F_SN) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
301 COMBINE_DATA(&m_ftlb_regs.serial);
302 break;
303 default:
304 LOGMASKED(LOG_FTLB | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x06000000 + (offset << 2), data, mem_mask);
305 break;
306 }
307 }
308
get_interrupt_line(uint32_t line)309 uint32_t pockstat_state::get_interrupt_line(uint32_t line)
310 {
311 return m_intc_regs.status & line;
312 }
313
set_interrupt_line(uint32_t line,int state)314 void pockstat_state::set_interrupt_line(uint32_t line, int state)
315 {
316 if (line)
317 {
318 if (state)
319 {
320 m_intc_regs.status |= line & INT_STATUS_MASK;
321 m_intc_regs.hold |= line &~ INT_STATUS_MASK;
322 LOGMASKED(LOG_IRQS, "Setting IRQ line %08x, status = %08x, hold = %08x\n", line, m_intc_regs.status, m_intc_regs.hold);
323 }
324 else
325 {
326 m_intc_regs.status &= ~line;
327 m_intc_regs.hold &= ~line;
328 LOGMASKED(LOG_IRQS, "Clearing IRQ line %08x, status = %08x, hold = %08x\n", line, m_intc_regs.status, m_intc_regs.hold);
329 }
330 }
331
332 const uint32_t new_irq = m_intc_regs.hold & m_intc_regs.enable & INT_IRQ_MASK;
333 if (new_irq)
334 {
335 m_maincpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE);
336 }
337 else
338 {
339 m_maincpu->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE);
340 }
341
342 const uint32_t new_fiq = m_intc_regs.hold & m_intc_regs.enable & INT_FIQ_MASK;
343 if (new_fiq)
344 {
345 m_maincpu->set_input_line(ARM7_FIRQ_LINE, ASSERT_LINE);
346 }
347 else
348 {
349 m_maincpu->set_input_line(ARM7_FIRQ_LINE, CLEAR_LINE);
350 }
351 }
352
intc_r(offs_t offset,uint32_t mem_mask)353 uint32_t pockstat_state::intc_r(offs_t offset, uint32_t mem_mask)
354 {
355 switch(offset)
356 {
357 case 0x0000/4:
358 LOGMASKED(LOG_INTC, "%s: Held Interrupt Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.hold, mem_mask);
359 return m_intc_regs.hold;
360 case 0x0004/4:
361 LOGMASKED(LOG_INTC, "%s: Interrupt Status Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.status, mem_mask);
362 return m_intc_regs.status;
363 case 0x0008/4:
364 LOGMASKED(LOG_INTC, "%s: Interrupt Enable Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.enable, mem_mask);
365 return m_intc_regs.enable;
366 case 0x000c/4:
367 LOGMASKED(LOG_INTC, "%s: Interrupt Mask Read (Invalid): %08x & %08x\n", machine().describe_context(), 0, mem_mask);
368 return 0;
369 case 0x0010/4:
370 LOGMASKED(LOG_INTC, "%s: Interrupt Acknowledge Read (Invalid): %08x & %08x\n", machine().describe_context(), 0, mem_mask);
371 return 0;
372 default:
373 LOGMASKED(LOG_INTC | LOG_UNKNOWN, "%s: Unknown Register Read: %08x & %08x\n", machine().describe_context(), 0x0a000000 + (offset << 2), mem_mask);
374 break;
375 }
376 return 0;
377 }
378
intc_w(offs_t offset,uint32_t data,uint32_t mem_mask)379 void pockstat_state::intc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
380 {
381 switch(offset)
382 {
383 case 0x0000/4:
384 LOGMASKED(LOG_INTC, "%s: Held Interrupt (Invalid Write) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
385 break;
386 case 0x0004/4:
387 LOGMASKED(LOG_INTC, "%s: Interrupt Status (Invalid Write) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
388 break;
389 case 0x0008/4:
390 LOGMASKED(LOG_INTC, "%s: Interrupt Enable = %08x & %08x\n", machine().describe_context(), data, mem_mask);
391 m_intc_regs.enable |= data;
392 //COMBINE_DATA(&m_intc_regs.enable);
393 //m_intc_regs.status &= m_intc_regs.enable;
394 //m_intc_regs.hold &= m_intc_regs.enable;
395 set_interrupt_line(0, 0);
396 break;
397 case 0x000c/4:
398 LOGMASKED(LOG_INTC, "%s: Interrupt Mask = %08x & %08x\n", machine().describe_context(), data, mem_mask);
399 m_intc_regs.enable &= ~data;
400 COMBINE_DATA(&m_intc_regs.mask);
401 //m_intc_regs.status &= m_intc_regs.enable;
402 //m_intc_regs.hold &= m_intc_regs.enable;
403 set_interrupt_line(0, 0);
404 break;
405 case 0x0010/4:
406 LOGMASKED(LOG_INTC, "%s: Interrupt Acknowledge = %08x & %08x\n", machine().describe_context(), data, mem_mask);
407 m_intc_regs.hold &= ~data;
408 m_intc_regs.status &= ~data;
409 set_interrupt_line(0, 0);
410 //COMBINE_DATA(&m_intc_regs.acknowledge);
411 break;
412 default:
413 LOGMASKED(LOG_INTC | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0a000000 + (offset << 2), data, mem_mask);
414 break;
415 }
416 }
417
TIMER_CALLBACK_MEMBER(pockstat_state::timer_tick)418 TIMER_CALLBACK_MEMBER(pockstat_state::timer_tick)
419 {
420 set_interrupt_line(param == 2 ? INT_TIMER2 : (param == 1 ? INT_TIMER1 : INT_TIMER0), 1);
421 m_timers[param].count = m_timers[param].period;
422 timer_start(param);
423 }
424
timer_start(int index)425 void pockstat_state::timer_start(int index)
426 {
427 int divisor = 1;
428 attotime period;
429 switch (m_timers[index].control & 3)
430 {
431 case 0:
432 case 3:
433 divisor = 1;
434 break;
435 case 1:
436 divisor = 16;
437 break;
438 case 2:
439 divisor = 256;
440 break;
441 }
442 period = attotime::from_hz(CPU_FREQ[m_clock_regs.mode & 0x0f] / 2) * divisor * m_timers[index].count;
443 m_timers[index].timer->adjust(period, index);
444 }
445
timer_r(offs_t offset,uint32_t mem_mask)446 uint32_t pockstat_state::timer_r(offs_t offset, uint32_t mem_mask)
447 {
448 switch (offset)
449 {
450 case 0x0000/4:
451 case 0x0010/4:
452 case 0x0020/4:
453 {
454 const uint32_t index = offset / (0x10/4);
455 LOGMASKED(LOG_TIMER, "%s: Timer %d Period Read: %08x & %08x\n", machine().describe_context(), index, m_timers[index].period, mem_mask);
456 return m_timers[index].period;
457 }
458 case 0x0004/4:
459 case 0x0014/4:
460 case 0x0024/4:
461 {
462 const uint32_t index = offset / (0x10/4);
463 LOGMASKED(LOG_TIMER, "%s: Timer %d Count Read: %08x & %08x\n", machine().describe_context(), index, m_timers[index].count, mem_mask);
464 if(m_timers[index].control & 4)
465 {
466 m_timers[index].count--;
467 if (m_timers[index].count > m_timers[index].period)
468 {
469 m_timers[index].count = m_timers[index].period;
470 }
471 return --m_timers[index].count;
472 }
473 return m_timers[index].count;
474 }
475 case 0x0008/4:
476 case 0x0018/4:
477 case 0x0028/4:
478 {
479 const uint32_t index = offset / (0x10/4);
480 LOGMASKED(LOG_TIMER, "%s: Timer %d Control = %08x & %08x\n", machine().describe_context(), index, m_timers[index].control, mem_mask);
481 return m_timers[index].control;
482 }
483 default:
484 LOGMASKED(LOG_TIMER | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0a800000 + (offset << 2), mem_mask);
485 break;
486 }
487 return 0;
488 }
489
timer_w(offs_t offset,uint32_t data,uint32_t mem_mask)490 void pockstat_state::timer_w(offs_t offset, uint32_t data, uint32_t mem_mask)
491 {
492 switch (offset)
493 {
494 case 0x0000/4:
495 case 0x0010/4:
496 case 0x0020/4:
497 {
498 const uint32_t index = offset / (0x10/4);
499 LOGMASKED(LOG_TIMER, "%s: Timer %d Period = %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
500 COMBINE_DATA(&m_timers[index].period);
501 break;
502 }
503 case 0x0004/4:
504 case 0x0014/4:
505 case 0x0024/4:
506 {
507 const uint32_t index = offset / (0x10/4);
508 LOGMASKED(LOG_TIMER, "%s: Timer %d Count = %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
509 COMBINE_DATA(&m_timers[index].count);
510 break;
511 }
512 case 0x0008/4:
513 case 0x0018/4:
514 case 0x0028/4:
515 {
516 const uint32_t index = offset / (0x10/4);
517 LOGMASKED(LOG_TIMER, "%s: Timer %d Control = %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
518 COMBINE_DATA(&m_timers[index].control);
519 if(m_timers[index].control & 4)
520 {
521 timer_start(index);
522 }
523 else
524 {
525 m_timers[index].timer->adjust(attotime::never, index);
526 }
527 break;
528 }
529 default:
530 LOGMASKED(LOG_TIMER | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0a800000 + (offset << 2), data, mem_mask);
531 break;
532 }
533 }
534
clock_r(offs_t offset,uint32_t mem_mask)535 uint32_t pockstat_state::clock_r(offs_t offset, uint32_t mem_mask)
536 {
537 switch(offset)
538 {
539 case 0x0000/4:
540 LOGMASKED(LOG_CLOCK, "%s: Clock Mode Read: %08x & %08x\n", machine().describe_context(), m_clock_regs.mode | 0x10, mem_mask);
541 return m_clock_regs.mode | CLOCK_STEADY;
542 case 0x0004/4:
543 LOGMASKED(LOG_CLOCK, "%s: Clock Control Read: %08x & %08x\n", machine().describe_context(), m_clock_regs.control, mem_mask);
544 return m_clock_regs.control;
545 default:
546 LOGMASKED(LOG_CLOCK | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0b000000 + (offset << 2), mem_mask);
547 break;
548 }
549 return 0;
550 }
551
clock_w(offs_t offset,uint32_t data,uint32_t mem_mask)552 void pockstat_state::clock_w(offs_t offset, uint32_t data, uint32_t mem_mask)
553 {
554 switch(offset)
555 {
556 case 0x0000/4:
557 LOGMASKED(LOG_CLOCK, "%s: Clock Mode = %08x & %08x\n", machine().describe_context(), data, mem_mask);
558 COMBINE_DATA(&m_clock_regs.mode);
559 m_maincpu->set_unscaled_clock(CPU_FREQ[m_clock_regs.mode & 0x0f]);
560 break;
561 case 0x0004/4:
562 LOGMASKED(LOG_CLOCK, "%s: Clock Control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
563 COMBINE_DATA(&m_clock_regs.control);
564 break;
565 default:
566 LOGMASKED(LOG_CLOCK | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0b000000 + (offset << 2), data, mem_mask);
567 break;
568 }
569 }
570
TIMER_CALLBACK_MEMBER(pockstat_state::rtc_tick)571 TIMER_CALLBACK_MEMBER(pockstat_state::rtc_tick)
572 {
573 set_interrupt_line(INT_RTC, get_interrupt_line(INT_RTC) ? 0 : 1);
574 if (!(m_rtc_regs.mode & 1))
575 {
576 m_rtc_regs.time++;
577 if ((m_rtc_regs.time & 0x0000000f) == 0x0000000a)
578 {
579 m_rtc_regs.time &= 0xfffffff0;
580 m_rtc_regs.time += 0x00000010;
581 if ((m_rtc_regs.time & 0x000000ff) == 0x00000060)
582 {
583 m_rtc_regs.time &= 0xffffff00;
584 m_rtc_regs.time += 0x00000100;
585 if ((m_rtc_regs.time & 0x00000f00) == 0x00000a00)
586 {
587 m_rtc_regs.time &= 0xfffff0ff;
588 m_rtc_regs.time += 0x00001000;
589 if ((m_rtc_regs.time & 0x0000ff00) == 0x00006000)
590 {
591 m_rtc_regs.time &= 0xffff00ff;
592 m_rtc_regs.time += 0x00010000;
593 if ((m_rtc_regs.time & 0x00ff0000) == 0x00240000)
594 {
595 m_rtc_regs.time &= 0xff00ffff;
596 m_rtc_regs.time += 0x01000000;
597 if ((m_rtc_regs.time & 0x0f000000) == 0x08000000)
598 {
599 m_rtc_regs.time &= 0xf0ffffff;
600 m_rtc_regs.time |= 0x01000000;
601 }
602 }
603 else if ((m_rtc_regs.time & 0x000f0000) == 0x000a0000)
604 {
605 m_rtc_regs.time &= 0xfff0ffff;
606 m_rtc_regs.time += 0x00100000;
607 }
608 }
609 }
610 }
611 }
612 }
613 m_rtc_regs.timer->adjust(attotime::from_hz(1));
614 }
615
rtc_r(offs_t offset,uint32_t mem_mask)616 uint32_t pockstat_state::rtc_r(offs_t offset, uint32_t mem_mask)
617 {
618 switch(offset)
619 {
620 case 0x0000/4:
621 LOGMASKED(LOG_RTC, "%s: RTC Mode Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.mode, mem_mask);
622 return m_rtc_regs.mode;
623 case 0x0004/4:
624 LOGMASKED(LOG_RTC, "%s: RTC Control Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.control, mem_mask);
625 return m_rtc_regs.control;
626 case 0x0008/4:
627 LOGMASKED(LOG_RTC, "%s: RTC Time Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.time, mem_mask);
628 return m_rtc_regs.time;
629 case 0x000c/4:
630 LOGMASKED(LOG_RTC, "%s: RTC Date Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.date, mem_mask);
631 return m_rtc_regs.date;
632 default:
633 LOGMASKED(LOG_RTC | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0b800000 + (offset << 2), mem_mask);
634 break;
635 }
636 return 0;
637 }
638
rtc_w(offs_t offset,uint32_t data,uint32_t mem_mask)639 void pockstat_state::rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
640 {
641 switch (offset)
642 {
643 case 0x0000/4:
644 LOGMASKED(LOG_RTC, "%s: RTC Mode = %08x & %08x\n", machine().describe_context(), data, mem_mask);
645 COMBINE_DATA(&m_rtc_regs.mode);
646 break;
647 case 0x0004/4:
648 LOGMASKED(LOG_RTC, "%s: RTC Control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
649 if (m_rtc_regs.control == 1 && data == 1)
650 {
651 switch (m_rtc_regs.mode >> 1)
652 {
653 case 0: // Seconds
654 m_rtc_regs.time += 0x00000001;
655 if ((m_rtc_regs.time & 0x0000000f) == 0x0000000a)
656 {
657 m_rtc_regs.time &= 0xfffffff0;
658 m_rtc_regs.time += 0x00000010;
659 if ((m_rtc_regs.time & 0x000000ff) == 0x00000060)
660 {
661 m_rtc_regs.time &= 0xffffff00;
662 }
663 }
664 break;
665 case 1: // Minutes
666 m_rtc_regs.time += 0x00000100;
667 if ((m_rtc_regs.time & 0x00000f00) == 0x00000a00)
668 {
669 m_rtc_regs.time &= 0xfffff0ff;
670 m_rtc_regs.time += 0x00001000;
671 if ((m_rtc_regs.time & 0x0000ff00) == 0x00006000)
672 {
673 m_rtc_regs.time &= 0xffff00ff;
674 }
675 }
676 break;
677 case 2: // Hours
678 m_rtc_regs.time += 0x00010000;
679 if ((m_rtc_regs.time & 0x00ff0000) == 0x00240000)
680 {
681 m_rtc_regs.time &= 0xff00ffff;
682 }
683 else if ((m_rtc_regs.time & 0x000f0000) == 0x000a0000)
684 {
685 m_rtc_regs.time &= 0xfff0ffff;
686 m_rtc_regs.time += 0x00100000;
687 }
688 break;
689 case 3: // Day of the week
690 m_rtc_regs.time += 0x01000000;
691 if ((m_rtc_regs.time & 0x0f000000) == 0x08000000)
692 {
693 m_rtc_regs.time &= 0xf0ffffff;
694 m_rtc_regs.time |= 0x01000000;
695 }
696 break;
697 case 4: // Day
698 m_rtc_regs.date += 0x00000001;
699 if ((m_rtc_regs.date & 0x000000ff) == 0x00000032)
700 {
701 m_rtc_regs.date &= 0xffffff00;
702 }
703 else if ((m_rtc_regs.date & 0x0000000f) == 0x0000000a)
704 {
705 m_rtc_regs.date &= 0xfffffff0;
706 m_rtc_regs.date += 0x00000010;
707 }
708 break;
709 case 5: // Month
710 m_rtc_regs.date += 0x00000100;
711 if ((m_rtc_regs.date & 0x0000ff00) == 0x00001300)
712 {
713 m_rtc_regs.date &= 0xffffff00;
714 m_rtc_regs.date |= 0x00000001;
715 }
716 else if ((m_rtc_regs.date & 0x00000f00) == 0x00000a00)
717 {
718 m_rtc_regs.date &= 0xfffff0ff;
719 m_rtc_regs.date += 0x00001000;
720 }
721 break;
722 case 6: // Year (LSB)
723 m_rtc_regs.date += 0x00010000;
724 if ((m_rtc_regs.date & 0x000f0000) == 0x000a0000)
725 {
726 m_rtc_regs.date &= 0xfff0ffff;
727 m_rtc_regs.date += 0x00100000;
728 if ((m_rtc_regs.date & 0x00f00000) == 0x00a00000)
729 {
730 m_rtc_regs.date &= 0xff00ffff;
731 }
732 }
733 break;
734 case 7: // Year (MSB)
735 break;
736 }
737 m_rtc_regs.control = 0;
738 }
739 else if(m_rtc_regs.control == 0)
740 {
741 COMBINE_DATA(&m_rtc_regs.control);
742 }
743 break;
744 default:
745 LOGMASKED(LOG_RTC | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0b800000 + (offset << 2), data, mem_mask);
746 break;
747 }
748 }
749
750
lcd_r(offs_t offset,uint32_t mem_mask)751 uint32_t pockstat_state::lcd_r(offs_t offset, uint32_t mem_mask)
752 {
753 switch (offset)
754 {
755 case 0x0000/4:
756 LOGMASKED(LOG_LCD, "%s: LCD Control Read: %08x & %08x\n", machine().describe_context(), m_lcd_control | 0x100, mem_mask);
757 return m_lcd_control;
758 default:
759 LOGMASKED(LOG_LCD | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0d000000 + (offset << 2), mem_mask);
760 break;
761 }
762 return 0;
763 }
764
lcd_w(offs_t offset,uint32_t data,uint32_t mem_mask)765 void pockstat_state::lcd_w(offs_t offset, uint32_t data, uint32_t mem_mask)
766 {
767 switch (offset)
768 {
769 case 0x0000/4:
770 LOGMASKED(LOG_LCD, "%s: LCD Control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
771 COMBINE_DATA(&m_lcd_control);
772 break;
773 default:
774 LOGMASKED(LOG_LCD | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0d000000 + (offset << 2), data, mem_mask);
775 break;
776 }
777 }
778
INPUT_CHANGED_MEMBER(pockstat_state::input_update)779 INPUT_CHANGED_MEMBER(pockstat_state::input_update)
780 {
781 uint32_t buttons = ioport("BUTTONS")->read();
782
783 set_interrupt_line(INT_BTN_ACTION, (buttons & 1) ? 1 : 0);
784 set_interrupt_line(INT_BTN_RIGHT, (buttons & 2) ? 1 : 0);
785 set_interrupt_line(INT_BTN_LEFT, (buttons & 4) ? 1 : 0);
786 set_interrupt_line(INT_BTN_DOWN, (buttons & 8) ? 1 : 0);
787 set_interrupt_line(INT_BTN_UP, (buttons & 16) ? 1 : 0);
788 }
789
rombank_r(offs_t offset,uint32_t mem_mask)790 uint32_t pockstat_state::rombank_r(offs_t offset, uint32_t mem_mask)
791 {
792 int32_t bank = (offset >> 11) & 0x0f;
793 for (int index = 0; index < 32; index++)
794 {
795 if (m_ftlb_regs.valid & (1 << index))
796 {
797 if (m_ftlb_regs.entry[index] == bank)
798 {
799 return m_cart->read32_rom(index * (0x2000/4) + (offset & (0x1fff/4)), mem_mask);
800 }
801 }
802 }
803 return m_cart->read32_rom(offset & 0x7fff, mem_mask);
804 }
805
806
807 // Horrible hack, probably wrong
flash_w(offs_t offset,uint32_t data,uint32_t mem_mask)808 void pockstat_state::flash_w(offs_t offset, uint32_t data, uint32_t mem_mask)
809 {
810 if (offset == (0x55a8/4))
811 {
812 m_flash_write_enable_count++;
813 return;
814 }
815 if (offset == (0x2a54/4))
816 {
817 m_flash_write_enable_count++;
818 return;
819 }
820 if (m_flash_write_enable_count == 3)
821 {
822 m_flash_write_enable_count = 0;
823 m_flash_write_count = 0x40;
824 return;
825 }
826 if (m_flash_write_count)
827 {
828 m_flash_write_count--;
829 COMBINE_DATA(&((uint32_t*)(m_cart_rom->base()))[offset]);
830 }
831 }
832
flash_r(offs_t offset,uint32_t mem_mask)833 uint32_t pockstat_state::flash_r(offs_t offset, uint32_t mem_mask)
834 {
835 return m_cart->read32_rom(offset, mem_mask);
836 }
837
audio_r(offs_t offset,uint32_t mem_mask)838 uint32_t pockstat_state::audio_r(offs_t offset, uint32_t mem_mask)
839 {
840 LOGMASKED(LOG_AUDIO | LOG_UNKNOWN, "%s: Unknown Audio Read: %08x = %08x & %08x\n", machine().describe_context(), 0xd800000 + (offset << 2), 0x10, mem_mask);
841 return 0;
842 }
843
audio_w(offs_t offset,uint32_t data,uint32_t mem_mask)844 void pockstat_state::audio_w(offs_t offset, uint32_t data, uint32_t mem_mask)
845 {
846 LOGMASKED(LOG_AUDIO | LOG_UNKNOWN, "%s: Unknown Audio Write: %08x = %08x & %08x\n", machine().describe_context(), 0xd800000 + (offset << 2), data, mem_mask);
847 }
848
mem_map(address_map & map)849 void pockstat_state::mem_map(address_map &map)
850 {
851 map(0x00000000, 0x000007ff).ram();
852 map(0x02000000, 0x02ffffff).r(FUNC(pockstat_state::rombank_r));
853 map(0x04000000, 0x04003fff).rom().region("maincpu", 0);
854 map(0x06000000, 0x06000307).rw(FUNC(pockstat_state::ftlb_r), FUNC(pockstat_state::ftlb_w));
855 map(0x08000000, 0x0801ffff).rw(FUNC(pockstat_state::flash_r), FUNC(pockstat_state::flash_w));
856 map(0x0a000000, 0x0a000013).rw(FUNC(pockstat_state::intc_r), FUNC(pockstat_state::intc_w));
857 map(0x0a800000, 0x0a80002b).rw(FUNC(pockstat_state::timer_r), FUNC(pockstat_state::timer_w));
858 map(0x0b000000, 0x0b000007).rw(FUNC(pockstat_state::clock_r), FUNC(pockstat_state::clock_w));
859 map(0x0b800000, 0x0b80000f).rw(FUNC(pockstat_state::rtc_r), FUNC(pockstat_state::rtc_w));
860 map(0x0d000000, 0x0d000003).rw(FUNC(pockstat_state::lcd_r), FUNC(pockstat_state::lcd_w));
861 map(0x0d000100, 0x0d00017f).ram().share("lcd_buffer");
862 map(0x0d80000c, 0x0d80000f).rw(FUNC(pockstat_state::audio_r), FUNC(pockstat_state::audio_w));
863 map(0x0d800014, 0x0d800015).w("dac", FUNC(dac_word_interface::data_w));
864 }
865
866 /* Input ports */
867 static INPUT_PORTS_START( pockstat )
868 PORT_START("BUTTONS")
869 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Action Button") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0)
870 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_NAME("Right") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0)
871 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_NAME("Left") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0)
872 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_NAME("Down") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0)
873 PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_NAME("Up") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0)
874 PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED)
875 INPUT_PORTS_END
876
machine_start()877 void pockstat_state::machine_start()
878 {
879 for (uint32_t index = 0; index < TIMER_COUNT; index++)
880 {
881 m_timers[index].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pockstat_state::timer_tick), this));
882 m_timers[index].timer->adjust(attotime::never, index);
883 }
884
885 m_rtc_regs.time = 0x01000000;
886 m_rtc_regs.date = 0x19990101;
887
888 m_rtc_regs.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pockstat_state::rtc_tick),this));
889 m_rtc_regs.timer->adjust(attotime::from_hz(1), TIMER_COUNT);
890
891 std::string region_tag;
892 m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
893
894 save_item(NAME(m_ftlb_regs.control));
895 save_item(NAME(m_ftlb_regs.stat));
896 save_item(NAME(m_ftlb_regs.valid));
897 save_item(NAME(m_ftlb_regs.wait1));
898 save_item(NAME(m_ftlb_regs.wait2));
899 save_item(NAME(m_ftlb_regs.entry));
900
901 save_item(NAME(m_intc_regs.hold));
902 save_item(NAME(m_intc_regs.status));
903 save_item(NAME(m_intc_regs.enable));
904 save_item(NAME(m_intc_regs.mask));
905
906 save_item(NAME(m_timers[0].period));
907 save_item(NAME(m_timers[0].count));
908 save_item(NAME(m_timers[0].control));
909 save_item(NAME(m_timers[1].period));
910 save_item(NAME(m_timers[1].count));
911 save_item(NAME(m_timers[1].control));
912 save_item(NAME(m_timers[2].period));
913 save_item(NAME(m_timers[2].count));
914 save_item(NAME(m_timers[2].control));
915
916 save_item(NAME(m_clock_regs.mode));
917 save_item(NAME(m_clock_regs.control));
918
919 save_item(NAME(m_rtc_regs.mode));
920 save_item(NAME(m_rtc_regs.control));
921 save_item(NAME(m_rtc_regs.time));
922 save_item(NAME(m_rtc_regs.date));
923
924 save_item(NAME(m_flash_write_enable_count));
925 save_item(NAME(m_flash_write_count));
926
927 save_item(NAME(m_lcd_control));
928 }
929
machine_reset()930 void pockstat_state::machine_reset()
931 {
932 m_maincpu->set_state_int(ARM7_R15, 0x4000000);
933
934 m_flash_write_enable_count = 0;
935 m_flash_write_count = 0;
936 }
937
screen_update_pockstat(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)938 uint32_t pockstat_state::screen_update_pockstat(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
939 {
940 for (int y = 0; y < 32; y++)
941 {
942 uint32_t *const scanline = &bitmap.pix(y);
943 for (int x = 0; x < 32; x++)
944 {
945 if (m_lcd_control != 0) // Hack
946 {
947 if (BIT(m_lcd_buffer[y], x))
948 scanline[x] = 0x00000000;
949 else
950 scanline[x] = 0x00ffffff;
951 }
952 else
953 scanline[x] = 0x00ffffff;
954 }
955 }
956 return 0;
957 }
958
DEVICE_IMAGE_LOAD_MEMBER(pockstat_state::flash_load)959 DEVICE_IMAGE_LOAD_MEMBER(pockstat_state::flash_load)
960 {
961 static const char *gme_id = "123-456-STD";
962 char cart_id[0xf40];
963 uint32_t size = image.length();
964
965 if (size != 0x20f40)
966 return image_init_result::FAIL;
967
968 image.fread(cart_id, 0xf40);
969
970 for (int i = 0; i < strlen(gme_id); i++)
971 {
972 if (cart_id[i] != gme_id[i])
973 return image_init_result::FAIL;
974 }
975
976 m_cart->rom_alloc(0x20000, GENERIC_ROM32_WIDTH, ENDIANNESS_LITTLE);
977 image.fread(m_cart->get_rom_base(), 0x20000);
978
979 return image_init_result::PASS;
980 }
981
pockstat(machine_config & config)982 void pockstat_state::pockstat(machine_config &config)
983 {
984 static constexpr uint32_t DEFAULT_CLOCK = 2000000;
985
986 /* basic machine hardware */
987 ARM7(config, m_maincpu, DEFAULT_CLOCK);
988 m_maincpu->set_addrmap(AS_PROGRAM, &pockstat_state::mem_map);
989
990 /* video hardware */
991 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
992 screen.set_refresh_hz(50);
993 screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
994 screen.set_size(32, 32);
995 screen.set_visarea(0, 32-1, 0, 32-1);
996 screen.set_screen_update(FUNC(pockstat_state::screen_update_pockstat));
997
998 PALETTE(config, "palette", palette_device::MONOCHROME);
999
1000 SPEAKER(config, "speaker").front_center();
1001 DAC_16BIT_R2R_TWOS_COMPLEMENT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
1002
1003 /* cartridge */
1004 GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "pockstat_cart", "gme");
1005 m_cart->set_width(GENERIC_ROM32_WIDTH);
1006 m_cart->set_endian(ENDIANNESS_LITTLE);
1007 m_cart->set_device_load(FUNC(pockstat_state::flash_load));
1008 }
1009
1010 /* ROM definition */
1011 ROM_START( pockstat )
1012 ROM_REGION( 0x4000, "maincpu", 0 )
1013 ROM_LOAD( "kernel.bin", 0x0000, 0x4000, CRC(5fb47dd8) SHA1(6ae880493ddde880827d1e9f08e9cb2c38f9f2ec) )
1014 ROM_END
1015
1016 /* Driver */
1017
1018 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
1019 CONS( 1999, pockstat, 0, 0, pockstat, pockstat, pockstat_state, empty_init, "Sony Computer Entertainment Inc", "Sony PocketStation", MACHINE_SUPPORTS_SAVE )
1020