Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
6.8KB

  1. ( ----- 600 )
  2. Sega Master System Recipe
  3. 602 VDP 610 PAD
  4. 620 KBD 625 Ports
  5. ( ----- 602 )
  6. ( VDP Driver. requires TMS9918 driver. Load range B602-B604. )
  7. CREATE _idat
  8. 0b00000100 C, 0x80 C, ( Bit 2: Select mode 4 )
  9. 0b00000000 C, 0x81 C,
  10. 0b00001111 C, 0x82 C, ( Name table: 0x3800, *B0 must be 1* )
  11. 0b11111111 C, 0x85 C, ( Sprite table: 0x3f00 )
  12. 0b11111111 C, 0x86 C, ( sprite use tiles from 0x2000 )
  13. 0b11111111 C, 0x87 C, ( Border uses palette 0xf )
  14. 0b00000000 C, 0x88 C, ( BG X scroll )
  15. 0b00000000 C, 0x89 C, ( BG Y scroll )
  16. 0b11111111 C, 0x8a C, ( Line counter (why have this?) )
  17. ( ----- 603 )
  18. : _zero ( x -- send 0 _data x times )
  19. ( x ) 0 DO 0 _data LOOP ;
  20. ( Each row in ~FNT is a row of the glyph and there is 7 of
  21. them. We insert a blank one at the end of those 7. For each
  22. row we set, we need to send 3 zero-bytes because each pixel in
  23. the tile is actually 4 bits because it can select among 16
  24. palettes. We use only 2 of them, which is why those bytes
  25. always stay zero. )
  26. : _sfont ( a -- Send font to VDP )
  27. 7 0 DO C@+ _data 3 _zero LOOP DROP
  28. ( blank row ) 4 _zero ;
  29. : CELL! ( tilenum pos )
  30. 2 * 0x7800 OR _ctl ( tilenum )
  31. 0x5e MOD _data 1 _zero ;
  32. ( ----- 604 )
  33. : VDP$
  34. 9 0 DO _idat I 2 * + @ _ctl LOOP _blank
  35. ( palettes )
  36. 0xc000 _ctl
  37. ( BG ) 1 _zero 0x3f _data 14 _zero
  38. ( sprite, inverted colors ) 0x3f _data 15 _zero
  39. 0x4000 _ctl 0x5e 0 DO ~FNT I 7 * + _sfont LOOP
  40. ( bit 6, enable display, bit 7, ?? ) 0x81c0 _ctl ;
  41. : COLS 32 ;
  42. : LINES 24 ;
  43. ( ----- 610 )
  44. Pad driver - read input from MD controller
  45. Conveniently expose an API to read the status of a MD pad A.
  46. Moreover, implement a mechanism to input arbitrary characters
  47. from it. It goes as follow:
  48. * Direction pad select characters. Up/Down move by one,
  49. Left/Right move by 5
  50. * Start acts like Return
  51. * A acts like Backspace
  52. * B changes "character class": lowercase, uppercase, numbers,
  53. special chars. The space character is the first among special
  54. chars.
  55. * C confirms letter selection
  56. (cont.)
  57. ( ----- 611 )
  58. This module is currently hard-wired to VDP driver, that is, it
  59. calls vdp's routines during (key) to update character
  60. selection.
  61. Load range: 632-637
  62. ( ----- 612 )
  63. : _prevstat [ PAD_MEM LITN ] ;
  64. : _sel [ PAD_MEM 1+ LITN ] ;
  65. : _next [ PAD_MEM 2+ LITN ] ;
  66. ( Put status for port A in register A. Bits, from MSB to LSB:
  67. Start - A - C - B - Right - Left - Down - Up
  68. Each bit is high when button is unpressed and low if button is
  69. pressed. When no button is pressed, 0xff is returned.
  70. This logic below is for the Genesis controller, which is modal.
  71. TH is an output pin that switches the meaning of TL and TR. When
  72. TH is high (unselected), TL = Button B and TR = Button C. When
  73. TH is low (selected), TL = Button A and TR = Start. )
  74. ( ----- 613 )
  75. : _status
  76. 1 _THA! ( output, high/unselected )
  77. _D1@ 0x3f AND ( low 6 bits are good )
  78. ( Start and A are returned when TH is selected, in bits 5 and
  79. 4. Well get them, left-shift them and integrate them to B. )
  80. 0 _THA! ( output, low/selected )
  81. _D1@ 0x30 AND 2 LSHIFT OR ;
  82. ( ----- 614 )
  83. : _chk ( c --, check _sel range )
  84. _sel C@ DUP 0x7f > IF 0x20 _sel C! THEN
  85. 0x20 < IF 0x7f _sel C! THEN ;
  86. CREATE _ '0' C, ':' C, 'A' C, '[' C, 'a' C, 0xff C,
  87. : _nxtcls
  88. _sel @ _ BEGIN ( c a ) C@+ 2 PICK > UNTIL ( c a )
  89. 1- C@ NIP _sel !
  90. ;
  91. ( ----- 615 )
  92. : _updsel ( -- f, has an action button been pressed? )
  93. _status _prevstat C@ OVER = IF DROP 0 EXIT THEN
  94. DUP _prevstat C! ( changed, update ) ( s )
  95. 0x01 ( UP ) OVER AND NOT IF 1 _sel +! THEN
  96. 0x02 ( DOWN ) OVER AND NOT IF -1 _sel +! THEN
  97. 0x04 ( LEFT ) OVER AND NOT IF -5 _sel +! THEN
  98. 0x08 ( RIGHT ) OVER AND NOT IF 5 _sel +! THEN
  99. 0x10 ( BUTB ) OVER AND NOT IF _nxtcls THEN
  100. ( update sel in VDP )
  101. _chk _sel C@ (emit) -1 XYPOS +!
  102. ( return whether any of the high 3 bits is low )
  103. 0xe0 AND 0xe0 <
  104. ;
  105. ( ----- 616 )
  106. : (key)
  107. _next C@ IF _next C@ 0 _next C! EXIT THEN
  108. BEGIN _updsel UNTIL
  109. _prevstat C@
  110. 0x20 ( BUTC ) OVER AND NOT IF DROP _sel C@ EXIT THEN
  111. 0x40 ( BUTA ) AND NOT IF 0x8 ( BS ) EXIT THEN
  112. ( If not BUTC or BUTA, it has to be START )
  113. 0xd _next C! _sel C@
  114. ;
  115. ( ----- 617 )
  116. : PAD$
  117. 0xff _prevstat C! 'a' _sel C! 0 _next C! ;
  118. ( ----- 620 )
  119. ( kbd - implement (ps2kc) for SMS PS/2 adapter )
  120. : (ps2kcA) ( for port A )
  121. ( Before reading a character, we must first verify that there
  122. is something to read. When the adapter is finished filling its
  123. '164 up, it resets the latch, which output's is connected to
  124. TL. When the '164 is full, TL is low. Port A TL is bit 4 )
  125. _D1@ 0x10 AND IF 0 EXIT ( nothing ) THEN
  126. 0 _THA! ( Port A TH output, low )
  127. _D1@ ( bit 3:0 go in 3:0 ) 0x0f AND ( n )
  128. 1 _THA! ( Port A TH output, high )
  129. _D1@ ( bit 3:0 go in 7:4 ) 0x0f AND 4 LSHIFT OR ( n )
  130. 2 _THA! ( TH input ) ;
  131. ( ----- 621 )
  132. : (ps2kcB) ( for port B )
  133. ( Port B TL is bit 2 )
  134. _D2@ 0x04 AND IF 0 EXIT ( nothing ) THEN
  135. 0 _THB! ( Port B TH output, low )
  136. _D1@ ( bit 7:6 go in 1:0 ) 6 RSHIFT ( n )
  137. _D2@ ( bit 1:0 go in 3:2 ) 0x03 AND 2 LSHIFT OR ( n )
  138. 1 _THB! ( Port B TH output, high )
  139. _D1@ ( bit 7:6 go in 5:4 ) 0xc0 AND 2 RSHIFT OR ( n )
  140. _D2@ ( bit 1:0 go in 7:6 ) 0x03 AND 6 LSHIFT OR ( n )
  141. 2 _THB! ( TH input ) ;
  142. ( ----- 622 )
  143. : (spie) DROP ; ( always enabled )
  144. : (spix) ( x -- x, for port B )
  145. 0 SWAP ( rx tx ) 8 0 DO
  146. ( send current bit to TRB, TR's output bit )
  147. DUP 7 I - RSHIFT 1 AND _TRB!
  148. 1 _THB! ( CLK hi )
  149. ( read into rx ) SWAP 1 LSHIFT _D1@ ( tx rx<< x )
  150. 0 _THB! ( CLK lo )
  151. ( out bit is the 6th ) 6 RSHIFT 1 AND OR
  152. SWAP LOOP ( rx tx ) DROP ;
  153. ( ----- 625 )
  154. ( Routines for interacting with SMS controller ports.
  155. Requires CPORT_MEM, CPORT_CTL, CPORT_D1 and CPORT_D2 to be
  156. defined. CPORT_MEM is a 1 byte buffer for CPORT_CTL. The last
  157. 3 consts will usually be 0x3f, 0xdc, 0xdd. )
  158. ( mode -- set TR pin on mode a on:
  159. 0= output low 1=output high 2=input )
  160. CODE _TRA! HL POP, chkPS, ( B0 -> B4, B1 -> B0 )
  161. L RR, RLA, RLA, RLA, RLA, L RR, RLA,
  162. 0x11 ANDi, L A LDrr, CPORT_MEM LDA(i),
  163. 0xee ANDi, L ORr, CPORT_CTL OUTiA, CPORT_MEM LD(i)A,
  164. ;CODE
  165. CODE _THA! HL POP, chkPS, ( B0 -> B5, B1 -> B1 )
  166. L RR, RLA, RLA, RLA, RLA, L RR, RLA, RLA,
  167. 0x22 ANDi, L A LDrr, CPORT_MEM LDA(i),
  168. 0xdd ANDi, L ORr, CPORT_CTL OUTiA, CPORT_MEM LD(i)A,
  169. ;CODE
  170. ( ----- 626 )
  171. CODE _TRB! HL POP, chkPS, ( B0 -> B6, B1 -> B2 )
  172. L RR, RLA, RLA, RLA, RLA, L RR, RLA, RLA, RLA,
  173. 0x44 ANDi, L A LDrr, CPORT_MEM LDA(i),
  174. 0xbb ANDi, L ORr, CPORT_CTL OUTiA, CPORT_MEM LD(i)A,
  175. ;CODE
  176. CODE _THB! HL POP, chkPS, ( B0 -> B7, B1 -> B3 )
  177. L RR, RLA, RLA, RLA, RLA, L RR, RLA, RLA, RLA, RLA,
  178. 0x88 ANDi, L A LDrr, CPORT_MEM LDA(i),
  179. 0x77 ANDi, L ORr, CPORT_CTL OUTiA, CPORT_MEM LD(i)A,
  180. ;CODE
  181. CODE _D1@ CPORT_D1 INAi, PUSHA, ;CODE
  182. CODE _D2@ CPORT_D2 INAi, PUSHA, ;CODE