Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCI: Fixed KGetTime with SYSDATE subop in SCI0-LATE. #770

Merged
merged 1 commit into from
Jun 30, 2016

Conversation

OmerMor
Copy link
Contributor

@OmerMor OmerMor commented Jun 16, 2016

SSCI implementation of the SYSDATE subop of the GetTime kernel function was
changed between SCI0-LATE and SCI01: The base year used was changed from 1920 to
1980.
This subop is used in "Codename: Iceman" (Say "ask for date" to a passing girl
on the beach).

The Atari ST version of "Codename: Iceman" use the 1980 base year.
The Amiga version of "Codename: Iceman" appears to return the time instead of
date, with 0 for the YEAR part.

@bluegr
Copy link
Member

bluegr commented Jun 25, 2016

I tried the Amiga version of Iceman, and it also seems to return the date instead of the time, when you ask a girl for the date. Are you sure that this only applies to the DOS version?

@OmerMor
Copy link
Contributor Author

OmerMor commented Jun 25, 2016

Here's my version of Iceman on an emulated amiga (WinUAE):
iceman-amiga-date

@OmerMor
Copy link
Contributor Author

OmerMor commented Jun 25, 2016

The (decompiled) Amiga and DOS functions for displaying the "date" response are the same:

(procedure (localproc_0a1c &tmp temp0 temp1)
    (= temp1 (& (= temp0 (GetTime 3)) $001f))
    (proc255_4
        301
        22
        (& (>> temp0 $0005) $000f)
        (+ (if (< temp1 29) global142 else 0) temp1)
        (- (>> temp0 $0009) 60)
    )
)

The Atari ST one is different in how it calculates the displayed year:

(procedure (localproc_0a1c &tmp temp0 temp1)
    (= temp1 (& (= temp0 (GetTime 3)) $001f))
    (proc255_4
        301
        22
        (& (>> temp0 $0005) $000f)
        (+ (if (< temp1 29) global142 else 0) temp1)
        (+ (>> temp0 $0009) 1990)
    )
)

@bluegr
Copy link
Member

bluegr commented Jun 26, 2016

I've just tried the Amiga and DOS versions. The older base year seems to be 1940 (not 1920), and the newer 1980. The check you got for DOS should also be applied for the Amiga version.

So, here's the code that works for me:

case KGETTIME_DATE :
    {
        // SCI0 late: Year since 1940 (0 = 1940, 1 = 1941, etc)
        // SCI01 and newer: Year since 1980 (0 = 1980, 1 = 1981, etc)
        // Atari ST SCI0 late versions use the newer base year.
        int baseYear = 80;
        if (getSciVersion() == SCI_VERSION_0_LATE && g_sci->getPlatform() != Common::kPlatformAtariST) 
            baseYear = 40;
        retval = loc_time.tm_mday | ((loc_time.tm_mon + 1) << 5) | (((loc_time.tm_year - baseYear) & 0x7f) << 9);
        debugC(kDebugLevelTime, "GetTime(date) returns %d", retval);
        break;
    }

Does that look better?

@OmerMor
Copy link
Contributor Author

OmerMor commented Jun 26, 2016

No, according to the disassembly done by m_kiewitz, the older base year is 1920.

The kernel is calling DOS interrupt 21/AH=2Ah.
The year is returned in CX.

The newer (base 1980) kernel is doing the following:

seg032:03A7                 or      al, dl
seg032:03A9                 sub     cx, 1980
seg032:03AD                 shl     cx, 1
seg032:03AF                 or      ah, cl

The older (base 1920) kernel is doing the following:

seg000:9B4F                 shl     cx, 1
seg000:9B51                 or      ah, cl

The fidelity of the year part in this kernel function is 7 bits.
The older version does not subtract 1980 from CX, and only stores it in the result. Since it is 7 bit long, the value will be (YEAR % 0xF). For the years in the range [1920, 2047], the result will be in the range [0, 127]. So effectively, until 2047, the year part have a base value of 1920. After 2048 it will overflow and start from 0 again, but I don't think we need to worry about that in the code.

I do like your code comment - so I'll update mine accordingly.

SSCI implementation of the SYSDATE subop of the GetTime kernel function was
changed between SCI0-LATE and SCI01: The base year used was changed from 1920 to
1980.
This subop is used in "Codename: Iceman" (Say "ask for date" to a passing girl
on the beach).

The Atari ST version of "Codename: Iceman" use the 1980 base year.
The Amiga version of "Codename: Iceman" appears to return the time instead of
date, with 0 for the YEAR part.
@bluegr
Copy link
Member

bluegr commented Jun 30, 2016

Looks good!

I still disagree on the base year for ICEMAN. Try asking the girl for a date, you get "06/30/36" (for today's date). So, the base looks to be 40 instead of 20 for ICEMAN.

@bluegr bluegr closed this Jun 30, 2016
@bluegr bluegr reopened this Jun 30, 2016
@OmerMor
Copy link
Contributor Author

OmerMor commented Jun 30, 2016

The girl is not supposed to give you today's date. The game is futuristic and was supposed to be happening in 2010, as evident in this comic from InterAction magazine.

Since the game was out around 1990, they programmed her to give you the date 20 years in the future.

@bluegr
Copy link
Member

bluegr commented Jun 30, 2016

That makes sense, thanks!

Merging as-is

@bluegr bluegr merged commit a40e43f into scummvm:master Jun 30, 2016
@OmerMor
Copy link
Contributor Author

OmerMor commented Jun 30, 2016

Thanks!

@lskovlun
Copy link
Contributor

I believe the game is officially set in 2004.

@raziel-
Copy link
Contributor

raziel- commented Jul 1, 2016

The game's in-package "Tenth Anniversary" ad says "Terror in the Year 2000", but that could be a rough mentioning that the story is set in the "2000s"

@OmerMor
Copy link
Contributor Author

OmerMor commented Jul 1, 2016

I couldn't find any reference to the year 2004, including in the game's resources.
The hint book however says the game takes place in the year 2110:

Welcome to the U.S. Navy in the year 2110 with "Codename: Iceman".

I believe it's a typo for 2010.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants