|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
SG-1000 port DE write/read at boot pattern
Posted: Sun Sep 15, 2019 9:00 am
|
I'm debugging my SG-1000 emulator and suspect that the PPI may be to blame. I keep seeing a pattern at boot time in game ROMs that I don't understand, and I'd like to be able to rule it out as a possible issue.
Lots of ROMs seem to write a known value to port DE (PPI port C write) then read it back (PPI port C read) and store state depending on whether the same value is returned. This state is then read in the per-frame input routine. What does this state mean? The only information I have been able to find is
From smspower>Development>Keyboard and smstech-20021112.txt For example: ; Space invaders 0548 ld hl, 0C004h 054B set 0, (hl) 054D xor a 054E out (0DEh), a 0550 in a, (0DEh) 0552 or a 0553 ret z 0554 res 0, (hl) 0556 ret ; Champion Golf 0B99 ld a, 0A2h 0B9B out (0DEh), a ; PPI I/O port C write. Select input row 2 0B9D in a, (0DEh) ; 8255 PPI I/O port C read 0B9F cp 0A2h ; read same value back? 0BA1 jr z, BA9 0BA3 xor a ; a <- 0 0BA4 ld (C247h), a 0BA7 jr BAE 0BA9 ld a, 1 0BAB ld (C247h), a 0BAE ret ; Q-bert checks twice 0017 ld a, 55h 0019 out (DEh), a 001B in a, (DEh) 001D cp 55h 001F jr nz, 2D 0021 cpl 0022 out (DEh), a 0024 in a, (DEh) 0026 cp 0AAh 0028 jr nz, 2D 002A ld (C079h), a |
|
|
Posted: Mon Sep 16, 2019 1:51 am |
This may be of use..
http://www.smspower.org/uploads/Development/sc3000h-20040729.txt In respect to..
|
|
|
Posted: Tue Sep 17, 2019 6:42 am |
Thanks. It seems strange that games configure PPI Port C as output, but then go on to test that it returns the last value written. There must be some situation in which it does not.
Perhaps this is testing for the presence of a keyboard, or testing if the game is running on a particular machine? |
|
|
Posted: Tue Sep 17, 2019 7:01 am |
Could be to check if its running on a sg-1000/mkIII with or without a keyboard..and or a sc-3000 i guess. | |
|
Posted: Tue Sep 17, 2019 7:18 am |
I thought the point was to have the game be controllable by the keyboard. | |
|
Posted: Wed Sep 18, 2019 3:32 pm |
I think it's a keyboard check. The SK-1100 keyboard you plug in adds the missing PPI: https://web.archive.org/web/20090213004805/http://www2.odn.ne.jp/~haf09260/Mark3... (Btw, what a shame Enri's page is down) When the keyboard is attached port C exists and can be read and written. When it is removed there is no port C so you read an open bus value, probably 00, FF, random, etc. Which may be why games check twice to be sure. I think they check port C this instead of testing the mode register at $DF because earlier NMOS PPIs had a mode register you couldn't read, and read-back functionality was only added later to the CMOS PPIs as I recall. This leaves port C as the only PPI register that can be read and written. |
|
|
Posted: Wed Sep 18, 2019 9:22 pm |
Thanks Charles. That makes a lot of sense. I wish I understood electronics, and Japanese. I've identified the input routines in Space Invaders, which I'm using to debug my emulator, so I hope to confirm this soon. I've almost figured it out.
; =============== S U B R O U T I N E ======================================= 0544 ; Standard PPI setup 0544 ; Set C004 bit high if SK-1100 keyboard connected 0544 InitInput: ; CODE XREF: 009E 0544 3E 92 LD A,92 ; PPI Control Register write 0546 D3 DF OUT ($DF),A ; Port A and B input, port C output 0548 21 04 C0 LD HL,C004 054B CB C6 SET 0,(HL) ; C004 bit 0 high means keyboard connected 054D AF XOR A ; A <- 0 054E D3 DE OUT ($DE),A ; write 0 to PPI port C 0550 DB DE IN A,($DE) ; Read port C back... 0552 B7 OR A ; read same value back? 0553 C8 RET Z ; yes = SK-1100 keyboard connected 0554 CB 86 RES 0,(HL) ; C004 bit 0 low means no keyboard connected 0556 C9 RET ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= 05A3 UpdateInput: ; CODE XREF: 0232 05A3 ; CODE XREF: 057B 05A3 3A 04 C0 LD A,(byte_C004) 05A6 0F RRCA ; Carry flag = Accumulator bit 0 = keyboard connected 05A7 38 1D JR C,Player1Input ; jump if keyboard connected 05A9 0F RRCA ; Rotate Accumulator Right 05AA 38 08 JR C,ReadPad2 ; read pad 2 if C004 bit 1 set 05AC DB DC IN A,($DC) ; PPI port A read 05AE F6 C0 OR C0 ; discard pad 2 bits (active low) 05B0 32 0F C0 LD (byte_C00F),A ; store joypad 1 bits in C00F 05B3 C9 RET ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= 05B4 ; Pad 2 bits are split across PPI port A and port B values so need logic to combine 05B4 ReadPad2: ; CODE XREF: 05AA 05B4 ; CODE XREF: 0620 05B4 DB DC IN A,($DC) ; PPI port A read 05B6 E6 C0 AND C0 ; discard pad 1 bits - keep only pad 2 bits 05B8 47 LD B,A 05B9 DB DD IN A,($DD) ; PPI port B read (joypad 2 bits) 05BB E6 3F AND 3F 05BD 80 ADD A,B ; combine: DUxxBARL 05BE 07 RLCA ; UxxBARLD 05BF 07 RLCA ; xxBARLDU 05C0 F6 C0 OR C0 ; 11BARLDU 05C2 32 0F C0 LD (byte_C00F),A 05C5 C9 RET ; --------------------------------------------------------------------------- 05C6 Player1Input: ; CODE XREF: 05A7 05C6 0F RRCA ; Rotate Accumulator Right 05C7 38 53 JR C,Player2Input ; test C004 bit 1 05C9 ; Combine joypad 1 and keyboard cursor input and store in C00F 05C9 ; Bits: xxBARLDU (active low) 05C9 3E 07 LD A,07 ; select PPI input row 7 (joypads) 05CB D3 DE OUT ($DE),A ; PPI Port C write 05CD DB DC IN A,($DC) ; PPI port A read 05CF F6 C0 OR C0 ; discard pad 2 bits (active low) 05D1 32 0F C0 LD (byte_C00F),A ; store pad 1 state in C00F 05D4 4F LD C,A 05D5 3E 04 LD A,04 ; select PPI input row 4 (keyboard) 05D7 D3 DE OUT ($DE),A 05D9 DB DC IN A,($DC) ; PPI port A read 05DB CB 6F BIT 5,A ; test keyboard down arrow 05DD 20 02 JR NZ,loc_05E1 ; skip next instruction if not pressed 05DF CB 89 RES 1,C ; bit 1 = down 05E1 loc_05E1: ; CODE XREF: 05DD 05E1 3E 05 LD A,05 ; select input row 5 (keyboard) 05E3 D3 DE OUT ($DE),A 05E5 DB DC IN A,($DC) 05E7 CB 6F BIT 5,A ; test keyboard left arrow 05E9 20 02 JR NZ,loc_05ED ; skip next instruction if not pressed 05EB CB 91 RES 2,C ; bit 2 = left 05ED loc_05ED: ; CODE XREF: 05E9 05ED 3E 06 LD A,06 ; test keyboard right arrow... 05EF D3 DE OUT ($DE),A 05F1 DB DC IN A,($DC) 05F3 CB 6F BIT 5,A 05F5 20 02 JR NZ,loc_05F9 05F7 CB 99 RES 3,C ; bit 3 = right 05F9 loc_05F9: ; CODE XREF: 05F5 05F9 CB 77 BIT 6,A ; test keyboard up arrow... 05FB 20 02 JR NZ,loc_05FF 05FD CB 81 RES 0,C 05FF loc_05FF: ; CODE XREF: 05FB 05FF 3E 02 LD A,02 ; row 2 0601 D3 DE OUT ($DE),A 0603 DB DC IN A,($DC) 0605 CB 67 BIT 4,A ; HOME CLR key 0607 20 02 JR NZ,loc_060B 0609 CB A1 RES 4,C ; bit 4 = button A 060B loc_060B: ; CODE XREF: 0607 060B 3E 03 LD A,03 ; row 3 060D D3 DE OUT ($DE),A 060F DB DC IN A,($DC) 0611 CB 67 BIT 4,A ; INS DEL key 0613 20 02 JR NZ,loc_0617 0615 CB A9 RES 5,C ; bit 5 = button B 0617 loc_0617: ; CODE XREF: 0613 0617 79 LD A,C 0618 32 0F C0 LD (byte_C00F),A 061B C9 RET ; --------------------------------------------------------------------------- 061C Player2Input: ; CODE XREF: 05C7 061C 3E 07 LD A,07 ; select input row 7 (joypads) 061E D3 DE OUT ($DE),A 0620 CD B4 05 CALL ReadPad2 0623 4F LD C,A ; C <- pad 2 bits 11BARLDU 0624 3E 01 LD A,01 ; row 1 0626 D3 DE OUT ($DE),A 0628 DB DC IN A,($DC) 062A CB 57 BIT 2,A ; S key 062C 20 02 JR NZ,loc_0630 062E CB 91 RES 2,C 0630 loc_0630: ; CODE XREF: 062C 0630 CB 5F BIT 3,A ; X key 0632 20 02 JR NZ,loc_0636 0634 CB 89 RES 1,C 0636 loc_0636: ; CODE XREF: 0632 0636 3E 02 LD A,02 ; row 2 0638 D3 DE OUT ($DE),A 063A DB DC IN A,($DC) 063C CB 4F BIT 1,A ; E key 063E 20 02 JR NZ,loc_0642 0640 CB 81 RES 0,C 0642 loc_0642: ; CODE XREF: 063E 0642 3E 03 LD A,03 ; row 3 0644 D3 DE OUT ($DE),A 0646 DB DC IN A,($DC) 0648 CB 57 BIT 2,A ; F key! 064A 20 02 JR NZ,loc_064E 064C CB 99 RES 3,C 064E loc_064E: ; CODE XREF: 064A 064E 3E 05 LD A,05 ; row 5 0650 D3 DE OUT ($DE),A 0652 DB DD IN A,($DD) 0654 CB 5F BIT 3,A ; N key 0656 20 02 JR NZ,loc_065A 0658 CB A9 RES 5,C 065A loc_065A: ; CODE XREF: 0656 065A 3E 06 LD A,06 ; row 6 065C D3 DE OUT ($DE),A 065E DB DD IN A,($DD) 0660 CB 57 BIT 2,A ; J Key 0662 20 02 JR NZ,loc_0666 0664 CB A1 RES 4,C 0666 loc_0666: ; CODE XREF: 0662 0666 79 LD A,C 0667 32 0F C0 LD (byte_C00F),A 066A C9 RET ; --------------------------------------------------------------------------- |
|
|
Posted: Thu Sep 19, 2019 2:47 am |
Ive been looking into this a bit too and its interesting the way its done. On a SC-3000, the controller ports are read directly from the keyboard PPI. On a SG-1000/MkIII the controller ports are read with logic. There is some address decoding logic that enables the controller ports during a read. Once a SK1100 keyboard gets plugged in, the PPI on the keyboard takes control and decides when the controller ports can be read instead. Its still using logic for the controller ports, and not the PPI like on the SG-3000, but the output enable signal for the controller logic comes from the PPI rather than the address decoding logic, as it would without the keyboard being plugged in. Based on that, if you plug a keyboard in, the PPI needs to be configured for the controller ports to be able to be read properly. This will be why they need to detect for it. |
|
|
Posted: Thu Sep 19, 2019 5:05 pm |
I can see now that it is important for software to test for the presence of a keyboard on the SG-1000. If it didn't then each time port A and B were read, the controller data would be returned, regardless of the last value written to port C. This would be disasterous in code like the Space Invaders snippet above which combines controller + keyboard input.
For the purposes of emulation, I think it will be enough to add a keyboard present boolean to the machine/PPI. If present then port C read will return the last value written to port C. If the keyboard is not present, it might make sense to return the complement of the last value written, so it is guaranteed not to be the same value that was written. EDIT: Just tried this and it works a treat. Thanks! |
|
|
Posted: Fri Sep 20, 2019 8:37 am |
The SF-7000 Users Manual has information about this
http://www.smspower.org/Scans/SF7000-Hardware-UsersManual From Page 196 http://www.smspower.org/Scans/SF7000-Hardware-UsersManual?gallerypage=196 |
|
|
Posted: Fri Sep 20, 2019 9:26 am |
Hmm, we need to OCR that for better searchability... | |