Not Rocket Science

PC Engine CD-ROM² BIOS Method offsets

The PC Engine CD-ROM² consists of a HuCard containing a BIOS, which interfaces with the actual CD-ROM drive and serves as a bare-bones operating system of sorts for CD-ROM games.

Like all HuCards, the System Card is mapped to the $E000-$FFFF memory range on startup (MPR#7 = $00), and developers should not change this when calling BIOS functions since the code assume that base address. The BIOS also assumes/requires that MPR#0 is $FF and MPR#1 is $F8 to map the I/O and Work RAM to the beginning of address space, which is standard anyway.

To keep the programming interface compatible between revisions of the System Card, it utilizes a jump table. For example, if a developer wants to call the cd_seek, they are supposed to always JSR to address $E00C, which consists of a JMP $xxyy call to jump to the actual body of the method. That way, if the actual location of the cd_seek method changes (because previous methods were refactored), game code still works.

In order to help with debugging (e.g., trying to figure out why Altered Beast only works with the 1.0 card), I've made a list of each BIOS method and it's actual location on the various system cards for the PC Engine and Turbografx-16.

I have the manual for the System Card 1.0, with the official names. The System Card 2.0 added 4 additional methods, marked new_1 through new_4. Neither System Card 2.1 nor 3.0 added any additional methods. I am not sure yet what these new methods are, I assume it's something to do with CD+G support, but have not verified this yet.

The Arcade Card is "just" a 3.0 card with more RAM on it, which is mapped through additional I/O registers - but the actual CD BIOS methods are unchanged from the regular 3.0 Super CD-ROM² card.

Aside: Something similar was done on the Amiga, where the only address a developer should ever hardcode is ExecBase. It's an elegant way to version the code, although there's a penalty on each and every BIOS call due to the extra layer of indirection. Thankfully the PC Engine's CPU was clocked very fast (for 6502 standards) and CD method calls were relatively infrequent.

Method Addresses across CD-ROM² System Cards

Method JSR 1.0 2.0 2.1 3.0 TG2.0 TG3.0
cd_boot $E000 $E0E7 $E0F3 $E0F3 $E0F3 $E0F3 $E0F3
cd_reset $E003 $E95C $E8E1 $E8E1 $E8E3 $E8FA $E8FC
cd_base $E006 $EC1C $EB8F $EB8F $EB8F $EBA8 $EBA8
cd_read $E009 $EC6D $EC05 $EC05 $EC05 $EC1E $EC1E
cd_seek $E00C $EE49 $EDCB $EDCB $EDCB $EDE4 $EDE4
cd_exec $E00F $EC57 $EBEC $EBEC $EBEC $EC05 $EC05
cd_play $E012 $EE96 $EE10 $EE10 $EE10 $EE29 $EE29
cd_search $E015 $EFB1 $EF34 $EF34 $EF34 $EF4D $EF4D
cd_pause $E018 $F01B $EF94 $EF94 $EF94 $EFAD $EFAD
cd_stat $E01B $F3A7 $F33D $F347 $F347 $F360 $F360
cd_subq $E01E $F047 $EFBF $EFBF $EFBF $EFD8 $EFD8
cd_dinfo $E021 $F081 $EFF1 $EFF1 $EFF1 $F00A $F00A
cd_contnts $E024 $F13A $F0A9 $F0A9 $F0A9 $F0C2 $F0C2
cd_subrd $E027 $F3B5 $F34A $F354 $F354 $F36D $F36D
cd_pcmrd $E02A $F3C5 $F35A $F364 $F364 $F37D $F37D
cd_fade $E02D $F3DA $F36F $F379 $F379 $F392 $F392
ad_reset $E030 $F3E0 $F375 $F37F $F37F $F398 $F398
ad_trans $E033 $F3F4 $F389 $F393 $F393 $F3AC $F3AC
ad_read $E036 $F467 $F3FD $F407 $F407 $F420 $F420
ad_write $E039 $F566 $F4CE $F4D8 $F4D8 $F4F1 $F4F1
ad_play $E03C $F662 $F5BC $F5C6 $F5C6 $F5DF $F5DF
ad_cplay $E03F $F6B1 $F615 $F61F $F61F $F638 $F638
ad_stop $E042 $F756 $F6B7 $F6C1 $F6C1 $F6DA $F6DA
ad_stat $E045 $F761 $F6D1 $F6DB $F6DB $F6F4 $F6F4
bm_format $E048 $F7A2 $F84E $F858 $F858 $F871 $F871
bm_free $E04B $F802 $F8AE $F8B8 $F8B8 $F8D1 $F8D1
bm_read $E04E $F827 $F8D9 $F8E3 $F8E3 $F8FC $F8FC
bm_write $E051 $F899 $F94B $F955 $F955 $F96E $F96E
bm_delete $E054 $F951 $FA10 $FA1A $FA1A $FA33 $FA33
bm_files $E057 $F9A9 $FA68 $FA72 $FA72 $FA8B $FA8B
ex_getver $E05A $F0BD $F02D $F02D $F02D $F046 $F046
ex_setvec $E05D $F0C4 $F034 $F034 $F034 $F04D $F04D
ex_getfnt $E060 $F1A3 $F122 $F124 $F124 $F13D $F13D
ex_joysns $E063 $E531 $E49A $E49A $E49A $E4B3 $E4B3
ex_joyrep $E066 $E171 $E175 $E175 $E175 $E18E $E18E
ex_scrsiz $E069 $E2FC $E267 $E267 $E267 $E280 $E280
ex_dotmod $E06C $E307 $E272 $E272 $E272 $E28B $E28B
ex_scrmod $E06F $E333 $E29D $E29D $E29D $E2B6 $E2B6
ex_imode $E072 $E418 $E382 $E382 $E382 $E39B $E39B
ex_vmode $E075 $E427 $E391 $E391 $E391 $E3AA $E3AA
ex_hmode $E078 $E43A $E3A4 $E3A4 $E3A4 $E3BD $E3BD
ex_vsync $E07B $E44B $E3B5 $E3B5 $E3B5 $E3CE $E3CE
ex_rcron $E07E $E45E $E3C7 $E3C7 $E3C7 $E3E0 $E3E0
ex_rcroff $E081 $E462 $E3CB $E3CB $E3CB $E3E4 $E3E4
ex_irqon $E084 $E466 $E3CF $E3CF $E3CF $E3E8 $E3E8
ex_irqoff $E087 $E46A $E3D3 $E3D3 $E3D3 $E3EC $E3EC
ex_bgon $E08A $E479 $E3E2 $E3E2 $E3E2 $E3FB $E3FB
ex_bgoff $E08D $E47C $E3E5 $E3E5 $E3E5 $E3FE $E3FE
ex_spron $E090 $E47F $E3E8 $E3E8 $E3E8 $E401 $E401
ex_sproff $E093 $E482 $E3EB $E3EB $E3EB $E404 $E404
ex_dspon $E096 $E485 $E3EE $E3EE $E3EE $E407 $E407
ex_dspoff $E099 $E48A $E3F3 $E3F3 $E3F3 $E40C $E40C
ex_dmamod $E09C $E48F $E3F8 $E3F8 $E3F8 $E411 $E411
ex_sprdma $E09F $E4A2 $E40B $E40B $E40B $E424 $E424
ex_satclr $E0A2 $E671 $E5DA $E5DA $E5DA $E5F3 $E5F3
ex_sprput $E0A5 $E6D3 $E63C $E63C $E63C $E655 $E655
ex_setrcr $E0A8 $E4B6 $E41F $E41F $E41F $E438 $E438
ex_setred $E0AB $E4C6 $E42F $E42F $E42F $E448 $E448
ex_setwrt $E0AE $E4DD $E446 $E446 $E446 $E45F $E45F
ex_setdma $E0B1 $E4F4 $E45D $E45D $E45D $E476 $E476
ex_binbcd $E0B4 $E6B8 $E621 $E621 $E621 $E63A $E63A
ex_bcdbin $E0B7 $E697 $E600 $E600 $E600 $E619 $E619
ex_rnd $E0BA $E707 $E67E $E67E $E67E $E697 $E697
ma_mul8u $E0BD $FD22 $FDBC $FDC6 $FDC6 $FDDF $FDDF
ma_mul8s $E0C0 $FCF2 $FDB5 $FDBF $FDBF $FDD8 $FDD8
ma_mul16u $E0C3 $FD3F $FDCA $FDD4 $FDD4 $FDED $FDED
ma_div16s $E0C6 $FD70 $FDD8 $FDE2 $FDE2 $FDFB $FDFB
ma_div16u $E0C9 $FDC3 $FDDF $FDE9 $FDE9 $FE02 $FE02
ma_sqrt $E0CC $FE0B $FDE6 $FDF0 $FDF0 $FE09 $FE09
ma_sin $E0CF $FE5C $FDF4 $FDFE $FDFE $FE17 $FE17
ma_cos $E0D2 $FE66 $FDED $FDF7 $FDF7 $FE10 $FE10
ma_atni $E0D5 $FE6E $FDFB $FE05 $FE05 $FE1E $FE1E
psg_bios $E0D8 $FF14 $FE02 $FE0C $FE0C $FE25 $FE25
grp_bios $E0DB $FF5B $FE4D $FE57 $FE57 $FE70 $FE70
ex_memopen $E0DE $FCCA $E175 $E175 $FE92 $E18E $FEAB
psg_driver $E0E1 $E759 $E6CF $E6CF $E6CF $E6E8 $E6E8
ex_colorcmd $E0E4 $E5A0 $E509 $E509 $E509 $E522 $E522
new_01 $E0E7 N/A $F726 $F730 $F730 $F749 $F749
new_02 $E0EA N/A $F762 $F76C $F76C $F785 $F785
new_03 $E0ED N/A $FDC3 $FDCD $FDCD $FDE6 $FDE6
new_04 $E0F0 N/A $FDD1 $FDDB $FDDB $FDF4 $FDF4
Post Tags
PC Engine